Merge "Enforce array type hinting in OutputPage.php"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 1 Aug 2014 19:08:16 +0000 (19:08 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 1 Aug 2014 19:08:16 +0000 (19:08 +0000)
567 files changed:
CREDITS
RELEASE-NOTES-1.24
api.php
docs/export-0.9.xsd [new file with mode: 0644]
docs/export-demo.xml
docs/hooks.txt
docs/kss/Makefile
docs/kss/styleguide-template/index.html
docs/kss/styleguide-template/public/kss.less
includes/AjaxDispatcher.php
includes/AjaxResponse.php
includes/AutoLoader.php
includes/Block.php
includes/CategoryViewer.php
includes/Categoryfinder.php
includes/ChangeTags.php
includes/Collation.php
includes/Cookie.php
includes/DefaultSettings.php
includes/EditPage.php
includes/Export.php
includes/Fallback.php
includes/Feed.php
includes/FeedUtils.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/Licenses.php
includes/Linker.php
includes/MWTimestamp.php
includes/MediaWiki.php
includes/Message.php
includes/OutputPage.php
includes/Preferences.php
includes/PrefixSearch.php
includes/Revision.php
includes/Sanitizer.php
includes/Setup.php
includes/SiteStats.php
includes/Skin.php
includes/SkinTemplate.php
includes/SquidPurgeClient.php
includes/Status.php
includes/StubObject.php
includes/Title.php
includes/User.php
includes/UserArrayFromResult.php
includes/UserMailer.php
includes/WebRequest.php
includes/WebResponse.php
includes/WebStart.php
includes/Xml.php
includes/actions/CachedAction.php
includes/actions/CreditsAction.php
includes/actions/HistoryAction.php
includes/actions/RawAction.php
includes/actions/RollbackAction.php
includes/api/ApiDelete.php
includes/api/ApiEditPage.php
includes/api/ApiFormatBase.php
includes/api/ApiFormatJson.php
includes/api/ApiImageRotate.php
includes/api/ApiMain.php
includes/api/ApiParse.php
includes/api/ApiQuery.php
includes/api/ApiQueryImageInfo.php
includes/api/ApiQueryLogEvents.php
includes/api/ApiQueryRecentChanges.php
includes/api/ApiRollback.php
includes/api/ApiUndelete.php
includes/cache/CacheDependency.php
includes/cache/CacheHelper.php
includes/cache/LocalisationCache.php
includes/cache/MessageCache.php
includes/changes/EnhancedChangesList.php
includes/changes/RecentChange.php
includes/clientpool/RedisConnectionPool.php
includes/config/ConfigFactory.php
includes/config/GlobalVarConfig.php
includes/content/ContentHandler.php
includes/content/CssContentHandler.php
includes/content/JavaScriptContentHandler.php
includes/content/MessageContent.php
includes/content/TextContent.php
includes/content/WikitextContent.php
includes/context/DerivativeContext.php
includes/db/Database.php
includes/db/DatabaseMssql.php
includes/db/DatabaseMysqlBase.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/ORMTable.php
includes/deferred/DataUpdate.php
includes/deferred/DeferredUpdates.php
includes/deferred/LinksUpdate.php
includes/deferred/SqlDataUpdate.php
includes/deferred/ViewCountUpdate.php
includes/diff/DifferenceEngine.php
includes/exception/BadTitleError.php
includes/exception/ErrorPageError.php
includes/externalstore/ExternalStore.php
includes/filebackend/FSFile.php
includes/filebackend/FSFileBackend.php
includes/filebackend/FileBackendStore.php
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/HTMLForm.php
includes/htmlform/HTMLFormField.php
includes/installer/CliInstaller.php
includes/installer/Installer.php
includes/installer/WebInstaller.php
includes/installer/WebInstallerPage.php
includes/installer/i18n/be-tarask.json
includes/installer/i18n/bn.json
includes/installer/i18n/br.json
includes/installer/i18n/bto.json
includes/installer/i18n/ca.json
includes/installer/i18n/ce.json
includes/installer/i18n/cs.json
includes/installer/i18n/de.json
includes/installer/i18n/en.json
includes/installer/i18n/es.json
includes/installer/i18n/fa.json
includes/installer/i18n/fr.json
includes/installer/i18n/he.json
includes/installer/i18n/ja.json
includes/installer/i18n/ko.json
includes/installer/i18n/mk.json
includes/installer/i18n/pl.json
includes/installer/i18n/qqq.json
includes/installer/i18n/ru.json
includes/installer/i18n/sco.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/DuplicateJob.php
includes/jobqueue/jobs/NullJob.php
includes/jobqueue/jobs/UploadFromUrlJob.php
includes/libs/CSSJanus.php
includes/logging/LogFormatter.php
includes/logging/LogPage.php
includes/media/Bitmap.php
includes/media/BitmapMetadataHandler.php
includes/media/DjVu.php
includes/media/DjVuImage.php
includes/media/Exif.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/XCF.php
includes/media/XMP.php
includes/objectcache/BagOStuff.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/parser/DateFormatter.php
includes/parser/LinkHolderArray.php
includes/parser/Parser.php
includes/parser/ParserCache.php
includes/parser/ParserOptions.php
includes/parser/ParserOutput.php
includes/parser/Preprocessor_Hash.php
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/profiler/Profiler.php
includes/profiler/ProfilerMwprof.php
includes/profiler/ProfilerStandard.php
includes/rcfeed/RCFeedEngine.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/resourceloader/ResourceLoaderFilePath.php [new file with mode: 0644]
includes/resourceloader/ResourceLoaderLanguageNamesModule.php
includes/resourceloader/ResourceLoaderModule.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/revisiondelete/RevisionDeleter.php
includes/search/SearchHighlighter.php
includes/search/SearchResult.php
includes/site/Site.php
includes/site/SiteList.php
includes/site/SiteSQLStore.php
includes/specialpage/ChangesListSpecialPage.php
includes/specialpage/QueryPage.php
includes/specialpage/SpecialPage.php
includes/specialpage/SpecialPageFactory.php
includes/specials/SpecialAllPages.php
includes/specials/SpecialBlock.php
includes/specials/SpecialCategories.php
includes/specials/SpecialChangePassword.php
includes/specials/SpecialContributions.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/SpecialJavaScriptTest.php
includes/specials/SpecialLinkSearch.php
includes/specials/SpecialListgrouprights.php
includes/specials/SpecialListusers.php
includes/specials/SpecialLog.php
includes/specials/SpecialMergeHistory.php
includes/specials/SpecialMovepage.php
includes/specials/SpecialMyLanguage.php [new file with mode: 0644]
includes/specials/SpecialPageLanguage.php
includes/specials/SpecialPagesWithProp.php
includes/specials/SpecialRandomInCategory.php
includes/specials/SpecialRandompage.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialRecentchangeslinked.php
includes/specials/SpecialRedirect.php
includes/specials/SpecialRevisiondelete.php
includes/specials/SpecialRunJobs.php
includes/specials/SpecialSearch.php
includes/specials/SpecialUndelete.php
includes/specials/SpecialUpload.php
includes/specials/SpecialUploadStash.php
includes/specials/SpecialUserlogin.php
includes/specials/SpecialUserrights.php
includes/specials/SpecialVersion.php
includes/specials/SpecialWatchlist.php
includes/specials/SpecialWhatlinkshere.php
includes/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
languages/Language.php
languages/classes/LanguageIu.php
languages/classes/LanguageKk.php
languages/classes/LanguageKu.php
languages/classes/LanguageShi.php
languages/classes/LanguageSr.php
languages/i18n/af.json
languages/i18n/ar.json
languages/i18n/az.json
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bn.json
languages/i18n/br.json
languages/i18n/bs.json
languages/i18n/ca.json
languages/i18n/cdo.json
languages/i18n/ce.json
languages/i18n/cs.json
languages/i18n/de.json
languages/i18n/egl.json
languages/i18n/en.json
languages/i18n/eo.json
languages/i18n/es.json
languages/i18n/et.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/gan-hant.json
languages/i18n/gl.json
languages/i18n/hak.json
languages/i18n/he.json
languages/i18n/hr.json
languages/i18n/ia.json
languages/i18n/ilo.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/kk-cyrl.json
languages/i18n/ko.json
languages/i18n/ku-latn.json
languages/i18n/lb.json
languages/i18n/lv.json
languages/i18n/lzh.json
languages/i18n/mk.json
languages/i18n/ms.json
languages/i18n/mzn.json
languages/i18n/nan.json
languages/i18n/nb.json
languages/i18n/nds-nl.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/pl.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ro.json
languages/i18n/ru.json
languages/i18n/sc.json
languages/i18n/sco.json
languages/i18n/sl.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/sv.json
languages/i18n/szl.json
languages/i18n/ta.json
languages/i18n/th.json
languages/i18n/tr.json
languages/i18n/uk.json
languages/i18n/vi.json
languages/i18n/wuu.json
languages/i18n/yi.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesEn.php
languages/messages/MessagesFrp.php
maintenance/deleteEqualMessages.php
maintenance/edit.php
maintenance/eraseArchivedFile.php
maintenance/fixDoubleRedirects.php
maintenance/generateJsonI18n.php
maintenance/importDump.php
maintenance/install.php
maintenance/purgeChangedPages.php
maintenance/resources/update-oojs.sh
maintenance/runJobs.php
maintenance/wrapOldPasswords.php [new file with mode: 0644]
resources/Resources.php
resources/lib/jquery/jquery.cookie.js
resources/lib/oojs-ui/i18n/ca.json
resources/lib/oojs-ui/i18n/en.json
resources/lib/oojs-ui/i18n/ms.json
resources/lib/oojs-ui/i18n/nb.json
resources/lib/oojs-ui/i18n/sl.json
resources/lib/oojs-ui/i18n/tr.json
resources/lib/oojs-ui/images/anchor.svg
resources/lib/oojs-ui/images/icons/accept.svg
resources/lib/oojs-ui/images/icons/add-item.svg
resources/lib/oojs-ui/images/icons/advanced.svg
resources/lib/oojs-ui/images/icons/alert.svg
resources/lib/oojs-ui/images/icons/arched-arrow-ltr.svg
resources/lib/oojs-ui/images/icons/arched-arrow-rtl.svg
resources/lib/oojs-ui/images/icons/clear.svg
resources/lib/oojs-ui/images/icons/close.svg
resources/lib/oojs-ui/images/icons/collapse.svg
resources/lib/oojs-ui/images/icons/comment.svg
resources/lib/oojs-ui/images/icons/expand.svg
resources/lib/oojs-ui/images/icons/help.svg
resources/lib/oojs-ui/images/icons/history.svg
resources/lib/oojs-ui/images/icons/info.svg
resources/lib/oojs-ui/images/icons/link.svg
resources/lib/oojs-ui/images/icons/menu.svg
resources/lib/oojs-ui/images/icons/move-ltr.svg
resources/lib/oojs-ui/images/icons/move-rtl.svg
resources/lib/oojs-ui/images/icons/picture.svg
resources/lib/oojs-ui/images/icons/remove-item.svg
resources/lib/oojs-ui/images/icons/remove.svg
resources/lib/oojs-ui/images/icons/search.svg
resources/lib/oojs-ui/images/icons/settings.svg
resources/lib/oojs-ui/images/icons/tag.svg
resources/lib/oojs-ui/images/icons/window.svg
resources/lib/oojs-ui/images/indicators/alert.svg
resources/lib/oojs-ui/images/indicators/arrow-down.svg
resources/lib/oojs-ui/images/indicators/arrow-up.svg
resources/lib/oojs-ui/oojs-ui-agora.css
resources/lib/oojs-ui/oojs-ui-apex.css
resources/lib/oojs-ui/oojs-ui.js
resources/lib/oojs-ui/oojs-ui.svg.css
resources/lib/oojs/oojs.jquery.js [new file with mode: 0644]
resources/lib/oojs/oojs.js [deleted file]
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.menu.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.spinner.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.ui-themes/vector/jquery.ui.tooltip.css [deleted file]
resources/src/jquery/jquery.textSelection.js
resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js
resources/src/mediawiki.less/mediawiki.ui/mixins.less
resources/src/mediawiki.page/mediawiki.page.image.pagination.js
resources/src/mediawiki.skinning/content.parsoid.less
resources/src/mediawiki.special/mediawiki.special.userlogin.common.js
resources/src/mediawiki.ui/components/anchors.less [new file with mode: 0644]
resources/src/mediawiki.ui/components/buttons.less
resources/src/mediawiki.ui/components/checkbox.less [new file with mode: 0644]
resources/src/mediawiki.ui/components/forms.less
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/default.less
skins/MonoBook/i18n/et.json
skins/MonoBook/i18n/he.json
skins/MonoBook/main.css
skins/Vector/Vector.php
skins/Vector/VectorTemplate.php
skins/Vector/components/common.less
skins/Vector/components/notifications.less [deleted file]
skins/Vector/i18n/bs.json
skins/Vector/i18n/bto.json [new file with mode: 0644]
skins/Vector/i18n/et.json
skins/Vector/i18n/he.json
skins/Vector/i18n/hy.json
skins/Vector/i18n/sl.json
skins/Vector/skinStyles/jquery.tipsy.less [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/close.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/titlebar-fade.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-anim_basic_16x16.gif [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-bg_flat_15_cd0a0a_40x100.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-bg_flat_70_000000_40x100.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-soft_100_ffffff_1x100.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-soft_25_ffef8f_1x100.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-bg_inset-hard_100_f0f0f0_1x100.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-icons_2694e8_256x240.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-icons_2e83ff_256x240.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-icons_3d80b3_256x240.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-icons_666666_256x240.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-icons_72a7cf_256x240.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/images/ui-icons_ffffff_256x240.png [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/jquery.ui.accordion.css [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/jquery.ui.autocomplete.css [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/jquery.ui.button.css [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/jquery.ui.core.css [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/jquery.ui.datepicker.css [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/jquery.ui.dialog.css [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/jquery.ui.progressbar.css [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/jquery.ui.resizable.css [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/jquery.ui.selectable.css [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/jquery.ui.slider.css [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/jquery.ui.tabs.css [new file with mode: 0644]
skins/Vector/skinStyles/jquery.ui/jquery.ui.theme.css [new file with mode: 0644]
skins/Vector/skinStyles/mediawiki.notification.less [new file with mode: 0644]
skins/Vector/skinStyles/mediawiki.special.less [new file with mode: 0644]
skins/Vector/skinStyles/mediawiki.special.preferences.less [new file with mode: 0644]
skins/Vector/special.less [deleted file]
skins/Vector/special.preferences.less [deleted file]
skins/common/commonElements.css
skins/common/shared.css
tests/TestsAutoLoader.php
tests/browser/README.mediawiki
tests/parser/parserTest.inc
tests/parserTests.php
tests/phpunit/MediaWikiPHPUnitTestListener.php
tests/phpunit/MediaWikiPasswordTestCase.php [new file with mode: 0644]
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/EditPageTest.php
tests/phpunit/includes/GlobalFunctions/GlobalTest.php
tests/phpunit/includes/GlobalFunctions/wfBCP47Test.php
tests/phpunit/includes/HtmlTest.php
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/SanitizerValidateEmailTest.php
tests/phpunit/includes/StatusTest.php
tests/phpunit/includes/TitleMethodsTest.php
tests/phpunit/includes/TitleTest.php
tests/phpunit/includes/api/ApiEditPageTest.php
tests/phpunit/includes/api/ApiTestCase.php
tests/phpunit/includes/api/format/ApiFormatJsonTest.php
tests/phpunit/includes/api/query/ApiQueryContinueTestBase.php
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/content/ContentHandlerTest.php
tests/phpunit/includes/exception/MWExceptionHandlerTest.php
tests/phpunit/includes/filerepo/RepoGroupTest.php
tests/phpunit/includes/libs/CSSJanusTest.php
tests/phpunit/includes/media/DjVuTest.php
tests/phpunit/includes/parser/NewParserTest.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/Pbkdf2PasswordTest.php [new file with mode: 0644]
tests/phpunit/includes/poolcounter/PoolCounterTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderModuleTest.php
tests/phpunit/includes/site/TestSites.php
tests/phpunit/includes/specials/SpecialListFilesTest.php
tests/phpunit/includes/specials/SpecialMyLanguageTest.php [new file with mode: 0644]
tests/phpunit/includes/title/MediaWikiPageLinkRendererTest.php
tests/phpunit/maintenance/DumpTestCase.php
tests/phpunit/maintenance/MaintenanceTest.php
tests/phpunit/maintenance/fetchTextTest.php
tests/phpunit/structure/ResourcesTest.php
tests/phpunit/suites/UploadFromUrlTestSuite.php
tests/qunit/suites/resources/jquery/jquery.textSelection.test.js
tests/testHelpers.inc
thumb.php

diff --git a/CREDITS b/CREDITS
index fde6b78..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
index 37ddc66..ec4bc0f 100644 (file)
@@ -15,6 +15,8 @@ production.
 * 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,
@@ -40,6 +42,9 @@ production.
   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.
 
 === New features in 1.24 ===
 * Added a new hook, "WhatLinksHereProps", to allow extensions to annotate
@@ -118,17 +123,24 @@ production.
 * (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.2.0.
+* 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).
-* Added a new hook, "OutputPageScriptsForBottomQueue", to add modules to the
-  bottom queue that should be requested in a dedicated <script> request.
 * (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) Links of the form [[localInterwikiPrefix:languageCode:pageTitle]],
   where localInterwikiPrefix is a member of the $wgLocalInterwikis array, will
   no longer be displayed in the sidebar when $wgInterwikiMagic is true.
+* 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 fixes in 1.24 ===
 * (bug 49116) Footer copyright notice is now always displayed in user language
@@ -156,6 +168,8 @@ production.
   for future updates. Because it's doing so heuristically, it may fail or drop
   wrong constraints.
 * (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.
 
 === Web API changes in 1.24 ===
 * action=parse API now supports prop=modules, which provides the list of
@@ -269,6 +283,14 @@ changes to languages because of Bugzilla reports.
 * 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)
 
 ==== Renamed classes ====
 * CLDRPluralRuleConverter_Expression to CLDRPluralRuleConverterExpression
@@ -315,6 +337,8 @@ changes to languages because of Bugzilla reports.
 * 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 e8a911e..2a6a095 100644 (file)
--- a/api.php
+++ b/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/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 3ee1221..25f5ad8 100644 (file)
@@ -1871,14 +1871,6 @@ $categories: associative array, keys are category names, values are category
 $links: array, intended to hold the result. Must be an associative array with
   category types as keys and arrays of HTML links as values.
 
-'OutputPageScriptsForBottomQueue': Allows adding modules to the bottom queue
-that should be requested in a dedicated <script> request. In most cases you'll
-want to use OutputPage::addModules instead (from another hook) which allows
-ResourceLoader to better combine requests and allows the module load requests
-to be cached better. Typically you'd only use this for user-specific modules.
-$out: OutputPage instance
-&$modules: Array of modules names to add to the bottom queue
-
 'PageContentInsertComplete': After a new article is created.
 $wikiPage: WikiPage created
 $user: User creating the article
@@ -2788,26 +2780,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
index 374bab2..7d2ee3b 100644 (file)
@@ -6,7 +6,7 @@ kss: nodecheck
 # 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)
+       @curl -sG "${MEDIAWIKI_LOAD_URL}?modules=mediawiki.ui.anchor|mediawiki.ui.checkbox|mediawiki.ui.input|mediawiki.legacy.shared|mediawiki.legacy.commonPrint|mediawiki.ui|mediawiki.ui.button&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)
 
index cb95197..b6036b2 100644 (file)
@@ -2,61 +2,68 @@
 <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 class="content">
+                       <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></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>
+                                               {{/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}}
+                               </section>
+                               {{/eachSection}}
+                       {{/if}}
+               </article>
+       </div>
 </div></body>
 </html>
index 431303d..9e850a3 100644 (file)
-header {
-       padding: .8em 16px 0;
+body {
+       margin: 0;
+       padding: 0;
+       padding-top: 3px;
+       padding-bottom: 40px;
+
+       // FIXME: Remove when typography module in mediawiki-ui
+       font-family: "Nimbus Sans L", "Liberation Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
 }
 
-nav {
-       float: left;
-       width: 200px;
+.content.kss-no-margin {
+       margin: 0;
 }
 
-article {
-       margin-left: 250px;
+.container {
+       width: 960px;
+       margin: 0 auto;
+       display: -webkit-flex;
+       display: flex;
+
 }
 
-.content.kss-no-margin {
+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;
+               }
+       }
 }
 
-// FIXME: Remove when typography module in mediawiki-ui
-body {
-       font-family: "Nimbus Sans L", "Liberation Sans", "Helvetica Neue", "Helvetica", "Arial", sans-serif;
+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;
+                               }
+                       }
+               }
+       }
 }
-h1,h2,h3,h4,h5 {
-       font-family: "DejaVu Serif", Georgia, serif;
+
+article {
+       -webkit-flex: 1;
+       flex: 1;
+       margin-left: 30px;
+
+       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;
+                       width: 338px;
+                       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;
+                       min-width: 360px;
+               }
+       }
+}
+
+@media (max-width: 960px) {
+       .container {
+               width: 100%;
+       }
+
+       nav {
+               display: none;
+       }
+
+       article {
+               .example {
+                       blockquote {
+                               margin-top: 20px;
+                       }
+               }
+       }
 }
index c9ca128..dde8467 100644 (file)
@@ -55,7 +55,7 @@ class AjaxDispatcher {
 
                $this->mode = "";
 
-               if ( ! empty( $_GET["rs"] ) ) {
+               if ( !empty( $_GET["rs"] ) ) {
                        $this->mode = "get";
                }
 
@@ -66,7 +66,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 +74,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();
@@ -105,7 +105,7 @@ class AjaxDispatcher {
 
                wfProfileIn( __METHOD__ );
 
-               if ( ! in_array( $this->func_name, $wgAjaxExportList ) ) {
+               if ( !in_array( $this->func_name, $wgAjaxExportList ) ) {
                        wfDebug( __METHOD__ . ' Bad Request for unknown function ' . $this->func_name . "\n" );
 
                        wfHttpError(
index a3808a5..41cbd24 100644 (file)
@@ -132,7 +132,7 @@ class AjaxResponse {
         * @param string $text
         */
        function addText( $text ) {
-               if ( ! $this->mDisabled && $text ) {
+               if ( !$this->mDisabled && $text ) {
                        $this->mText .= $text;
                }
        }
@@ -141,7 +141,7 @@ class AjaxResponse {
         * Output text
         */
        function printText() {
-               if ( ! $this->mDisabled ) {
+               if ( !$this->mDisabled ) {
                        print $this->mText;
                }
        }
index 046a0df..9fa0c13 100644 (file)
@@ -130,7 +130,6 @@ $wgAutoloadLocalClasses = array(
        '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',
@@ -165,7 +164,6 @@ $wgAutoloadLocalClasses = array(
        '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',
@@ -194,7 +192,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
@@ -640,6 +637,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
@@ -829,6 +827,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',
@@ -858,6 +869,7 @@ $wgAutoloadLocalClasses = array(
        'ResourceLoaderContext' => 'includes/resourceloader/ResourceLoaderContext.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',
@@ -1011,6 +1023,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',
@@ -1188,7 +1201,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 aaabec9..45bae28 100644 (file)
@@ -1104,13 +1104,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 $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 ) ) {
index d6755c2..22eb3d1 100644 (file)
@@ -54,6 +54,9 @@ class CategoryViewer extends ContextSource {
        /** @var array */
        protected $nextPage;
 
+       /** @var array */
+       protected $prevPage;
+
        /** @var array */
        protected $flip;
 
@@ -288,6 +291,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 +353,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 +470,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 )
                ) {
index b9cbc9a..a5415af 100644 (file)
@@ -61,7 +61,7 @@ class Categoryfinder {
        /** @var array */
        protected $name2id = array();
 
-       /** @var  "AND" or "OR" */
+       /** @var string "AND" or "OR" */
        protected $mode;
 
        /** @var DatabaseBase Read-DB slave */
@@ -96,7 +96,7 @@ class Categoryfinder {
        /**
         * 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)
+        * @return array Array of page_ids (those given to seed() that match the conditions)
         */
        function run() {
                $this->dbr = wfGetDB( DB_SLAVE );
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.
index bcb0a56..1c2c2db 100644 (file)
@@ -162,7 +162,7 @@ class IcuCollation extends Collation {
        /** @var Collator */
        private $mainCollator;
 
-       /** @var  */
+       /** @var string */
        private $locale;
 
        /** @var Language */
@@ -367,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'] )
index b8d34e2..8b5906a 100644 (file)
@@ -90,13 +90,15 @@ 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 86b7533..dea6e71 100644 (file)
@@ -2960,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 = 'vector';
 
 /**
- * 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
@@ -3190,6 +3193,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
@@ -4016,6 +4124,7 @@ $wgActiveUserDays = 30;
 
 /**
  * For compatibility with old installations set to false
+ * @deprecated since 1.24 will be removed in future
  */
 $wgPasswordSalt = true;
 
@@ -4032,6 +4141,65 @@ $wgMinimalPasswordLength = 1;
  */
 $wgInvalidPasswordReset = true;
 
+/**
+ * Default password type to use when hashing user passwords
+ *
+ * @since 1.24
+ */
+$wgPasswordDefault = 'B';
+
+/**
+ * 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
@@ -4126,6 +4294,7 @@ $wgDefaultUserOptions = array(
        'watchlisthideown' => 0,
        'watchlisthidepatrolled' => 0,
        'watchmoves' => 0,
+       'watchrollback' => 0,
        'wllimit' => 250,
        'useeditwarning' => 1,
        'prefershttps' => 1,
@@ -5000,6 +5169,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.
  *
@@ -6049,13 +6225,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();
 
@@ -6884,12 +7059,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;
 
@@ -7085,12 +7260,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.
index 9d512ab..6454cfa 100644 (file)
@@ -99,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;
 
@@ -244,6 +244,12 @@ class EditPage {
        /** @var bool */
        protected $allowBlankSummary = false;
 
+       /** @var bool */
+       protected $blankArticle = false;
+
+       /** @var bool */
+       protected $allowBlankArticle = false;
+
        /** @var string */
        protected $autoSumm = '';
 
@@ -411,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 ||
@@ -633,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?
         *
@@ -710,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 );
@@ -850,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" );
@@ -970,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
         *
@@ -1180,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
         *
@@ -1205,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.
@@ -1321,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();
@@ -1343,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;
@@ -1363,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;
@@ -1390,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:
@@ -1425,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;
@@ -1767,7 +1696,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;
@@ -2015,28 +1946,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
@@ -2314,7 +2223,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 ) {
@@ -2346,7 +2255,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.
         */
@@ -2517,10 +2426,16 @@ class EditPage {
 
                $wgOut->addHTML( $this->editFormTextBeforeContent );
 
-               if ( !$this->isCssJsSubpage && $showToolbar && $wgUser->getOption( 'showtoolbar' ) ) {
+               if ( $this->contentModel === CONTENT_MODEL_WIKITEXT &&
+                       $showToolbar && $wgUser->getOption( 'showtoolbar' ) )
+               {
                        $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
@@ -2590,7 +2505,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 );
@@ -2649,6 +2564,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 );
                        }
@@ -2836,7 +2755,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
@@ -2867,7 +2786,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
@@ -3887,40 +3806,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 e57fe7f..43dfd17 100644 (file)
@@ -69,7 +69,7 @@ class WikiExporter {
         * @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
         */
index c4b22f5..8e7f4b7 100644 (file)
@@ -152,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..58f3ebd 100644 (file)
@@ -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 ) {
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 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 fe12a07..4c2b772 100644 (file)
@@ -176,21 +176,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
  *
@@ -209,27 +194,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.
@@ -246,7 +210,7 @@ function wfArrayMerge( $array1 /*...*/ ) {
  *             array( 'y' )
  *     )
  *
- * @param array [$array1,...]
+ * @param array $array1,...
  * @return array
  */
 function wfMergeErrorArrays( /*...*/ ) {
@@ -1179,7 +1143,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;
@@ -1438,7 +1402,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
@@ -1459,7 +1423,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
@@ -1479,7 +1443,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
@@ -1664,7 +1628,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 ) {
@@ -1685,7 +1649,7 @@ function wfMsgHtml( $key ) {
  * @deprecated since 1.18
  *
  * @param string $key
- * @param string [$args,...] Parameters
+ * @param string $args,... Parameters
  * @return string
  */
 function wfMsgWikiHtml( $key ) {
@@ -1807,19 +1771,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
@@ -1873,7 +1824,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 );
 }
@@ -2116,16 +2067,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
@@ -2276,7 +2217,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 = '*/*' ) {
@@ -2701,7 +2642,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( /*...*/ ) {
@@ -2785,7 +2726,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.
@@ -2834,6 +2777,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;
@@ -3020,7 +2972,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.
@@ -3468,7 +3420,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 (
@@ -3574,7 +3526,7 @@ function wfGetPrecompiledData( $name ) {
 /**
  * Get a cache key
  *
- * @param string [$args,...]
+ * @param string $args,...
  * @return string
  */
 function wfMemcKey( /*...*/ ) {
@@ -3591,7 +3543,7 @@ function wfMemcKey( /*...*/ ) {
  *
  * @param string $db
  * @param string $prefix
- * @param string [$args,...]
+ * @param string $args,...
  * @return string
  */
 function wfForeignMemcKey( $db, $prefix /*...*/ ) {
@@ -3663,7 +3615,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 ) {
@@ -3683,7 +3635,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
@@ -3750,7 +3702,7 @@ function wfScript( $script = 'index' ) {
 /**
  * Get the script URL.
  *
- * @return string script URL
+ * @return string Script URL
  */
 function wfGetScriptUrl() {
        if ( isset( $_SERVER['SCRIPT_NAME'] ) ) {
@@ -3800,6 +3752,7 @@ function wfGetNull() {
  * @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( $ifWritesSince = false, $wiki = false, $cluster = false ) {
        // B/C: first argument used to be "max seconds of lag"; ignore such values
@@ -3815,19 +3768,21 @@ function wfWaitForSlaves( $ifWritesSince = false, $wiki = false, $cluster = fals
        // Prevents permission error when getting master position
        if ( $lb->getServerCount() > 1 ) {
                if ( $ifWritesSince && !$lb->hasMasterConnection() ) {
-                       return; // assume no writes done
+                       return true; // assume no writes done
                }
                $dbw = $lb->getConnection( DB_MASTER, array(), $wiki );
                if ( $ifWritesSince && $dbw->lastDoneWrites() < $ifWritesSince ) {
-                       return; // no writes since the last wait
+                       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;
 }
 
 /**
@@ -4031,7 +3986,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..d2be9e9 100644 (file)
@@ -202,7 +202,7 @@ class HistoryBlobStub {
        /** @var string */
        public $mHash;
 
-       /** @var  */
+       /** @var string */
        public $mRef;
 
        /**
@@ -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 dbabbae..ce439cb 100644 (file)
@@ -114,7 +114,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*
@@ -414,7 +414,7 @@ class Html {
         *   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
+        * @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)
         */
@@ -654,6 +654,64 @@ class Html {
                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
+        */
+       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
+        */
+       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
+        */
+       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
         *
index ebced70..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__ );
@@ -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..1eb8ca5 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,
index 6aab157..e6b5dc2 100644 (file)
@@ -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 );
@@ -533,7 +533,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;
                }
@@ -1050,30 +1050,6 @@ 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
@@ -1503,6 +1479,7 @@ class WikiRevision {
                $linkCache->clear();
 
                $page = WikiPage::factory( $this->title );
+               $page->loadPageData( 'fromdbmaster' );
                if ( !$page->exists() ) {
                        # must create the page...
                        $pageId = $page->insertOn( $dbw );
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 1991694..9f578a9 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
  */
@@ -272,7 +272,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
         */
@@ -937,7 +937,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__ );
index ad3228d..bc59588 100644 (file)
@@ -401,7 +401,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 +415,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 a8bafa3..1b014f6 100644 (file)
@@ -38,7 +38,9 @@ class MediaWiki {
         */
        public function request( WebRequest $x = null ) {
                $old = $this->context->getRequest();
-               $this->context->setRequest( $x );
+               if ( $x ) {
+                       $this->context->setRequest( $x );
+               }
                return $old;
        }
 
@@ -48,7 +50,9 @@ class MediaWiki {
         */
        public function output( OutputPage $x = null ) {
                $old = $this->context->getOutput();
-               $this->context->setOutput( $x );
+               if ( $x ) {
+                       $this->context->setOutput( $x );
+               }
                return $old;
        }
 
@@ -198,7 +202,9 @@ class MediaWiki {
                // 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 );
+               $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
@@ -558,7 +564,7 @@ class MediaWiki {
                                        // 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
+                                       // @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" );
                                }
@@ -660,9 +666,9 @@ class MediaWiki {
                }
 
                if ( !$wgRunJobsAsync ) {
-                       // If running jobs asynchronously has been disabled, run the job here
-                       // while the user waits
-                       SpecialRunJobs::executeJobs( $n );
+                       // Fall back to running the job here while the user waits
+                       $runner = new JobRunner();
+                       $runner->run( array( 'maxJobs'  => $n ) );
                        return;
                }
 
@@ -695,7 +701,8 @@ class MediaWiki {
                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 );
+                       $runner = new JobRunner();
+                       $runner->run( array( 'maxJobs'  => $n ) );
                        return;
                }
 
index 950bcd5..931a3f9 100644 (file)
@@ -291,7 +291,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 +308,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 +332,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 +355,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 +377,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 +399,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 +421,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 +443,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 +465,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 +487,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
index 0c49b72..85d101f 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 = '';
@@ -355,8 +355,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,7 +367,7 @@ 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( array $linkarr ) {
                array_push( $this->mLinktags, $linkarr );
@@ -376,7 +376,7 @@ class OutputPage extends ContextSource {
        /**
         * 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
         */
@@ -412,7 +412,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 +421,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,9 +442,9 @@ 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;
@@ -484,7 +484,7 @@ 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
         */
@@ -647,8 +647,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 +667,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;
@@ -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 ) {
@@ -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,7 +1101,7 @@ 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 ) {
@@ -1121,7 +1121,7 @@ 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 ) {
@@ -1142,7 +1142,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;
@@ -1235,7 +1235,7 @@ 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( array $categories ) {
                global $wgContLang;
@@ -1266,11 +1266,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 +1284,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,7 +1301,7 @@ 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( array $categories ) {
                $this->mCategoryLinks = array();
@@ -1640,6 +1638,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 ) {
@@ -1852,7 +1852,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 +1967,16 @@ class OutputPage extends ContextSource {
                $this->mPreventClickjacking = false;
        }
 
+       /**
+        * Get the prevent-clickjacking flag
+        *
+        * @since 1.24
+        * @return boolean
+        */
+       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
@@ -2174,7 +2184,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 ) {
@@ -2195,8 +2205,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
         */
@@ -2249,8 +2259,8 @@ 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( array $errors, $action = null ) {
                // For some action (read, edit, create and upload), display a "login to do this action"
@@ -2334,7 +2344,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 ) {
@@ -2725,6 +2735,8 @@ $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;
@@ -2895,7 +2907,7 @@ $templates
 
                // Startup - this will immediately load jquery and mediawiki modules
                $links = array();
-               $links[] = $this->makeResourceLoaderLink( 'startup', ResourceLoaderModule::TYPE_SCRIPTS, /* $useESI =  */ true );
+               $links[] = $this->makeResourceLoaderLink( 'startup', ResourceLoaderModule::TYPE_SCRIPTS, true );
 
                // Load config before anything else
                $links[] = Html::inlineScript(
@@ -3017,14 +3029,6 @@ $templates
                        /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
                );
 
-               $modules = array();
-               wfRunHooks( 'OutputPageScriptsForBottomQueue', array( $this, &$modules ) );
-               if ( $modules ) {
-                       $links[] = $this->makeResourceLoaderLink( $modules, ResourceLoaderModule::TYPE_COMBINED,
-                               /* $useESI = */ false, /* $extraQuery = */ array(), /* $loadCall = */ $inHead
-                       );
-               }
-
                return self::getHtmlFromLoaderLinks( $links );
        }
 
@@ -3225,7 +3229,7 @@ $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,
@@ -3482,9 +3486,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();
@@ -3579,7 +3583,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
index b4bb6de..084d6ab 100644 (file)
@@ -108,7 +108,7 @@ class Preferences {
         * @throws MWException
         * @param User $user
         * @param IContextSource $context
-        * @param array defaultPreferences to load values for
+        * @param array $defaultPreferences Array to load values for
         * @return array|null
         */
        static function loadPreferenceValues( $user, $context, &$defaultPreferences ) {
@@ -989,10 +989,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',
@@ -1022,7 +1027,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',
                        );
                }
index f794b2a..35be2a9 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
index bcd3fd8..a6148c7 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
index ec17a08..b173ae9 100644 (file)
@@ -715,7 +715,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 +1081,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
@@ -1228,7 +1228,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 040aba5..03c529e 100644 (file)
@@ -169,7 +169,6 @@ $wgLockManagers[] = array(
  * Initialise $wgLocalFileRepo from backwards-compatible settings
  */
 if ( !$wgLocalFileRepo ) {
-       $deletedHashLevel = $wgHashedUploadDirectory ? 3 : 0;
        $wgLocalFileRepo = array(
                'class' => 'LocalRepo',
                'name' => 'local',
@@ -181,7 +180,7 @@ if ( !$wgLocalFileRepo ) {
                'thumbScriptUrl' => $wgThumbnailScriptPath,
                'transformVia404' => !$wgGenerateThumbnailOnParse,
                'deletedDir' => $wgDeletedDirectory,
-               'deletedHashLevels' => $deletedHashLevel
+               'deletedHashLevels' => $wgHashedUploadDirectory ? 3 : 0
        );
 }
 /**
@@ -488,7 +487,7 @@ if ( !$wgHTCPRouting && $wgHTCPMulticastAddress ) {
 }
 
 // Back compatibility for $wgRateLimitLog deprecated with 1.23
-if ( $wgRateLimitLog && ! array_key_exists( 'ratelimit', $wgDebugLogGroups ) ) {
+if ( $wgRateLimitLog && !array_key_exists( 'ratelimit', $wgDebugLogGroups ) ) {
        $wgDebugLogGroups['ratelimit'] = $wgRateLimitLog;
 }
 
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)
         */
index f493b7b..fd737c0 100644 (file)
@@ -145,25 +145,28 @@ abstract class Skin extends ContextSource {
 
        /**
         * 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.
+        *
+        * 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;
+               global $wgDefaultSkin, $wgFallbackSkin;
 
                $skinNames = Skin::getSkinNames();
 
                // Make keys lowercase for case-insensitive matching.
                $skinNames = array_change_key_case( $skinNames, CASE_LOWER );
                $key = strtolower( $key );
-               $default = strtolower( $wgDefaultSkin );
+               $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 = $default;
+                       $key = $defaultSkin;
                }
 
                if ( isset( $skinNames[$key] ) ) {
@@ -173,7 +176,7 @@ abstract class Skin extends ContextSource {
                // Older versions of the software used a numeric setting
                // in the user preferences.
                $fallback = array(
-                       0 => $default,
+                       0 => $defaultSkin,
                        2 => 'cologneblue'
                );
 
@@ -183,10 +186,10 @@ abstract class Skin extends ContextSource {
 
                if ( isset( $skinNames[$key] ) ) {
                        return $key;
-               } elseif ( isset( $skinNames[$default] ) ) {
-                       return $default;
+               } elseif ( isset( $skinNames[$defaultSkin] ) ) {
+                       return $defaultSkin;
                } else {
-                       return 'vector';
+                       return $fallbackSkin;
                }
        }
 
@@ -196,7 +199,7 @@ abstract class Skin extends ContextSource {
         * @return Skin
         */
        static function &newFromKey( $key ) {
-               global $wgStyleDirectory;
+               global $wgStyleDirectory, $wgFallbackSkin;
 
                $key = Skin::normalizeKey( $key );
 
@@ -216,7 +219,9 @@ abstract class Skin extends ContextSource {
                                # except by SQL manipulation if a previously valid skin name
                                # is no longer valid.
                                wfDebug( "Skin class does not exist: $className\n" );
-                               $className = 'SkinVector';
+
+                               $fallback = $skinNames[ Skin::normalizeKey( $wgFallbackSkin ) ];
+                               $className = "Skin{$fallback}";
                        }
                }
                $skin = new $className( $key );
@@ -991,8 +996,8 @@ abstract class Skin extends ContextSource {
 
        /**
         * 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
+        * @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 ) {
index bcd3532..52e72e8 100644 (file)
@@ -763,7 +763,7 @@ class SkinTemplate extends Skin {
        /**
         * Builds an array with tab definition
         *
-        * @param Title $title page Where the tab links to
+        * @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
@@ -1197,7 +1197,7 @@ class SkinTemplate extends Skin {
 
        /**
         * an array of edit links by default used for the tabs
-        * @param $content_navigation
+        * @param array $content_navigation
         * @return array
         */
        private function buildContentActionUrls( $content_navigation ) {
@@ -1796,9 +1796,9 @@ abstract class BaseTemplate extends QuickTemplate {
         * 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
+        * @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.
+        * @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
@@ -1819,7 +1819,7 @@ abstract class BaseTemplate extends QuickTemplate {
         *
         * If you don't want an accesskey, set $item['tooltiponly'] = true;
         *
-        * @param array $options can be used to affect the output of a link.
+        * @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
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 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..73952da 100644 (file)
@@ -134,7 +134,7 @@ 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 ) {
@@ -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
index b7c0a25..ab55257 100644 (file)
@@ -95,7 +95,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? */
@@ -608,7 +608,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
         */
@@ -853,7 +853,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).
         *
@@ -1094,7 +1094,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
         */
@@ -1645,7 +1645,7 @@ class Title {
         * @see self::getFullURL to always get an absolute URL.
         * @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.
@@ -1878,11 +1878,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.
         */
@@ -1906,7 +1906,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
@@ -2564,7 +2564,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
         */
index ce3ea74..a21119a 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
@@ -357,7 +346,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;
@@ -369,7 +358,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;
                }
@@ -410,7 +399,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 );
@@ -753,7 +742,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 );
@@ -918,8 +907,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 ) ) {
@@ -997,10 +987,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;
@@ -1139,7 +1132,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 ) {
@@ -1190,6 +1183,7 @@ class User implements IDBAccessObject {
         */
        public function loadFromRow( $row, $data = null ) {
                $all = true;
+               $passwordFactory = self::getPasswordFactory();
 
                $this->mGroups = null; // deferred
 
@@ -1223,9 +1217,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;
@@ -1235,7 +1251,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;
@@ -1286,6 +1301,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.
         *
@@ -1385,7 +1420,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 ) );
 
@@ -2034,7 +2069,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 ) {
@@ -2151,7 +2186,7 @@ class User implements IDBAccessObject {
         *
         * Called implicitly from invalidateCache() and saveSettings().
         */
-       private function clearSharedCache() {
+       public function clearSharedCache() {
                $this->load();
                if ( $this->mId ) {
                        global $wgMemc;
@@ -2224,7 +2259,7 @@ 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
         */
@@ -2267,16 +2302,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;
        }
 
@@ -2303,7 +2338,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;
                }
@@ -2323,7 +2358,7 @@ class User implements IDBAccessObject {
                        $this->mNewpassword = '';
                        $this->mNewpassTime = null;
                } else {
-                       $this->mNewpassword = self::crypt( $str );
+                       $this->mNewpassword = self::getPasswordFactory()->newFromPlaintext( $str );
                        if ( $throttle ) {
                                $this->mNewpassTime = wfTimestampNow();
                        }
@@ -2374,8 +2409,8 @@ class User implements IDBAccessObject {
                if ( $str == $this->mEmail ) {
                        return;
                }
-               $this->mEmail = $str;
                $this->invalidateEmail();
+               $this->mEmail = $str;
                wfRunHooks( 'UserSetEmail', array( $this, &$this->mEmail ) );
        }
 
@@ -2624,7 +2659,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();
@@ -2908,7 +2943,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() ) {
@@ -3411,6 +3446,7 @@ class User implements IDBAccessObject {
                global $wgAuth;
 
                $this->load();
+               $this->loadPasswords();
                if ( wfReadOnly() ) {
                        return;
                }
@@ -3420,15 +3456,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,
@@ -3490,6 +3526,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;
@@ -3501,8 +3538,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 ),
@@ -3552,6 +3589,7 @@ class User implements IDBAccessObject {
         */
        public function addToDatabase() {
                $this->load();
+               $this->loadPasswords();
                if ( !$this->mToken ) {
                        $this->setToken(); // init token
                }
@@ -3565,8 +3603,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 ),
@@ -3717,12 +3755,12 @@ 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();
+               $this->loadPasswords();
 
                // Certain authentication plugins do NOT want to save
                // domain passwords in a mysql database, so we should
@@ -3737,19 +3775,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;
        }
 
        /**
@@ -3764,7 +3810,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;
                        }
@@ -3779,7 +3826,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
         */
@@ -3796,7 +3843,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
         */
@@ -3806,7 +3853,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 ) {
@@ -3816,7 +3863,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;
                }
        }
 
@@ -3857,7 +3904,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 ) {
@@ -4014,6 +4061,7 @@ class User implements IDBAccessObject {
                $this->mEmailToken = null;
                $this->mEmailTokenExpires = null;
                $this->setEmailAuthenticationTimestamp( null );
+               $this->mEmail = '';
                wfRunHooks( 'InvalidateEmailComplete', array( $this ) );
                return true;
        }
@@ -4363,7 +4411,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) )
@@ -4433,7 +4481,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) )
@@ -4550,22 +4598,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
         *
@@ -4573,23 +4605,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();
        }
 
        /**
@@ -4601,26 +4622,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 );
        }
 
        /**
@@ -4824,6 +4843,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
@@ -4892,16 +4925,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;
 
        /**
index 25be921..913b430 100644 (file)
@@ -397,7 +397,7 @@ class UserMailer {
                        if ( self::$mErrorString ) {
                                wfDebug( "Error sending mail: " . self::$mErrorString . "\n" );
                                return Status::newFatal( 'php-mail-error', self::$mErrorString );
-                       } elseif ( ! $sent ) {
+                       } elseif ( !$sent ) {
                                // mail function only tells if there's an error
                                wfDebug( "Unknown error sending mail\n" );
                                return Status::newFatal( 'php-mail-error-unknown' );
index ce9fecd..a1fa0eb 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...
@@ -271,51 +270,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 +700,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 +772,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 +799,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 +868,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 +969,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 +1252,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..adccf9c 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.
@@ -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..e137628 100644 (file)
@@ -41,11 +41,7 @@ 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();
-}
+$wgRUstart = function_exists( 'getrusage' ) ? getrusage() : array();
 unset( $IP );
 
 # Valid web server entry point, enable includes.
@@ -61,11 +57,7 @@ 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
index 6fb5380..7761ecc 100644 (file)
@@ -233,7 +233,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
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..dd5195d 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__ );
@@ -104,7 +104,7 @@ class CreditsAction extends FormlessAction {
         * 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;
index 2ca9d9a..4992313 100644 (file)
@@ -251,7 +251,7 @@ 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;
@@ -303,7 +303,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 ) {
@@ -776,18 +776,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 +801,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
+                       )
+               );
        }
 
        /**
index 4baf7b9..37e6e66 100644 (file)
@@ -205,10 +205,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 +217,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;
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 ) &&
index 2fa4518..35555bc 100644 (file)
@@ -104,8 +104,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 ) {
index 884306a..8a0c280 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'] ) ) {
index 848d129..5d20005 100644 (file)
@@ -354,7 +354,7 @@ class ApiFormatFeedWrapper extends ApiFormatBase {
         * 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
+        * @param array $feedItems Array of FeedItem objects
         */
        public static function setResult( $result, $feed, $feedItems ) {
                // Store output in the Result data.
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 c932a74..fa7524f 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 ) {
index a5873e6..4a75f3c 100644 (file)
@@ -861,7 +861,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() ) {
index b906b59..2e993e3 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,10 @@ class ApiParse extends ApiBase {
                return $pout;
        }
 
+       /**
+        * @param Content $content
+        * @param string $what Identifies the content in error messages, e.g. page title.
+        */
        private function getSectionContent( Content $content, $what ) {
                // Not cached (save or load)
                $section = $content->getSection( $this->section );
index f4b28fa..606012c 100644 (file)
@@ -180,7 +180,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 +191,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 +348,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 +426,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 +450,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
index 4b49a80..a214610 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;
index d79deec..7cd8aac 100644 (file)
@@ -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 ) {
index 44d287b..cb4e3e8 100644 (file)
@@ -47,7 +47,7 @@ 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)
+        * @return array Array(tokenname => function)
         */
        protected function getTokenFunctions() {
                // Don't call the hooks twice
@@ -105,7 +105,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'] );
index 80e09b6..1bba715 100644 (file)
@@ -61,7 +61,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(),
index 332ed51..7d6a7e4 100644 (file)
@@ -60,7 +60,7 @@ class ApiUndelete extends ApiBase {
                $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 );
@@ -105,6 +105,10 @@ class ApiUndelete extends ApiBase {
                                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,10 +124,19 @@ 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',
+                       'token' => array(
+                               'An undelete token previously retrieved through list=deletedrevs, or ',
+                               'a delete token retrieved through action=tokens.'
+                       ),
                        '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',
                );
@@ -143,7 +156,8 @@ class ApiUndelete extends ApiBase {
        public function getDescription() {
                return array(
                        'Restore certain revisions of a deleted page. A list of deleted revisions ',
-                       '(including timestamps) can be retrieved through list=deletedrevs.'
+                       '(including timestamps) can be retrieved through list=deletedrevs, and a list',
+                       'of deleted file ids can be retrieved through list=filearchive.'
                );
        }
 
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.
index 695eac3..401c2b9 100644 (file)
@@ -55,7 +55,7 @@ interface ICacheHelper {
         *
         * @since 1.20
         *
-        * @param {function} $computeFunction
+        * @param callable $computeFunction
         * @param array|mixed $args
         * @param string|null $key
         *
@@ -255,7 +255,7 @@ class CacheHelper implements ICacheHelper {
         *
         * @since 1.20
         *
-        * @param {function} $computeFunction
+        * @param callable $computeFunction
         * @param array|mixed $args
         * @param string|null $key
         *
index 9dc3dc3..cf87129 100644 (file)
@@ -536,7 +536,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 ) {
@@ -1157,7 +1157,7 @@ class LCStoreDB implements LCStore {
 
        /** @var DatabaseBase */
        private $dbw;
-       /** @var Array */
+       /** @var array */
        private $batch = array();
 
        private $readOnly = false;
@@ -1186,7 +1186,7 @@ class LCStoreDB implements LCStore {
 
                // We must keep a separate connection to MySQL in order to avoid breaking
                // main transactions. However, SQLite deadlocks when using two connections.
-               // @TODO: get this trick to work on PostgreSQL too
+               // @todo get this trick to work on PostgreSQL too
                if ( wfGetDB( DB_MASTER )->getType() == 'mysql' ) {
                        $lb = wfGetLBFactory()->newMainLB();
                        $this->dbw = $lb->getConnection( DB_MASTER );
index e5afd21..e34961c 100644 (file)
@@ -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)
         */
index 0c073c6..b471ea5 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.' );
                        }
index 8fa6ed9..cfebf40 100644 (file)
@@ -179,7 +179,7 @@ class RecentChange {
        /**
         * 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 ) {
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 b09316b..ff2f403 100644 (file)
@@ -57,8 +57,8 @@ class ConfigFactory {
         * 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 +70,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..0841a00 100644 (file)
@@ -72,7 +72,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 +80,9 @@ 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
         */
        protected function setWithPrefix( $prefix, $name, $value ) {
-               $GLOBALS[ $prefix . $name ] = $value;
+               $GLOBALS[$prefix . $name] = $value;
        }
 }
index e077c77..c8a9f1e 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.
@@ -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 85059a8..fd326f0 100644 (file)
@@ -65,7 +65,7 @@ class CssContentHandler extends TextContentHandler {
         * @param Title $title
         * @param Content $content
         *
-        * @return Language wfGetLangObj( 'en' )
+        * @return Language Return of wfGetLangObj( 'en' )
         *
         * @see ContentHandler::getPageLanguage()
         */
@@ -79,7 +79,7 @@ class CssContentHandler extends TextContentHandler {
         * @param Title $title
         * @param Content $content
         *
-        * @return Language wfGetLangObj( 'en' )
+        * @return Language Return of wfGetLangObj( 'en' )
         *
         * @see ContentHandler::getPageViewLanguage()
         */
index 2e98976..122003f 100644 (file)
@@ -65,7 +65,7 @@ class JavaScriptContentHandler extends TextContentHandler {
         * @param Title $title
         * @param Content $content
         *
-        * @return Language wfGetLangObj( 'en' )
+        * @return Language Return of wfGetLangObj( 'en' )
         *
         * @see ContentHandler::getPageLanguage()
         */
@@ -79,7 +79,7 @@ class JavaScriptContentHandler extends TextContentHandler {
         * @param Title $title
         * @param Content $content
         *
-        * @return Language wfGetLangObj( 'en' )
+        * @return Language Return of wfGetLangObj( 'en' )
         *
         * @see ContentHandler::getPageViewLanguage()
         */
index b601344..abaac53 100644 (file)
@@ -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
         */
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 cdf5962..237029b 100644 (file)
@@ -170,7 +170,7 @@ class WikitextContent extends TextContent {
        /**
         * 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
         *
@@ -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,
index d78f420..b8966f0 100644 (file)
@@ -296,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 3207a1b..df19a49 100644 (file)
@@ -1028,7 +1028,7 @@ 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->isWriteQuery( $sql ) ) {
@@ -1102,7 +1102,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';
@@ -1133,7 +1134,8 @@ abstract class DatabaseBase implements IDatabase, DatabaseType {
                        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 ) {
@@ -1898,7 +1900,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
         */
@@ -2093,11 +2095,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();
@@ -2383,7 +2385,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 ) {
@@ -2417,7 +2419,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 ) {
@@ -2918,9 +2920,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
         */
@@ -3209,7 +3211,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.
         */
@@ -3286,7 +3288,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
@@ -3297,6 +3299,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 ) );
@@ -3312,7 +3318,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
@@ -3321,6 +3327,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 ) );
@@ -4150,7 +4160,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 ) {
index be01f1a..c2f5b6d 100644 (file)
@@ -743,7 +743,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 +787,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
@@ -1177,7 +1177,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..5ad7c78 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,7 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
 
        /**
         * @param bool $value
-        * @return mixed null|bool|ResultWrapper
+        * @return null|bool|ResultWrapper
         */
        public function setBigSelects( $value = true ) {
                if ( $value === 'default' ) {
@@ -1241,7 +1241,7 @@ class MySQLMasterPos implements DBMasterPos {
        /** @var string */
        public $file;
 
-       /** @var int timestamp */
+       /** @var int Timestamp */
        public $pos;
 
        function __construct( $file, $pos ) {
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 49dcbc0..f5fdca1 100644 (file)
@@ -1235,7 +1235,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 +1322,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 +1546,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 af687b2..9a03a33 100644 (file)
@@ -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]";
index 36d218a..3923241 100644 (file)
@@ -107,7 +107,7 @@ class ResultWrapper implements Iterator {
        /** @var int */
        protected $pos = 0;
 
-       /** @var */
+       /** @var object|null */
        protected $currentRow = null;
 
        /**
index ab1ab79..bf49bbb 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 );
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 01440f4..db4ed60 100644 (file)
@@ -43,7 +43,7 @@ class LoadBalancer {
        private $mLoadMonitorClass, $mLoadMonitor;
 
        /**
-        * @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 +331,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 +369,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 +393,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
index 51b81da..24fa68c 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
         */
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..2178281 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 = '' ) {
index 2c984f7..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 */
@@ -524,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.
         *
@@ -553,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 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 901ef9f..8282295 100644 (file)
@@ -51,7 +51,7 @@ class ViewCountUpdate implements DeferrableUpdate {
                if ( $wgHitcounterUpdateFreq <= 1 || $dbw->getType() == 'sqlite' ) {
                        $id = $this->id;
                        $method = __METHOD__;
-                       $dbw->onTransactionIdle( function() use ( $dbw, $id, $method ) {
+                       $dbw->onTransactionIdle( function () use ( $dbw, $id, $method ) {
                                try {
                                        $dbw->update( 'page',
                                                array( 'page_counter = page_counter + 1' ),
index 3aad389..661330d 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
@@ -823,8 +823,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 +972,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
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 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 4575e7c..47bacb5 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
@@ -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 2b0c3c2..b99ffb6 100644 (file)
@@ -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 a1ff1f4..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
@@ -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 9ef23f8..e9c8883 100644 (file)
@@ -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..a45fb7a 100644 (file)
@@ -1055,7 +1055,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.
index 3f7adb0..96c8803 100644 (file)
@@ -369,7 +369,7 @@ 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
+        * @param string $hash A sha1 hash to look for
         * @return array
         */
        function findBySha1( $hash ) {
index 65637df..fce3f78 100644 (file)
@@ -272,7 +272,7 @@ class RepoGroup {
        /**
         * Find all instances of files with this key
         *
-        * @param string $hash base 36 SHA-1 hash
+        * @param string $hash Base 36 SHA-1 hash
         * @return array Array of File objects
         */
        function findBySha1( $hash ) {
@@ -292,7 +292,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 ) {
@@ -420,7 +420,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..735bf8a 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 */
index e970e38..c6da1f1 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.
@@ -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(
@@ -1606,7 +1606,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 +1623,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 +1633,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 +1741,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
@@ -2072,44 +2072,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 1f2defe..1eff1df 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) */
@@ -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
@@ -437,7 +437,7 @@ class LocalFile extends File {
        /**
         * @param DatabaseBase $dbr
         * @param string $fname
-        * @return array|false
+        * @return array|bool
         */
        private function loadFieldsWithTimestamp( $dbr, $fname ) {
                $fieldMap = false;
@@ -833,7 +833,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 ) {
@@ -1848,7 +1848,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();
index ca92496..0adcc73 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 ) {
index 837a731..53c2e10 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;
 
index bb55c89..b004a95 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
         */
index df6582c..6cf8d0a 100644 (file)
@@ -352,7 +352,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 );
@@ -622,7 +622,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)
@@ -741,8 +741,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;
@@ -760,7 +760,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 ) );
@@ -980,7 +980,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
         */
@@ -1010,7 +1010,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)
         */
@@ -1024,12 +1024,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;
        }
@@ -1143,12 +1146,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;
        }
@@ -1370,7 +1376,7 @@ class HTMLForm extends ContextSource {
         *
         * @param array $data
         *
-        * @return
+        * @return array
         */
        function filterDataForSubmit( $data ) {
                return $data;
index 1fcc866..7e4b15b 100644 (file)
@@ -35,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.
@@ -125,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;
@@ -250,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;
@@ -264,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 ) {
index c6939a8..1c7762b 100644 (file)
@@ -179,11 +179,16 @@ class CliInstaller extends Installer {
        public function showHelpBox( $msg /*, ... */ ) {
        }
 
-       /**
-        * @param Status $status
-        */
        public function showStatusMessage( Status $status ) {
-               parent::showStatusMessage( $status );
+               $warnings = array_merge( $status->getWarningsArray(),
+                       $status->getErrorsArray() );
+
+               if ( count( $warnings ) !== 0 ) {
+                       foreach ( $warnings as $w ) {
+                               call_user_func_array( array( $this, 'showMessage' ), $w );
+                       }
+               }
+
                if ( !$status->isOk() ) {
                        echo "\n";
                        exit( 1 );
index 1fdd6fb..28304c2 100644 (file)
@@ -119,7 +119,6 @@ abstract class Installer {
                'envCheckRegisterGlobals',
                'envCheckBrokenXML',
                'envCheckMagicQuotes',
-               'envCheckMagicSybase',
                'envCheckMbstring',
                'envCheckSafeMode',
                'envCheckXML',
@@ -353,17 +352,10 @@ abstract class Installer {
        abstract public function showError( $msg /*, ... */ );
 
        /**
-        * Shows messages to the user through a Status object
+        * Show a message to the installing user by using a Status object
         * @param Status $status
         */
-       public function showStatusMessage( Status $status ) {
-               $errors = array_merge( $status->getErrorsArray(), $status->getWarningsArray() );
-               if ( $errors ) {
-                       foreach ( $errors as $error ) {
-                               call_user_func( 'showMessage', $error );
-                       }
-               }
-       }
+       abstract public function showStatusMessage( Status $status );
 
        /**
         * Constructor, always call this from child classes.
@@ -762,31 +754,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;
        }
 
        /**
@@ -1294,8 +1274,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
index 3515469..68c2ebe 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
         */
@@ -729,6 +729,16 @@ class WebInstaller extends Installer {
                $this->output->addHTML( $html );
        }
 
+       /**
+        * @param Status $status
+        */
+       public function showStatusMessage( Status $status ) {
+               $errors = array_merge( $status->getErrorsArray(), $status->getWarningsArray() );
+               foreach ( $errors as $error ) {
+                       call_user_func_array( array( $this, 'showMessage' ), $error );
+               }
+       }
+
        /**
         * Label a control by wrapping a config-input div around it and putting a
         * label before it.
index c26028d..9fdee76 100644 (file)
@@ -164,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
         */
@@ -1048,7 +1048,7 @@ class WebInstallerOptions extends WebInstallerPage {
                                                '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 class="config-skins-use-as-default">' . $radioButtons[strtolower( $skin )] . '</div>' .
                                        '</div>';
                        }
                } else {
index dc5c0b7..79e16f1 100644 (file)
@@ -59,6 +59,7 @@
        "config-outdated-sqlite": "'''Папярэджаньне''': усталяваны SQLite $1, у той час, калі мінімальная сумяшчальная вэрсія — $2. SQLite ня будзе даступны.",
        "config-no-fts3": "'''Папярэджаньне''': SQLite створаны без модуля [//sqlite.org/fts3.html FTS3], для гэтага ўнутранага інтэрфэйсу ня будзе даступная магчымасьць пошуку.",
        "config-register-globals-error": "<strong>Памылка: парамэтар PHP <code>[http://php.net/register_globals register_globals]</code> уключаны.\nЁн павінен быць адключаны, каб працягнуць усталяваньне.</strong>\nГлядзіце [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals] дзеля дапамогі, як зрабіць гэта.",
+       "config-magic-quotes-gpc": "<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 немагчымыя, пакуль рэжым ня будзе выключаны.",
        "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-install-alreadydone": "'''Папярэджаньне:''' здаецца, што Вы ўжо ўсталёўвалі MediaWiki і спрабуеце зрабіць гэтай зноў.\nКалі ласка, перайдзіце на наступную старонку.",
        "config-install-begin": "Пасьля націску кнопкі «{{int:config-continue}}» пачнецца ўсталяваньне MediaWiki.\nКалі Вы жадаеце што-небудзь зьмяніць, націсьніце кнопку «{{int:config-back}}».",
        "config-install-step-done": "зроблена",
index 1192e2c..880e974 100644 (file)
@@ -56,9 +56,9 @@
        "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": "ইনোডিবি",
index f4b75db..c2aaf64 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-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-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",
index c1960fb..e8db404 100644 (file)
@@ -5,9 +5,30 @@
                ]
        },
        "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-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-profile-wiki": "Bukas na wiki",
        "config-profile-private": "Pribadong wiki",
        "config-logo": "URL ko logo:",
index 3fa9b92..5d65f2d 100644 (file)
        "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",
        "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-install-step-done": "fet",
        "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",
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 bc274ac..0510bfc 100644 (file)
@@ -60,6 +60,7 @@
        "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-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.",
index 93da07d..532d7c1 100644 (file)
@@ -66,6 +66,7 @@
        "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-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.",
index da8117b..bd76ada 100644 (file)
@@ -52,6 +52,7 @@
        "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 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.",
index b651b40..135a32b 100644 (file)
@@ -23,7 +23,8 @@
                        "Seb35",
                        "McDutchie",
                        "Miguel2706",
-                       "Macofe"
+                       "Macofe",
+                       "AVIADOR"
                ]
        },
        "config-desc": "El instalador de MediaWiki",
@@ -75,6 +76,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-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.",
@@ -85,6 +88,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-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",
index ccebf08..d619cff 100644 (file)
@@ -59,6 +59,7 @@
        "config-outdated-sqlite": "''' هشدار:''' شما اس‌کیولایت $1 دارید، که پایین‌تر از حداقل نسخهٔ $2 مورد نیاز است.اس‌کیولایت در دسترس نخواهد بود.",
        "config-no-fts3": "'''هشدار:''' اس‌کیولایت بدون [//sqlite.org/fts3.html FTS3 module] تهیه شده‌است ، جستجوی ویژگی‌ها در این بخش پیشین در دسترس نخواهد‌بود.",
        "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شما نمی‌توانید مدیاویکی را نصب یا استفاده کنید مگر اینکه این گزینه غیر‌فعال باشد.",
@@ -69,6 +70,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] نصب شده‌است.",
        "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": "انجام شد",
index cdb6c99..57d7444 100644 (file)
@@ -74,6 +74,7 @@
        "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-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.",
index e49ee2f..57e3c94 100644 (file)
@@ -59,6 +59,7 @@
        "config-outdated-sqlite": "'''אזהרה''': במערכת מתוקן SQLite $1. גרסה זו לא נתמכת ולשימוש ב־SQLite נדרשת גרסה $2 לפחות. SQLlite לא יהיה זמין.",
        "config-no-fts3": "'''אזהרה''': SQLite מקומפל ללא [//sqlite.org/fts3.html מודול FTS]. יכולות חיפוש לא יהיו זמינות בהתקנה הזאת.",
        "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לא ניתן להתקין את מדיה־ויקי או להשתמש בה אלא אם האפשרות הזאת תכובה.",
index 79aed40..80b8a09 100644 (file)
@@ -11,7 +11,8 @@
                        "Whym",
                        "Yanajin66",
                        "青子守歌",
-                       "아라"
+                       "아라",
+                       "Shield-9"
                ]
        },
        "config-desc": "MediaWiki のインストーラー",
        "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": "少なくとも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": "実行",
index 72619bc..b2221a5 100644 (file)
        "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-install-alreadydone": "'''경고:''' 이미 미디어위키를 설치했고 다시 설치하려고 합니다.\n다음 페이지로 진행하세요.",
        "config-install-begin": "\"{{int:config-continue}}\"을 누르면 미디어위키의 설치를 시작합니다.\n그래도 바꾸는 것을 원한다면 \"{{int:config-back}}\"를 누르세요.",
        "config-install-step-done": "완료",
index 255718f..74359b2 100644 (file)
@@ -55,6 +55,7 @@
        "config-outdated-sqlite": "'''Предупредување''': имате SQLite $1. Најстарата допуштена верзија е $2. Затоа, SQLite ќе биде недостапен.",
        "config-no-fts3": "'''Предупредување''': SQLite iе составен без модулот [//sqlite.org/fts3.html FTS3] - за оваа база нема да има можност за пребарување.",
        "config-register-globals-error": "<strong>Грешка: Вклучена е можноста <code>[http://php.net/register_globals register_globals]</code> за PHP.\nМора да се исклучи за да продолжите со воспоставката.</strong>\nКако да го направите тоа можете да прочитате на [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals].",
+       "config-magic-quotes-gpc": "<strong>Кобно: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc] е ективно!</strong>\nОваа можност непредвидливо го расипува вносот на податоци.\nОваа можност мора да е исклучена. Во спротивно нема да можете да го воспоставите и користите МедијаВики.",
        "config-magic-quotes-runtime": "'''Кобно: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] е активно!'''\nОваа можност непредвидливо го расипува вносот на податоци.\nОваа можност мора да е исклучена. Во спротивно нема да можете да го воспоставите и користите МедијаВики.",
        "config-magic-quotes-sybase": "'''Кобно: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase] е активно!'''\nОваа можност непредвидливо го расипува вносот на податоци.\nОваа можност мора да е исклучена. Во спротивно нема да можете да го воспоставите и користите МедијаВики.",
        "config-mbstring": "'''Кобно: [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload] е активно!'''\nОваа можност предизвикува грешки и може непредвидиво да го расипува вносот на податоци.\nОваа можност мора да е исклучена. Во спротивно нема да можете да го воспоставите и користите МедијаВики.",
index eb16d0d..a856301 100644 (file)
@@ -16,7 +16,8 @@
                        "Pan Cube",
                        "WTM",
                        "Alan ffm",
-                       "Matik7"
+                       "Matik7",
+                       "Pio387"
                ]
        },
        "config-desc": "Instalator MediaWiki",
@@ -79,6 +80,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-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",
index 1ea0e63..0735574 100644 (file)
@@ -70,6 +70,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}}",
index 15ac805..b5441c1 100644 (file)
@@ -70,6 +70,7 @@
        "config-outdated-sqlite": "'''Предупреждение''': у Вас установлен SQLite  $1, версия которого ниже требуемой $2 . SQLite будет недоступен.",
        "config-no-fts3": "'''Внимание''': SQLite собран без модуля [//sqlite.org/fts3.html FTS3] — поиск не будет работать для этой базы данных.",
        "config-register-globals-error": "<strong>Ошибка: Параметр PHP <code>[http://php.net/register_globals register_globals]</code> включен.\nОн должен быть отключен для того, чтобы можно было продолжить установку.</strong>\nПолучить справку о том, как это сделать, можно по адресу [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals].",
+       "config-magic-quotes-gpc": "'''Проблема: включена опция PHP [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc magic_quotes_gpc]!'''\nЭто приводит к непредсказуемой порче вводимых данных.\nУстановка и использование MediaWiki без выключения этой опции невозможно.",
        "config-magic-quotes-runtime": "'''Проблема: включена опция PHP [http://www.php.net/manual/ru/function.magic-quotes-runtime.php magic_quotes_runtime]!'''\nЭто приводит к непредсказуемой порче вводимых данных.\nУстановка и использование MediaWiki без выключения этой опции невозможно.",
        "config-magic-quotes-sybase": "'''Проблема: включена опция PHP [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-sybase magic_quotes_sybase]!'''\nЭто приводит к непредсказуемой порче вводимых данных.\nУстановка и использование MediaWiki без выключения этой опции невозможно.",
        "config-mbstring": "'''Проблема: включена опция PHP [http://www.php.net/manual/en/ref.mbstring.php#mbstring.overload mbstring.func_overload]!'''\nЭто приводит к ошибкам и непредсказуемой порче вводимых данных.\nУстановка и использование MediaWiki без выключения этой опции невозможно.",
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 a255cc1..001a0f8 100644 (file)
@@ -63,6 +63,7 @@
        "config-outdated-sqlite": "'''Увага''': у Вас встановлена версія SQLite $1, а це нижче, ніж мінімально необхідна версія $2. SQLite буде недоступним.",
        "config-no-fts3": "'''Увага''': SQLite зібраний без [//sqlite.org/fts3.html модуля FTS3], функції пошуку не будуть працювати у цій системі.",
        "config-register-globals-error": "<strong>Помилка: Опція PHP <code>[http://php.net/register_globals register_globals]</code> увімкнена.\nЩоб продовжити це встановлення, її треба вимкнути.</strong>\nДив. довідку, як це зробити, на [https://www.mediawiki.org/wiki/register_globals https://www.mediawiki.org/wiki/register_globals].",
+       "config-magic-quotes-gpc": "'''Фатальна помилка: [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, поки не буде вимкнено цю опцію.",
@@ -73,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-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": "виконано",
index f9a5fd7..82dd202 100644 (file)
@@ -73,6 +73,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-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。",
@@ -83,6 +85,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-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": "完成",
index 8342653..ed7c44b 100644 (file)
@@ -10,7 +10,9 @@
                        "아라",
                        "Liuxinyu970226",
                        "Xiaomingyan",
-                       "Cwlin0416"
+                       "Cwlin0416",
+                       "S8321414",
+                       "LNDDYL"
                ]
        },
        "config-desc": "MediaWiki 安裝程式",
        "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-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": "開啟監視清單通知",
        "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-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 c11df93..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() {
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 522bae1..3519eac 100644 (file)
@@ -73,7 +73,7 @@ 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.
@@ -83,7 +83,6 @@ class JobQueueRedis extends JobQueue {
         *   - 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.
-        * @param array $params
         */
        public function __construct( array $params ) {
                parent::__construct( $params );
diff --git a/includes/jobqueue/JobRunner.php b/includes/jobqueue/JobRunner.php
new file mode 100644 (file)
index 0000000..9a4073f
--- /dev/null
@@ -0,0 +1,296 @@
+<?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
+        * @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();
+
+               $backoffs = $this->loadBackoffs(); // map of (type => UNIX expiry)
+               $startingBackoffs = $backoffs; // avoid unnecessary writes
+               $backoffExpireFunc = function ( $t ) {
+                       return $t > time();
+               };
+
+               $jobsRun = 0; // counter
+               $timeMsTotal = 0;
+               $flags = JobQueueGroup::USE_CACHE;
+               $startTime = microtime( true ); // time since jobs started running
+               $lastTime = microtime( true ); // 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
+                               $jType = $job->getType();
+
+                               $this->runJobsLog( $job->toString() . " STARTING" );
+
+                               // Run the job...
+                               wfProfileIn( __METHOD__ . '-' . get_class( $job ) );
+                               $t = 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 ) - $t ) * 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
+                               }
+
+                               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
+                               );
+
+                               // Back off of certain jobs for a while (for throttling and for errors)
+                               $ttw = $this->getBackoffTimeToWait( $job );
+                               if ( $status === false && mt_rand( 0, 49 ) == 0 ) {
+                                       $ttw = max( $ttw, 30 );
+                               }
+                               if ( $ttw > 0 ) {
+                                       $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 ) {
+                                       $response['reached'] = 'job-limit';
+                                       break;
+                               } elseif ( $maxTime && ( microtime( true ) - $startTime ) > $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
+               $backoffs = array_filter( $backoffs, $backoffExpireFunc );
+               if ( $backoffs !== $startingBackoffs ) {
+                       $this->syncBackoffs( $backoffs );
+               }
+
+               $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
+        *
+        * @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)." );
+               }
+       }
+
+       /**
+        * 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 e8e8e30..db9e764 100644 (file)
@@ -36,14 +36,13 @@ 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 );
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..30b92c7 100644 (file)
@@ -301,7 +301,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 0139c4a..92985f3 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();
index 1b7e677..be7931d 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;
@@ -192,7 +192,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 +234,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 +250,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 +440,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 c0d9b71..b2802dd 100644 (file)
@@ -329,7 +329,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'] )
@@ -458,7 +458,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 );
index 2a393db..053c586 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 $meta 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 299252b..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;
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 d630136..d285c0c 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] ) ) {
@@ -729,8 +729,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
@@ -840,7 +840,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 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 2612685..e8f8360 100644 (file)
@@ -124,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
@@ -308,7 +308,7 @@ 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();
@@ -689,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();
@@ -843,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..9245d42 100644 (file)
@@ -185,7 +185,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 +479,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 ) {
index 9e69137..04099c3 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
index a74b701..154c85d 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' ) {
index de3efd1..6f8f9af 100644 (file)
@@ -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 ) {
@@ -330,9 +330,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 0c91dab..32996ac 100644 (file)
@@ -145,7 +145,7 @@ class SqlBagOStuff extends BagOStuff {
                        } else {
                                // We must keep a separate connection to MySQL in order to avoid deadlocks
                                // However, SQLite has an opposite behavior.
-                               // @TODO: get this trick to work on PostgreSQL too
+                               // @todo get this trick to work on PostgreSQL too
                                if ( wfGetDB( DB_MASTER )->getType() == 'mysql' ) {
                                        $lb = wfGetLBFactory()->newMainLB();
                                        $db = $lb->getConnection( DB_MASTER );
@@ -244,6 +244,9 @@ class SqlBagOStuff extends BagOStuff {
                                                // 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;
@@ -579,7 +582,7 @@ class SqlBagOStuff extends BagOStuff {
                                                        $conds,
                                                        __METHOD__,
                                                        array( 'LIMIT' => 100, 'ORDER BY' => 'exptime' ) );
-                                               if ( !$rows->numRows() ) {
+                                               if ( $rows === false || !$rows->numRows() ) {
                                                        break;
                                                }
                                                $keys = array();
index a6c7d9c..2a882ac 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 $valueObject Value to store
         * @param int $expire Expiration time
         * @return bool
         */
index 2f27826..436f148 100644 (file)
@@ -703,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
@@ -858,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;
@@ -1240,7 +1242,7 @@ class Article implements Page {
 
                $hookResult = wfRunHooks( 'BeforeDisplayNoArticleText', array( $this ) );
 
-               if ( ! $hookResult ) {
+               if ( !$hookResult ) {
                        return;
                }
 
@@ -1268,7 +1270,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 ) ) {
@@ -1655,11 +1657,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' );
@@ -1681,10 +1684,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' ) ) .
@@ -1743,7 +1746,7 @@ 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' );
 
@@ -1762,9 +1765,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 );
        }
 
        /**
@@ -1818,7 +1819,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;
@@ -1894,7 +1895,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 ) {
index 9aff6ef..380252f 100644 (file)
@@ -430,6 +430,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 +1063,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 +1102,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;
index 87cc7ba..bfcd4c3 100644 (file)
@@ -201,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 fc269d8..be5ce3f 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.
@@ -2313,7 +2313,7 @@ class WikiPage implements Page, IDBAccessObject {
         *
         * @param Content $content Content submitted
         * @param User $user The relevant user
-        * @param string $comment comment submitted
+        * @param string $comment Comment submitted
         * @param string $serialisation_format Format for storing the content in the database
         * @param bool $minor Whereas it's a minor modification
         */
@@ -2739,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
@@ -2780,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' );
@@ -2904,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.
@@ -2949,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)
         *
@@ -3525,7 +3525,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
index cfd5370..0bf2ffc 100644 (file)
@@ -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;
index 648667b..30bb2cf 100644 (file)
@@ -265,7 +265,7 @@ 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 ) {
index b37e977..bc4fcce 100644 (file)
@@ -211,7 +211,7 @@ class Parser {
        var $mLangLinkLanguages;
 
        /**
-        * @var boolean Recursive call protection.
+        * @var bool Recursive call protection.
         * This variable should be treated as if it were private.
         */
        public $mInParse = false;
@@ -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
@@ -798,7 +798,7 @@ class Parser {
        /**
         * Get the ParserOptions object
         *
-        * @return ParserOptions object
+        * @return ParserOptions
         */
        function getOptions() {
                return $this->mOptions;
@@ -1434,7 +1434,7 @@ class Parser {
         *
         * @param string $text
         *
-        * @return string the altered text
+        * @return string The altered text
         */
        function doAllQuotes( $text ) {
                wfProfileIn( __METHOD__ );
index 33f0f96..6102ca4 100644 (file)
@@ -26,7 +26,7 @@
  * @todo document
  */
 class ParserCache {
-       /** @var MWMemcached  */
+       /** @var MWMemcached */
        private $mMemc;
        /**
         * Get an instance of this object
index 2cd208c..411702f 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.
index 09f714f..3de7505 100644 (file)
@@ -56,6 +56,7 @@ class ParserOutput extends CacheTime {
                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>))#';
@@ -396,7 +397,7 @@ 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 ) {
                if ( !$title->isExternal() ) {
@@ -471,6 +472,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 +480,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 );
@@ -537,7 +539,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 +578,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.
@@ -793,6 +795,17 @@ class ParserOutput extends CacheTime {
                $this->mLimitReportData[$key] = $value;
        }
 
+       /**
+        * Get or set the prevent-clickjacking flag
+        *
+        * @since 1.24
+        * @param boolean|null $flag New flag value, or null to leave it unchanged
+        * @return boolean Old flag value
+        */
+       public function preventClickjacking( $flag = null ) {
+               return wfSetVar( $this->mPreventClickjacking, $flag );
+       }
+
        /**
         * Save space for for serialization by removing useless values
         */
index bf2bf61..26daca1 100644 (file)
@@ -995,7 +995,7 @@ class PPFrame_Hash implements PPFrame {
 
        /**
         * @throws MWException
-        * @param string|PPNode$root
+        * @param string|PPNode $root
         * @param int $flags
         * @return string
         */
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..70b7656
--- /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 object
+        * @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 object
+        * @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 object
+        */
+       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 779f8b6..7b8f340 100644 (file)
@@ -25,7 +25,7 @@
 
 /**
  * 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 +38,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
@@ -196,7 +196,7 @@ abstract class Profiler {
        /**
         * Called by wfProfieOut()
         *
-        * @param  string $functionname
+        * @param string $functionname
         */
        abstract public function profileOut( $functionname );
 
@@ -326,7 +326,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 +338,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 +356,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 +397,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 5de9982..7fd86eb 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 ) {
index 066ecbe..768dd7f 100644 (file)
@@ -31,7 +31,7 @@ interface RCFeedEngine {
         * @see RecentChange::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 );
 }
index 36e3a1b..bcb3842 100644 (file)
@@ -50,7 +50,7 @@ class ResourceLoader {
         */
        protected $testModuleNames = array();
 
-       /** @var array e.g. array( 'source-id' => array( 'loadScript' => 'http://.../load.php' ) ) */
+       /** @var array E.g. array( 'source-id' => array( 'loadScript' => 'http://.../load.php' ) ) */
        protected $sources = array();
 
        /** @var bool */
@@ -293,6 +293,47 @@ class ResourceLoader {
                                        '\': expected ResourceLoaderModule or array (got: ' . gettype( $info ) . ')'
                                );
                        }
+
+                       // Last-minute changes
+
+                       // Apply custom skin-defined styles to existing modules.
+                       if ( $this->isFileModule( $name ) ) {
+                               global $wgResourceModuleSkinStyles;
+                               foreach ( $wgResourceModuleSkinStyles 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();
+                                       } else if ( 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__ );
@@ -448,6 +489,23 @@ class ResourceLoader {
                return $this->modules[$name];
        }
 
+       /**
+        * Return whether the definition of a module corresponds to a simple ResourceLoaderFileModule.
+        *
+        * @param string $name Module name
+        * @return boolean
+        */
+       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.
         *
@@ -463,7 +521,7 @@ class ResourceLoader {
         *
         * @since 1.24
         * @param string $source
-        * @throws MWException on an invalid $source name
+        * @throws MWException On an invalid $source name
         * @return string
         */
        public function getLoadScript( $source ) {
@@ -1250,7 +1308,7 @@ class ResourceLoader {
         * Build a load.php URL
         *
         * @since 1.24
-        * @param string $source name of the ResourceLoader source
+        * @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)
index 3a6d5d2..edde9bc 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,59 @@ 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 = $remoteBasePath;
+               } else {
+                       $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 +369,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 ) {
@@ -567,18 +605,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 +706,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        $files = array_merge( $files, $this->debugScripts );
                }
 
-               return array_unique( $files );
+               return array_unique( $files, SORT_REGULAR );
        }
 
        /**
@@ -751,7 +797,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        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\"" );
@@ -785,7 +831,7 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        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 );
@@ -804,17 +850,18 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
         * @param bool $flip
         *
         * @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 ) {
                $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' ) {
+               if ( $this->getStyleSheetLang( $localPath ) === 'less' ) {
                        $style = $this->compileLESSFile( $localPath );
                        $this->hasGeneratedStyles = true;
                } else {
@@ -824,20 +871,15 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                if ( $flip ) {
                        $style = CSSJanus::transform( $style, true, false );
                }
-               $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
                );
        }
 
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 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 00d245c..0ace76a 100644 (file)
@@ -188,7 +188,7 @@ 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 ) {
                $resourceLoader = $context->getResourceLoader();
@@ -548,7 +548,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;
 
index 56eb0a0..2c0f8df 100644 (file)
@@ -168,7 +168,7 @@ 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'
@@ -233,7 +233,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                                );
                        }
 
-                       $registryData[ $name ] = array(
+                       $registryData[$name] = array(
                                'version' => $mtime,
                                'dependencies' => $module->getDependencies(),
                                'group' => $module->getGroup(),
index e42301b..dc52969 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.
index b8b2bae..57cdaf4 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
         */
@@ -528,7 +528,7 @@ class SearchHighlighter {
                        }
                        ++$lineno;
                        $m = array();
-                       if ( ! preg_match( $pat1, $line, $m ) ) {
+                       if ( !preg_match( $pat1, $line, $m ) ) {
                                continue;
                        }
                        --$contextlines;
index 56ae2ff..453211b 100644 (file)
@@ -217,7 +217,7 @@ class SearchResult {
        }
 
        /**
-        * @return string timestamp
+        * @return string Timestamp
         */
        function getTimestamp() {
                if ( $this->mRevision ) {
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
         */
index 008200d..806a48a 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 );
@@ -351,8 +359,9 @@ abstract class ChangesListSpecialPage extends SpecialPage {
         * Set the text to be displayed above the changes
         *
         * @param FormOptions $opts
+        * @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.
index 3a83d2b..b8fc05e 100644 (file)
@@ -470,7 +470,6 @@ 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;
@@ -488,7 +487,7 @@ abstract class QueryPage extends SpecialPage {
 
                if ( $this->isCached() && !$this->isCacheable() ) {
                        $out->addWikiMsg( 'querypage-disabled' );
-                       return 0;
+                       return;
                }
 
                $out->setSyndicated( $this->isSyndicated() );
@@ -578,8 +577,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
        }
 
        /**
index f968276..0070c74 100644 (file)
@@ -101,8 +101,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 +134,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() {
@@ -328,7 +328,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 ) {
index 9ff96ab..07b6b4e 100644 (file)
@@ -160,6 +160,7 @@ class SpecialPageFactory {
                'Emailuser' => 'SpecialEmailUser',
                'Movepage' => 'MovePageForm',
                'Mycontributions' => 'SpecialMycontributions',
+               'MyLanguage' => 'SpecialMyLanguage',
                'Mypage' => 'SpecialMypage',
                'Mytalk' => 'SpecialMytalk',
                'Myuploads' => 'SpecialMyuploads',
index e4b606d..04e2f11 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();
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 734544d..3367bd4 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
         */
index dcd2443..ad1d597 100644 (file)
@@ -61,7 +61,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;
@@ -230,7 +230,7 @@ class SpecialChangePassword extends FormSpecialPage {
        }
 
        /**
-        * @throws PasswordError when cannot set the new password because requirements not met.
+        * @throws PasswordError When cannot set the new password because requirements not met.
         */
        protected function attemptReset( $oldpass, $newpass, $retype ) {
                global $wgPasswordAttemptThrottle;
@@ -260,7 +260,7 @@ class SpecialChangePassword extends FormSpecialPage {
                        );
                }
 
-               // @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 251ac51..a884a39 100644 (file)
@@ -255,6 +255,9 @@ class SpecialContributions extends IncludableSpecialPage {
                                                wfEscapeWikiText( $userObj->getName() ),
                                        )
                                );
+                               if ( !$this->including() ) {
+                                       $this->getOutput()->setStatusCode( 404 );
+                               }
                        }
                        $user = htmlspecialchars( $userObj->getName() );
                } else {
index 355726a..76f2f4a 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 ) {
@@ -331,7 +347,7 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
         *
         * @return array
         */
-       private function getWatchlistInfo() {
+       protected function getWatchlistInfo() {
                $titles = array();
                $dbr = wfGetDB( DB_MASTER );
 
@@ -538,23 +554,26 @@ class SpecialEditWatchlist extends UnlistedSpecialPage {
                $count = 0;
 
                foreach ( $this->getWatchlistInfo() as $namespace => $pages ) {
-                       if ( $namespace >= 0 ) {
-                               $fields['TitlesNs' . $namespace] = array(
-                                       'class' => 'EditWatchlistCheckboxSeriesField',
-                                       'options' => array(),
-                                       'section' => "ns$namespace",
-                               );
-                       }
+                       $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();
 
@@ -763,8 +782,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..0958126 100644 (file)
@@ -175,7 +175,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 ) {
index 35a3ba1..ecbd353 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() {
index bc8e728..2cf5bfe 100644 (file)
@@ -302,7 +302,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)
@@ -536,7 +536,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..354960b 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();
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 03b3688..a67d3c0 100644 (file)
@@ -177,7 +177,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..10d1957 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
         */
index a77b70c..582f743 100644 (file)
@@ -217,12 +217,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 ) {
index cf11881..feeafbc 100644 (file)
@@ -193,7 +193,7 @@ class UsersPager extends AlphabeticPager {
                $edits = '';
                global $wgEdititis;
                if ( !$this->including && $wgEdititis ) {
-                       // @fixme i18n issue: Hardcoded square brackets.
+                       // @todo fixme i18n issue: Hardcoded square brackets.
                        $edits = ' [' .
                                $this->msg( 'usereditcount' )->numParams( $row->edits )->escaped() .
                                ']';
@@ -403,7 +403,7 @@ class SpecialListUsers extends IncludableSpecialPage {
         * 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 ced5d25..36abeb0 100644 (file)
@@ -119,7 +119,7 @@ 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 ) {
index 510055a..e1700de 100644 (file)
@@ -328,14 +328,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
@@ -477,7 +477,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 );
 
index 7223efd..ee144d6 100644 (file)
@@ -126,7 +126,7 @@ 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().
         */
diff --git a/includes/specials/SpecialMyLanguage.php b/includes/specials/SpecialMyLanguage.php
new file mode 100644 (file)
index 0000000..1f3c63f
--- /dev/null
@@ -0,0 +1,94 @@
+<?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 ) {
+               global $wgLanguageCode;
+               // 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 !== $wgLanguageCode && $proposed && $proposed->exists() ) {
+                       return $proposed;
+               } elseif ( $provided && $provided->exists() ) {
+                       return $provided;
+               } else {
+                       return $base;
+               }
+       }
+}
index 24eca07..ba972ce 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;
 
@@ -86,6 +86,10 @@ class SpecialPageLanguage extends FormSpecialPage {
                return $page;
        }
 
+       protected function postText() {
+               return $this->showLogFragment( $this->par );
+       }
+
        public function alterForm( HTMLForm $form ) {
                $form->setDisplayFormat( 'vform' );
                $form->setWrapperLegend( false );
@@ -178,4 +182,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 2707916..8c01ef2 100644 (file)
@@ -239,7 +239,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 aa8ed82..ea785fa 100644 (file)
@@ -229,9 +229,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;
                }
@@ -255,6 +254,15 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                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() );
        }
@@ -344,6 +352,9 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                                $this->msg( 'recentchanges-noresult' )->parse() .
                                '</div>'
                        );
+                       if ( !$this->including() ) {
+                               $this->getOutput()->setStatusCode( 404 );
+                       }
                } else {
                        $this->getOutput()->addHTML( $rclistOutput );
                }
@@ -353,8 +364,9 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
         * Set the text to be displayed above the changes
         *
         * @param FormOptions $opts
+        * @param int $numRows Number of rows in the result to show after this header
         */
-       public function doHeader( $opts ) {
+       public function doHeader( $opts, $numRows ) {
                global $wgScript;
 
                $this->setTopText( $opts );
@@ -364,7 +376,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 );
@@ -639,9 +651,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 ) {
+       function optionsPanel( $defaults, $nondefaults, $numRows ) {
                global $wgRCLinkLimits, $wgRCLinkDays;
 
                $options = $nondefaults + $defaults;
@@ -655,10 +668,15 @@ 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.
index e73cabc..9700638 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;
                }
@@ -221,6 +220,15 @@ class SpecialRecentChangesLinked extends SpecialRecentChanges {
                return $res;
        }
 
+       protected function runMainQueryHook( &$tables, &$select, &$conds, &$query_options, &$join_conds, $opts ) {
+               return parent::runMainQueryHook( $tables, $select, $conds, $query_options, $join_conds, $opts )
+               && wfRunHooks(
+                       'SpecialRecentChangesQuery',
+                       array( &$conds, &$tables, &$join_conds, $opts, &$query_options, &$select ),
+                       '1.23'
+               );
+       }
+
        function setTopText( FormOptions $opts ) {
                $target = $this->getTargetTitle();
                if ( $target ) {
index 4926d6d..774fd80 100644 (file)
@@ -66,7 +66,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 +85,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 +121,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 +141,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 +164,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 9cec847..93df289 100644 (file)
@@ -160,6 +160,14 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                if ( !$this->typeName || count( $this->ids ) == 0 ) {
                        throw new ErrorPageError( 'revdelete-nooldid-title', 'revdelete-nooldid-text' );
                }
+
+               # Allow the list type to adjust the passed target
+               $this->targetObj = RevisionDeleter::suggestTarget(
+                       $this->typeName,
+                       $this->targetObj,
+                       $this->ids
+               );
+
                $this->typeLabels = self::$UILabels[$this->typeName];
                $list = $this->getList();
                $list->reset();
@@ -170,13 +178,6 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                $pageIsSuppressed = $bitfield & Revision::DELETED_RESTRICTED;
                $this->mIsAllowed = $this->mIsAllowed && !( $canViewSuppressedOnly && $pageIsSuppressed );
 
-               # Allow the list type to adjust the passed target
-               $this->targetObj = RevisionDeleter::suggestTarget(
-                       $this->typeName,
-                       $this->targetObj,
-                       $this->ids
-               );
-
                $this->otherReason = $request->getVal( 'wpReason' );
                # We need a target page!
                if ( is_null( $this->targetObj ) ) {
index 4c8c8f3..54f224a 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 );
@@ -75,18 +75,28 @@ 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 );
+                       }
                }
        }
 
@@ -100,52 +110,4 @@ class SpecialRunJobs extends UnlistedSpecialPage {
                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 );
-               }
-       }
 }
index 15a7b59..1caed0b 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
@@ -346,6 +347,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,
@@ -406,7 +410,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 +427,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 +445,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>' );
@@ -798,7 +804,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
         */
@@ -1081,7 +1087,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,7 +1096,7 @@ class SpecialSearch extends SpecialPage {
                ) . "\n";
 
                // Results-info
-               if ( $totalNum > 0 ) {
+               if ( $totalNum > 0 && $this->offset < $totalNum ) {
                        $top = $this->msg( 'showingresultsheader' )
                                ->numParams( $this->offset + 1, $this->offset + $resultsShown, $totalNum )
                                ->params( wfEscapeWikiText( $term ) )
index 04b36c7..25f520e 100644 (file)
@@ -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...
index fc18706..4fd7cd4 100644 (file)
@@ -1144,7 +1144,7 @@ class UploadForm extends HTMLForm {
        /**
         * Empty function; submission is handled elsewhere.
         *
-        * @return bool false
+        * @return bool False
         */
        function trySubmit() {
                return false;
index 75ab19f..cb821cb 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
         */
@@ -227,7 +227,7 @@ 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
index 1ef96c3..46b4999 100644 (file)
@@ -1048,7 +1048,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
@@ -1214,6 +1214,7 @@ class LoginForm extends SpecialPage {
                $out->addModuleStyles( array(
                        'mediawiki.ui',
                        'mediawiki.ui.button',
+                       'mediawiki.ui.input',
                        'mediawiki.special.userlogin.common.styles'
                ) );
                $out->addModules( array(
index 411970e..0ec85ba 100644 (file)
@@ -715,7 +715,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 28ad0f4..8ca9e23 100644 (file)
@@ -307,7 +307,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 +349,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() {
index 94de5ce..5691e50 100644 (file)
@@ -83,7 +83,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 ) {
@@ -279,9 +279,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 +291,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
         *
@@ -391,8 +398,9 @@ class SpecialWatchlist extends ChangesListSpecialPage {
         * Set the text to be displayed above the changes
         *
         * @param FormOptions $opts
+        * @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(
@@ -406,7 +414,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";
                }
index 694bc83..60ac02f 100644 (file)
@@ -151,7 +151,7 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
                        $conds['pagelinks'][] = 'rd_from is NOT NULL';
                }
 
-               $queryFunc = function( $dbr, $table, $fromCol ) use ( $conds, $target, $limit ) {
+               $queryFunc = function ( $dbr, $table, $fromCol ) use ( $conds, $target, $limit ) {
                        global $wgUseLinkNamespaceDBFields;
                        // Read an extra row as an at-end check
                        $queryLimit = $limit + 1;
@@ -163,14 +163,17 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
                        if ( $wgUseLinkNamespaceDBFields ) { // migration check
                                $on['rd_namespace'] = $target->getNamespace();
                        }
-                       // Inner LIMIT is 2X in case of stale backlinks with no page
+                       // Inner LIMIT is 2X in case of stale backlinks with wrong namespaces
                        $subQuery = $dbr->selectSqlText(
-                               array( $table, 'redirect' ),
+                               array( $table, 'page', 'redirect' ),
                                array( $fromCol, 'rd_from' ),
                                $conds[$table],
                                __CLASS__ . '::showIndirectLinks',
                                array( 'ORDER BY' => $fromCol, 'LIMIT' => 2 * $queryLimit ),
-                               array( 'redirect' => array( 'LEFT JOIN', $on ) )
+                               array(
+                                       'page' => array( 'INNER JOIN', "$fromCol = page_id" ),
+                                       'redirect' => array( 'LEFT JOIN', $on )
+                               )
                        );
                        return $dbr->select(
                                array( 'page', 'temp_backlink_range' => "($subQuery)" ),
@@ -208,6 +211,7 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
                                        }
                                        $errMsg = is_int( $namespace ) ? 'nolinkshere-ns' : 'nolinkshere';
                                        $out->addWikiMsg( $errMsg, $this->target->getPrefixedText() );
+                                       $out->setStatusCode( 404 );
                                }
                        }
 
index a4240e2..f1e7065 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',
@@ -109,7 +109,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 +129,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 +139,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 +161,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 +176,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 +189,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',
@@ -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 bab544b..7187e8c 100644 (file)
@@ -72,7 +72,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',
@@ -102,7 +102,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',
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..12b7143 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
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..6a6b358 100644 (file)
@@ -283,7 +283,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__ );
@@ -379,8 +379,8 @@ abstract class UploadBase {
        /**
         * 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.
+        * @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
         * @return mixed True if the file is verified, an array otherwise
         */
@@ -388,7 +388,7 @@ abstract class UploadBase {
                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__ );
@@ -593,7 +593,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.
         */
@@ -1276,8 +1276,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 ) {
index 6f90280..bea7128 100644 (file)
@@ -68,7 +68,7 @@ class UploadFromChunks extends UploadFromFile {
         * 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..23a7a3a 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 ) {
@@ -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..b97e2ad 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 );
 
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 aa86ea4..8610386 100644 (file)
@@ -101,7 +101,7 @@ class MWCryptHKDF {
        /**
         * @param string $hash 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 +133,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 +189,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 +237,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 +256,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 $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
         */
        private static function HKDFExtract( $hash, $salt, $ikm ) {
                return hash_hmac( $hash, $ikm, $salt, true );
@@ -268,16 +268,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];
@@ -306,9 +306,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 +318,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..31a71c4 100644 (file)
@@ -147,7 +147,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 +214,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 +259,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 +270,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 +487,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 +503,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..604d381 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
         */
@@ -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 454a97b..0f56e33 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.
         *
@@ -181,6 +181,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 +301,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'];
@@ -483,6 +485,7 @@ class ZipDirectoryReader {
 
        /**
         * Get the length of the file.
+        * @return int
         */
        function getFileLength() {
                if ( $this->fileLength === null ) {
@@ -659,7 +662,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
         */
@@ -669,6 +672,7 @@ class ZipDirectoryReader {
 
        /**
         * Debugging helper function which dumps a string in hexdump -C format.
+        * @param string $s
         */
        function hexDump( $s ) {
                $n = strlen( $s );
index 887490b..8b41b4e 100644 (file)
@@ -2396,7 +2396,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 ) );
@@ -3125,7 +3125,7 @@ class Language {
         */
        function getMagic( $mw ) {
                // Saves a function call
-               if ( ! $this->mMagicHookDone ) {
+               if ( !$this->mMagicHookDone ) {
                        $this->doMagicHook();
                }
 
@@ -3795,7 +3795,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] );
@@ -4443,7 +4443,7 @@ class Language {
                if ( !isset( $format['avoid'] ) ) {
                        $format['avoid'] = false;
                }
-               if ( !isset( $format['noabbrevs' ] ) ) {
+               if ( !isset( $format['noabbrevs'] ) ) {
                        $format['noabbrevs'] = false;
                }
                $secondsMsg = wfMessage(
index 4c956f0..1d279d6 100644 (file)
@@ -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..3d05b81 100644 (file)
@@ -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..f74be05 100644 (file)
@@ -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..a22730c 100644 (file)
@@ -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..80099ac 100644 (file)
@@ -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 c3e146a..9cb0166 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",
        "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",
        "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 8070e2d..1381688 100644 (file)
        "license": "ترخيص:",
        "license-header": "ترخيص",
        "nolicense": "غير محدد",
+       "licenses-edit": "عدل خيارات الترخيص",
        "license-nopreview": "(العرض المسبق غير متوفر)",
        "upload_source_url": "  (مسار صحيح، يمكن الوصول إليه)",
        "upload_source_file": " (ملف على حاسوبك)",
        "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": "يراقب...",
index 1669b9d..b3cf3a2 100644 (file)
@@ -24,7 +24,8 @@
                        "לערי ריינהארט",
                        "아라",
                        "Arystanbek",
-                       "Dağlı95"
+                       "Dağlı95",
+                       "Sayginer"
                ]
        },
        "tog-underline": "Keçidlərin altını xətlə:",
        "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.",
        "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",
        "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",
        "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 16385c7..d8ce916 100644 (file)
@@ -31,6 +31,7 @@
        "tog-watchdefault": "Дадаваць у мой сьпіс назіраньня старонкі і файлы, якія я {{GENDER:|рэдагаваў|рэдагавала}}",
        "tog-watchmoves": "Дадаваць у мой сьпіс назіраньня перанесеныя мною старонкі і файлы",
        "tog-watchdeletion": "Дадаваць у мой сьпіс назіраньня старонкі і файлы, якія я выдаляю",
+       "tog-watchrollback": "Дадаваць у мой сьпіс назіраньня старонкі, дзе я {{GENDER:|зрабіў|зрабіла}} адкат",
        "tog-minordefault": "Па змоўчаньні пазначаць усе мае праўкі дробнымі",
        "tog-previewontop": "Паказваць папярэдні прагляд старонкі над полем рэдагаваньня",
        "tog-previewonfirst": "Папярэдні прагляд пры першым рэдагаваньні",
        "preview": "Папярэдні прагляд",
        "showpreview": "Праглядзець",
        "showdiff": "Паказаць зьмены",
+       "blankarticle": "<strong>Папярэджаньне:</strong> вы ствараеце пустую старонку.\nКалі вы націсьніце «{{int:savearticle}}» яшчэ раз, старонка будзе створаная без аніякага зьместу.",
        "anoneditwarning": "'''Папярэджаньне:''' Вы не ўвайшлі ў сыстэму. Ваш IP-адрас будзе запісаны ў гісторыі гэтай старонкі.",
        "anonpreviewwarning": "''Вы не ўвайшлі ў сыстэму. Падчас захаваньня Ваш IP-адрас будзе дададзены ў гісторыю рэдагаваньняў старонкі.''",
        "missingsummary": "'''Напамін:''' Вы не пазначылі кароткае апісаньне зьменаў.\nКалі Вы націсьніце кнопку «Запісаць» яшчэ раз, Вашае рэдагаваньне будзе запісанае без апісаньня.",
        "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}}}} журнале выдаленьняў].",
        "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": "Паказаць",
        "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": "Пошук па назьве файла:",
        "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|паказаная '''$1''' апошняя зьмена|паказаныя '''$1''' апошнія зьмены|паказаныя '''$1''' апошніх зьменаў}} за '''$2''' {{PLURAL:$2|гадзіну|гадзіны|гадзінаў}}, па стане на $3, $4.",
        "wlshowlast": "Паказаць: за апошнія $1 гадзінаў, $2 дзён, $3",
        "watchlist-options": "Налады сьпісу назіраньня",
        "watching": "Дадаецца ў сьпіс назіраньня…",
        "import-upload": "Загрузіць XML-зьвесткі",
        "import-token-mismatch": "Страчаныя зьвесткі сэсіі. Калі ласка, паспрабуйце ізноў.",
        "import-invalid-interwiki": "Немагчыма імпартаваць з вызначанай вікі.",
-       "import-error-edit": "Старонка «$1» не імпартаваная, бо Вы ня маеце правоў на яе рэдагаваньне.",
+       "import-error-edit": "Старонка «$1» не была імпартаваная, бо Вы ня маеце правоў на яе рэдагаваньне.",
        "import-error-create": "Старонка «$1» не імпартаваная, бо Вы ня маеце правоў на яе стварэньне.",
        "import-error-interwiki": "Старонка «$1» не была імпартаваная, таму што гэтая назва зарэзэрваваная для інтэрвікі.",
        "import-error-special": "Старонка «$1» не была імпартаваная, таму што яна належыць да спэцыяльнай прасторы назваў, старонкі ў якой не дазволеныя.",
        "autosumm-replace": "Старонка замененая на '$1'",
        "autoredircomment": "Перанакіроўвае на [[$1]]",
        "autosumm-new": "Створана старонка са зьместам '$1'",
+       "autosumm-newblank": "Створаная пустая старонка",
        "size-bytes": "$1 б",
        "size-kilobytes": "$1 кб",
        "size-megabytes": "$1 Мб",
index cfae5f8..6b7f88a 100644 (file)
@@ -39,6 +39,7 @@
        "tog-watchdefault": "Дабаўляць старонкі і файлы пасля маіх правак у мой спіс назірання",
        "tog-watchmoves": "Дабаўляць перайменаваныя мной старонкі і файлы ў мой спіс назірання",
        "tog-watchdeletion": "Дабаўляць сцёртыя мной старонкі і файлы ў мой спіс назірання",
+       "tog-watchrollback": "Дадаваць старонкі, дзе я {{GENDER:|зрабіў|зрабіла}} адкат, у мой спіс назірання",
        "tog-minordefault": "Пачынаць кожную праўку як дробную",
        "tog-previewontop": "Папярэдні паказ — над рэдактарскім полем",
        "tog-previewonfirst": "Папярэдні паказ пры першай праўцы",
        "preview": "Перадпаказ",
        "showpreview": "Як будзе",
        "showdiff": "Розніца",
+       "blankarticle": "<strong>Увага:</strong> Вы ствараеце пустую старонку.\nКалі вы націсніце \"{{int:savearticle}}\" яшчэ раз, будзе створана старонка без аніякага зместу.",
        "anoneditwarning": "Вы не ўвайшлі ў сістэму. Таму, калі вы запішаце старонку, у яе гісторыю трапіць ваш адрас IP.",
        "anonpreviewwarning": "''Вы не прайшлі ідэнтыфікацыю Захаванне будзе запісана з вашым IP адрасам у гісторыі правак гэтай старонкі.''",
        "missingsummary": "<strong>Нагадваем:</strong> вы не ўпісалі тлумачэння для сваёй праўкі. Калі націснуць \"{{int:savearticle}}\" яшчэ раз, праўка будзе замацавана без тлумачэння.",
        "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}}}} журнале сціранняў].",
        "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": "Паказаць",
        "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": "Знайсці назву выявы:",
        "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": "Найстарэйшыя старонкі",
        "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": "Дапісваецца ў спіс назірання...",
        "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>",
        "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": "Створана пустая старонка",
        "lag-warn-normal": "Змены, зробленыя менш за $1 {{PLURAL:$1|сек.|сек.}} таму назад, могуць не трапіць у гэты спіс.",
        "lag-warn-high": "З прычыны моцных затрымак на серверы баз звестак, змены, зробленыя менш за $1 {{PLURAL:$1|сек.|сек.}} таму назад, могуць не трапіць у гэты спіс.",
        "watchlistedit-normal-title": "Спіс назірання",
index 07a5a29..5ac6601 100644 (file)
        "watchlist-details": "আপনার নজরতালিকাতে {{PLURAL:$1|$1টি পাতা}} আছে (আলাপ পাতাগুলি গণনায় না ধরে)।",
        "wlheader-enotif": "ইমেল বিজ্ঞপ্তি সক্রিয় করা আছে।",
        "wlheader-showupdated": "আপনার শেষ আগমনের পর থেকে যেসব পাতায় পরিবর্তন হয়েছে সেগুলি '''গাঢ়''' করে দেখানো হয়েছে।",
-       "wlnote2": "$3, $2 অনুসারে, সর্বশেষ {{PLURAL:$1|ঘণ্টার|<strong>$1</strong> ঘণ্টার}} পরিবর্তন নিচে দেয়া হয়েছে।",
+       "wlnote": "নিচে $3, $4 তারিখ থেকে বিগত {{PLURAL:$2|১ ঘন্টায়|'''$2''' ঘন্টায়}} সংঘটিত {{PLURAL:$1|শেষ ১টি পরিবর্তন|শেষ '''$1'''টি পরিবর্তন}} দেখানো হল।",
        "wlshowlast": "দেখাও সর্বশেষ  $1 ঘণ্টা $2 দিন $3",
        "watchlist-options": "নজর তালিকা পছন্দসমূহ",
        "watching": "নজর রাখা হচ্ছে...",
        "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": "এই পাতাটি জাভাস্ক্রিপ্ট পরীক্ষার জন্য সংরক্ষিত।",
        "autosumm-replace": "পাতাকে '$1' দিয়ে প্রতিস্থাপিত করা হল",
        "autoredircomment": "[[$1]]-এ পুনর্নির্দেশ করা হল",
        "autosumm-new": "$1 দিয়ে তৈরি পাতা",
+       "autosumm-newblank": "খালি পাতা তৈরি হয়েছে",
        "size-bytes": "$1 বাইট",
        "size-kilobytes": "$1 কিলোবাইট",
        "size-megabytes": "$1 মেগাবাইট",
index 0198e96..3978647 100644 (file)
        "talkpagelinktext": "Kaozeal",
        "specialpage": "Pajenn dibar",
        "personaltools": "Ostilhoù personel",
-       "postcomment": "Rann nevez",
        "articlepage": "Sellet ouzh ar pennad",
        "talk": "Kaozeadenn",
        "views": "Gweladennoù",
        "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ñ",
        "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",
        "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)",
+       "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",
        "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-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ñ",
        "watchlist-details": "Lakaet hoc'h eus {{PLURAL:$1|$1 bajenn|$1 pajenn}} dindan evezh, 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}} ziwezhañ, evit an $3 da $4.",
        "wlshowlast": "Diskouez an $1 eurvezh $2 devezh diwezhañ $3",
        "watchlist-options": "Dibarzhioù ar roll evezhiañ",
        "watching": "Heuliet...",
        "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-removed": "Tennet ez eus bet {{PLURAL:$1|1 pajenn|$1 pajenn}} :",
        "watchlistedit-clear-legend": "Diverkañ ar roll-evezhiañ",
        "watchlistedit-clear-titles": "Titloù :",
+       "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",
        "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"
 }
index 98a8f98..fac19cc 100644 (file)
        "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.",
        "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...",
        "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",
        "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",
index 25ce027..bb47166 100644 (file)
        "right-browsearchive": "Cercar pàgines esborrades",
        "right-undelete": "Restaurar pàgines esborrades",
        "right-suppressrevision": "Revisar i restaurar les versions amagades als administradors",
+       "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",
        "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)",
        "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.",
        "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 '''$1''' canvis}} en {{PLURAL:$2|la darrera hora|les  '''$2''' 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...",
index f69fec2..d525b7b 100644 (file)
@@ -6,7 +6,9 @@
                        "Yejianfei",
                        "Hakka",
                        "아라",
-                       "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": "躒出",
index 1f6960d..b14dcbe 100644 (file)
        "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=цхьаъ бен файл яц}}.",
        "preview": "Хьалха муха ю хьажа",
        "showpreview": "Хьалха муха ю хьажар",
        "showdiff": "Хlоттина болу хийцам",
+       "blankarticle": "<strong>ДӀахьедар:</strong> Ахьа кхуллуш йолу агӀо еса ю.\nЮху кнопка «{{int:savearticle}}» тӀетаӀаяхь, агӀо цхьа чулацам боцуш кхуллур ю.",
        "anoneditwarning": "'''Тергам бе''': Ахьа хьай цӀарца тадарш деш дац. Хьан IP-адрес дӀаяздина хира ду хӀокху агӀон истори чу.",
        "anonpreviewwarning": "''Системин чу цагӀахь хьан IP-адрес агӀона истори чу дӀаяз лур ду.''",
        "missingcommenttext": "Дехар до дӀаязбе хайн хаам лахахь.",
        "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}}}} дӀаяьхнарш йолу тептар чохь].",
        "license": "Бакъойалар:",
        "license-header": "Бакъойалар",
        "nolicense": "Яц",
+       "licenses-edit": "Лицензин параметраш хийца",
        "license-nopreview": "(Хьалха муха ю хьажа цало)",
-       "upload_source_file": " (файл хьан компьютер чохь ю)",
+       "upload_source_file": "(файл хьан компьютер чохь ю)",
        "listfiles-delete": "дӀаяккха",
        "listfiles-summary": "Лахахь гойтуш ю ерриг файлаш.\nДекъашхо къастичи, цун керла файлаш гойту.",
        "listfiles_search_for": "Лаха хIуман цIарца:",
        "mostimages": "Массарел дуккха лелайо файлаш",
        "mostinterwikis": "Дуккха юкъарвики хьажоргаш тӀе тоьхна йолу агӀонаш",
        "mostrevisions": "Сих сиха нисйина йолу агӀонаш",
-       "prefixindex": "Ð¥Ñ\8cалÑ\85а Ð°Ð³Ó\80онаÑ\88ан Ñ\86Ó\80еÑ\80аÑ\88 Ñ\85Ó\80оÑ\82Ñ\82о Ð¹еза",
+       "prefixindex": "Ð¥Ñ\8cалÑ\85а Ð°Ð³Ó\80онийн Ñ\86Ó\80еÑ\80аÑ\88 Ñ\85Ó\80оÑ\82Ñ\82о еза",
        "prefixindex-namespace": "Хьалха агӀонашан цӀераш хӀотто еза («{{ns:$1}}»)",
        "prefixindex-strip": "Хиламийн могӀам чура префикс къайлаяккха",
        "shortpages": "Боца яззамаш",
        "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огаман юкъаяккха…",
        "undelete-error-long": "Файл меттахӀоттош гӀалат даьлла:\n\n$1",
        "undelete-show-file-submit": "Хlаъ",
        "namespace": "Цlерийн ана:",
-       "invert": "Хаьржинарг хилийта",
+       "invert": "Хаьржинарг къайлаяккха",
        "tooltip-invert": "ХӀоттае хӀара билгало, хаьржинчу цӀерийн меттиган агӀонашан хийцамаш къайлабаха (кхин дихкина цӀерийн меттигаш, гайтина елахь)",
        "namespace_association": "Йихкина меттиг",
        "tooltip-namespace_association": "ХӀоттае хӀара билгало, иштта дийцарийн (я кхин) цӀерийн меттиг юкъахь хилийта",
        "sp-contributions-newonly": "АгӀонаш кхоллар бен ма гайта",
        "sp-contributions-submit": "Лаха",
        "whatlinkshere": "Хьажоргаш кхузе",
-       "whatlinkshere-title": "ХӀокхунца «$1» йолу агӀонаш",
+       "whatlinkshere-title": "«$1» тӀе хьажоргаш йолу агӀонаш",
        "whatlinkshere-page": "Агlо:",
        "linkshere": "ТӀаьхьайогӀу агӀонаш оцу '''[[:$1]]''': хьажорагца ю",
        "nolinkshere": "ХӀокху '''[[:$1]]''' агӀона тӀе кхечу агӀонашкахь хьажоргаш яц.",
        "import-upload": "Чуяха XML-хаамаш",
        "import-token-mismatch": "Сеансан хаамаш дӀадайна. Дехар до, юху гӀорта.",
        "import-invalid-interwiki": "Билгалйина вики чура импорт ян йиш яц.",
-       "import-error-special": "«$1» агӀо импорт йина яц, и къастина цӀерийн меттигашан юкъайогӀуш хиларна.",
+       "import-error-edit": "«$1» агӀо хьуна таян цамагор бахьнехь и импорт цайина.",
+       "import-error-special": "«$1» агӀо импорт йина яц, и къастина цӀерийн меттигийн юкъайогӀуш хиларна.",
+       "import-error-invalid": "«$1» агӀо импорт цайина, оцунна импорт еш йолу цӀе хӀокху вики чохь ца магийна хилар бахьнехь.",
        "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о",
        "minutes-abbrev": "$1 мин",
        "hours-abbrev": "$1 сахь.",
        "seconds": "{{PLURAL:$1|$1 секунд|$1 секунд}}",
-       "minutes": "{{PLURAL:$1|$1 минут|$1 минут}}",
+       "minutes": "{{PLURAL:$1|$1 минот|$1 минот}}",
        "hours": "{{PLURAL:$1|$1 сахьт|$1 сахьт}}",
        "days": "{{PLURAL:$1|$1 де|$1 де}}",
        "weeks": "{{PLURAL:$1|$1 кӀира}}",
        "ago": "$1 хьалха",
        "just-now": "хӀинца",
        "hours-ago": "$1 {{PLURAL:$1|сахьт}}",
-       "minutes-ago": "$1 {{PLURAL:$1|минут}} хьалха",
+       "minutes-ago": "$1 {{PLURAL:$1|минот}} хьалха",
        "seconds-ago": "$1 {{PLURAL:$1|секунд}} хьалха",
        "monday-at": "оршотан дийнахь $1",
        "tuesday-at": "шинара дийнахь $1",
        "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|йозан кепар могӀом нисба ]].",
        "watchlisttools-clear": "Тергаман могӀам дӀацӀанбан",
        "watchlisttools-view": "МогӀам чура агӀонашан хийцамаш",
        "watchlisttools-edit": "Хьажа/нисбé могӀам",
-       "watchlisttools-raw": "Йоза санна нисдé",
+       "watchlisttools-raw": "Йоза санна тае",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|дийцаре]])",
        "version": "Верси MediaWiki",
        "version-extensions": "ДӀахӀоттийна шордарш",
        "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|кӀира}}",
index 250b228..8eb7191 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",
        "preview": "Náhled",
        "showpreview": "Ukázat náhled",
        "showdiff": "Ukázat změny",
+       "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). Vaše IP adresa bude zveřejněna v historii této stránky.",
        "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í.",
        "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].",
        "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",
        "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…",
        "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.",
index c5b8ca4..e99fb4d 100644 (file)
@@ -91,6 +91,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 der Beobachtungsliste hinzufügen, bei denen ich eine Zurücksetzung durchgeführt habe.",
        "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",
        "preview": "Vorschau",
        "showpreview": "Vorschau zeigen",
        "showdiff": "Änderungen zeigen",
+       "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": "Du bearbeitest diese Seite unangemeldet. Wenn du sie abspeicherst, wird deine aktuelle IP-Adresse in der Versionsgeschichte aufgezeichnet und ist damit unwiderruflich '''öffentlich''' einsehbar.",
        "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.",
        "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].",
        "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": "Spezielle Seitenversionen von jedem Benutzer ansehen, verstecken und wiederherstellen",
-       "right-viewsuppressed": "Versteckte Versionen von jedem Benutzer ansehen",
+       "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",
        "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:",
        "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 …",
        "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",
index 4f6e294..6641fbd 100644 (file)
        "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",
        "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",
        "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:",
        "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",
index e42d716..d506ad2 100644 (file)
@@ -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",
        "preview": "Preview",
        "showpreview": "Show preview",
        "showdiff": "Show changes",
+       "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.\nYour IP address will be recorded in this page's edit history.",
        "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.",
        "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].",
        "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",
        "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:",
        "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...",
        "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",
index 340ff8a..3cf01bc 100644 (file)
        "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...",
index deec915..b8e5683 100644 (file)
                        "Wifidel",
                        "Macofe",
                        "Koavf",
-                       "Themasterriot"
+                       "Themasterriot",
+                       "AVIADOR"
                ]
        },
        "tog-underline": "Subrayar los enlaces:",
        "preview": "Previsualizar",
        "showpreview": "Mostrar previsualización",
        "showdiff": "Mostrar los cambios",
+       "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.\nTu dirección IP se almacenará en el historial de edición de esta página.",
        "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.",
        "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].",
        "right-browsearchive": "Buscar páginas borradas",
        "right-undelete": "Restaurar una página",
        "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",
        "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:",
        "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...",
        "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",
index 794dbe7..9e7ebb1 100644 (file)
        "preview": "Eelvaade",
        "showpreview": "Näita eelvaadet",
        "showdiff": "Näita muudatusi",
+       "blankarticle": "<strong>Hoiatus:</strong> Lehekülg, mida alustad, on tühi.\nKui klõpsad uuesti \"{{int:savearticle}}\", luuakse lehekülg ilma sisuta.",
        "anoneditwarning": "'''Hoiatus:''' Sa pole sisse logitud.\nSelle lehe redigeerimislogisse salvestatakse su IP-aadress.",
        "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.",
        "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.",
        "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.",
        "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",
        "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 '''$1''' muudatust}} viimase {{PLURAL:$2|tunni|'''$2''' tunni}} jooksul seisuga $3, $4.",
        "wlshowlast": "Näita viimast $1 tundi $2 päeva. $3",
        "watchlist-options": "Jälgimisloendi seaded",
        "watching": "Jälgimine...",
        "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-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",
index cc18333..51e07bd 100644 (file)
        "preview": "پیش‌نمایش",
        "showpreview": "پیش‌نمایش",
        "showdiff": "نمایش تغییرات",
+       "blankarticle": "<strong>هشدار:</strong> شما در حال ایجاد صفحه خالی هستید.\nاگر \"{{int:savearticle}}\" را دوباره کلیک کنید، صفحه بدون محتوا ایجاد می‌شود.",
        "anoneditwarning": "'''هشدار:''' شما به سامانه وارد نشده‌اید.\nنشانی آی‌پی شما در تاریخچهٔ ویرایش این صفحه ثبت خواهد شد.",
        "anonpreviewwarning": "''شما به سامانه وارد نشده‌اید. ذخیره کردن باعث می‌شود که نشانی آی‌پی شما در تاریخچهٔ این صفحه ثبت گردد.''",
        "missingsummary": "'''یادآوری:''' شما خلاصهٔ ویرایش ننوشته‌اید.\nاگر دوباره دکمهٔ «{{int:savearticle}}» را فشار دهید ویرایش شما بدون آن ذخیره خواهد شد.",
        "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": "تنظیم محدودیت‌های پیدایی",
        "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>$3, $4</strong> (تا <strong>$1</strong> {{PLURAL:$5|نشان داده شده‌است|نشان داده شده‌اند}}).",
        "rclistfrom": "نمایش تغییرات جدید با شروع از $3 $2",
        "rcshowhideminor": "$1 ویرایش‌های جزئی",
        "rcshowhideminor-show": "نمایش",
        "watchlist-details": "بدون احتساب صفحه‌های جداگانهٔ بحث، {{PLURAL:$1|$1 صفحه|$1 صفحه}} در فهرست پی‌گیری‌های شما قرار {{PLURAL:$1|دارد|دارند}}.",
        "wlheader-enotif": "آگاه‌سازی رایانامه‌ای فعال است.",
        "wlheader-showupdated": "صفحه‌هایی که پس از آخرین بازدید شما تغییر کرده‌اند '''پررنگ''' نمایش داده شده‌اند.",
-       "wlnote2": "در زیر تغییرات اخیر وجود دارد {{PLURAL:$1|ساعت|<strong>$1</strong> ساعت‌ها}}, به عنوان $2, $3.",
+       "wlnote": "در زیر {{PLURAL:$1|تغییری|$1 تغییری}} که در {{PLURAL:$2|ساعت|$2 ساعت}} گذشته انجام شده موجود است، تاریخ آخرین بازیابی: $3، $4",
        "wlshowlast": "نمایش آخرین $1 ساعت $2 روز $3",
        "watchlist-options": "گزینه‌های پی‌گیری",
        "watching": "پی‌گیری...",
        "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>",
        "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": "آزمایش جاوا اسکریپت",
        "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 مگابایت",
index 15b04aa..739356f 100644 (file)
@@ -57,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",
        "preview": "Esikatselu",
        "showpreview": "Esikatsele",
        "showdiff": "Näytä muutokset",
+       "blankarticle": "<strong>Varoitus:</strong> Sivu, jota olet luomassa, on tyhjä.\nJos napsautat \"{{int:savearticle}}\" uudelleen, sivu luodaan ilman sisältöä.",
        "anoneditwarning": "'''Varoitus:''' Et ole kirjautunut sisään.\nIP-osoitteesi kirjataan tämän sivun muutoshistoriaan.",
        "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.",
        "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].",
        "right-browsearchive": "Hakea poistettuja sivuja",
        "right-undelete": "Palauttaa poistettuja sivuja",
        "right-suppressrevision": "Katsoa, piilottaa ja tuoda näkyviin tiettyjä sivujen versioita kaikilta käyttäjiltä",
-       "right-viewsuppressed": "Katsoa kaikilta käyttäjiltä piilotettuja versioita",
+       "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ä",
        "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",
        "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.",
+       "wlnote": "Alla on {{PLURAL:$1|yksi muutos|<strong>$1</strong> muutosta}} viimeisen {{PLURAL:$2|tunnin|<strong>$2</strong> tunnin}} ajalta $3 kello $4 asti.",
        "wlshowlast": "Näytä viimeiset $1 tuntia tai $2 päivää, $3",
        "watchlist-options": "Tarkkailulistan asetukset",
        "watching": "Lisätään tarkkailulistalle...",
        "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",
index 8f6c670..edd5e2c 100644 (file)
                        "Linedwell",
                        "Yona b",
                        "SnowedEarth",
-                       "Orikrin1998"
+                       "Orikrin1998",
+                       "Automatik"
                ]
        },
        "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 annulation",
        "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",
        "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",
        "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 »",
        "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.",
        "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}}",
        "preview": "Prévisualisation",
        "showpreview": "Prévisualiser",
        "showdiff": "Voir les modifications",
+       "blankarticle": "<strong>Attention :</strong> La page que vous créez est vide.\nSi vous cliquez de nouveau sur « {{int:savearticle}} », la page sera créée sans aucun contenu.",
        "anoneditwarning": "<strong>Attention :</strong> Vous n’êtes pas identifié(e). Votre adresse IP sera enregistrée dans l’historique de cette page.",
        "anonpreviewwarning": "''Vous n’êtes pas identifié(e). Sauvegarder enregistrera votre adresse IP dans l’historique des modifications de la page.''",
        "missingsummary": "'''Rappel :''' vous n'avez pas encore fourni le résumé de votre modification.\nSi vous cliquez de nouveau sur le bouton « {{int:savearticle}} », la publication sera faite sans nouvel avertissement.",
        "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].",
        "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",
        "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 :",
        "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…",
        "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.",
        "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",
        "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",
        "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",
index 8320af5..e3f8bbb 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": "退出",
        "watchlist-details": "$1隻頁面(伓算討論頁) 拕眏到哩",
        "wlheader-enotif": "啟動哩email通知功能。",
        "wlheader-showupdated": "上回倷眵嗰頁面改動嗰部分用'''粗體'''顯到",
+       "wlnote": "下底係最近'''$2'''鐘頭內嗰最晏'''$1'''道修改:",
        "wlshowlast": "顯示箇日子$1鐘頭$2日$3嗰改動",
        "watchlist-options": "監視清單選項",
        "watching": "眏到...",
index bf20771..8b1a199 100644 (file)
@@ -14,7 +14,8 @@
                        "Vivaelcelta",
                        "Xosé",
                        "לערי ריינהארט",
-                       "Fitoschido"
+                       "Fitoschido",
+                       "McDutchie"
                ]
        },
        "tog-underline": "Subliñar as ligazóns:",
        "preview": "Vista previa",
        "showpreview": "Mostrar a vista previa",
        "showdiff": "Mostrar os cambios",
+       "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": "'''Aviso:''' Non accedeu ao sistema.\nO seu enderezo IP quedará rexistrado no historial de revisións desta páxina.",
        "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.",
        "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].",
        "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",
        "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 '''$1''' modificacións}} {{PLURAL:$2|na última hora|nas últimas '''$2''' 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...",
        "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.",
        "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}}.",
index a900ad5..b781900 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": "登出",
        "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 d7d77c3..df559b0 100644 (file)
@@ -43,6 +43,7 @@
        "tog-watchdefault": "מעקב אחרי דפים וקבצים שערכתי",
        "tog-watchmoves": "מעקב אחרי דפים וקבצים שהעברתי",
        "tog-watchdeletion": "מעקב אחרי דפים וקבצים שמחקתי",
+       "tog-watchrollback": "מעקב אחרי דפים ששחזרתי",
        "tog-minordefault": "הגדרת כל פעולת עריכה כמשנית אם לא צוין אחרת",
        "tog-previewontop": "הצגת תצוגה מקדימה לפני תיבת העריכה",
        "tog-previewonfirst": "הצגת תצוגה מקדימה בעריכה ראשונה",
        "preview": "תצוגה מקדימה",
        "showpreview": "תצוגה מקדימה",
        "showdiff": "הצגת שינויים",
+       "blankarticle": "<strong>אזהרה:</strong> הדף שאתם יוצרים הוא ריק.\nאם תלחצו שוב על \"{{int:savearticle}}\", הדף ייווצר ללא תוכן.",
        "anoneditwarning": "'''אזהרה:''' אינכם מחוברים לחשבון. כתובת ה־IP שלכם תירשם בהיסטוריית העריכות של הדף.",
        "anonpreviewwarning": "''אינכם מחוברים לחשבון. שמירה תגרום לכתובת ה־IP שלכם להירשם בהיסטוריית העריכות של הדף.''",
        "missingsummary": "'''תזכורת:''' לא הזנתם תקציר עריכה.\nאם תלחצו שוב על הכפתור \"{{int:savearticle}}\", עריכתכם תישמר בלעדיו.",
        "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נת \"{{int:emailuser}}\", ×\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|העדפות המשתמש]] שלכם.",
        "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": "מחיקה ושחזור של גרסאות",
        "logdelete-text": "פעולות יומן שנמחקו עדיין תופענה בדפי היומנים, אך חלקים מהתוכן שלהן לא יהיו זמינים לציבור.",
        "revdelete-text-others": "מפעילי מערכת אחרים עדיין יוכלו לגשת לתוכן הנסתר כדי לשחזר אותו, אלא אם כן תוגדרנה הגבלות נוספות.",
        "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'''לפחות גרסה אחת של דף המקור חייבת להישאר בו.'''",
        "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": "שמירת קובץ",
        "nolicense": "אין",
        "licenses-edit": "עריכת אפשרויות רישיון",
        "license-nopreview": "(תצוגה מקדימה לא זמינה)",
-       "upload_source_url": "(×\9bת×\95×\91ת URL ×ª×§×¤×\94 ×\95× ×\92×\99ש×\94)",
-       "upload_source_file": "(ק×\95×\91×¥ ×\91מחשב שלך)",
+       "upload_source_url": "(ק×\95×\91×¥ ×©×\91×\97רת ×\9e×\9bת×\95×\91ת URL ×ª×§×\99× ×\94 ×\95× ×\92×\99ש×\94 ×\9cצ×\99×\91×\95ר)",
+       "upload_source_file": "(ק×\95×\91×¥ ×©×\91×\97רת ×\9e×\94מחשב שלך)",
        "listfiles-delete": "מחיקה",
        "listfiles-summary": "דף מיוחד זה מציג את כל הקבצים שהועלו.",
        "listfiles_search_for": "חיפוש קובץ מדיה בשם:",
        "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": "בהוספה לרשימת המעקב…",
        "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": "יומנים",
        "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",
        "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|חסימה אחרת|חסימות אחרות}}",
        "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.",
        "autosumm-replace": "החלפת הדף בתוכן \"$1\"",
        "autoredircomment": "הפניה לדף [[$1]]",
        "autosumm-new": "יצירת דף עם התוכן \"$1\"",
+       "autosumm-newblank": "יצירת דף ריק",
        "size-bytes": "$1 בייט",
        "size-kilobytes": "$1 קילו־בייט",
        "size-megabytes": "$1 מגה־בייט",
        "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",
index 62fd035..0b526c5 100644 (file)
        "prefs-watchlist-token": "Token popisa praćenja:",
        "prefs-misc": "Razno",
        "prefs-resetpass": "Promijeni lozinku",
-       "prefs-changeemail": "Promijeni E-mail",
+       "prefs-changeemail": "promijeni e-mail",
        "prefs-setemail": "Postavite E-mail adresu",
        "prefs-email": "Mogućnosti e-maila",
        "prefs-rendering": "Izgled",
        "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...",
index 514b944..d9cabd3 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",
        "preview": "Previsualisation",
        "showpreview": "Monstrar previsualisation",
        "showdiff": "Detaliar modificationes",
+       "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": "'''Attention:''' Tu non ha aperite un session.\nTu adresse IP essera registrate in le historia de modificationes de iste pagina.",
        "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.",
        "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].",
        "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",
        "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:",
        "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|'''$1''' modificationes}} durante le ultime {{PLURAL:$2|hora|'''$2''' horas}}, a partir del $3 a $4.",
        "wlshowlast": "Revelar ultime $1 horas $2 dies $3",
        "watchlist-options": "Optiones del observatorio",
        "watching": "Observation in curso...",
        "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",
index 74eec5e..bfb5a74 100644 (file)
        "preview": "Ipadas",
        "showpreview": "Ipakita ti ipadas",
        "showdiff": "Ipakita dagiti sinukatan",
+       "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.",
        "creating": "Agparpartuat ti $1",
        "editingsection": "Ur-urnosen ti $1 (paset)",
        "editingcomment": "Ur-urnosen ti $1 (baro a paset)",
-       "editconflict": "Kasinnungat ti panag-urnos: $1",
+       "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": "Rebision a naidulin",
        "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].",
        "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",
        "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).",
+       "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",
        "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 porman 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 nakalista 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> tapnomausar ti 200 a piksel a kalawa a panagiparang iti kanigid a margin ng aaddaan iti \"alt text\"a kas deskripsion\n* <strong><code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code></strong> para iti dagus a panangisilpo itipapeles nga awan ti panangipakita ti papeles",
+       "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 kaykayat a kita ti papeles: $1.",
        "upload-prohibited": "Dagiti maiparit a kita ti papeles: $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": "Dagiti URL nga addan iti \"$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.",
        "nolicense": "Awan ti napili",
        "licenses-edit": "Urnosen dagiti pagpilian ti lisensia",
        "license-nopreview": "(Saan a magun-od ti panagipadas)",
-       "upload_source_url": "(maysa nga umisu, ken publiko a maserrekan nga URL)",
-       "upload_source_file": "(ti papeles iti kompiutermo)",
+       "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:",
        "speciallogtitlelabel": "Puntaan (titulo wenno agar-aramat):",
        "log": "Dagiti listaan",
        "all-logs-page": "Amin a listaan a publiko",
-       "alllogstext": "Naipagtipon 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 (ket sensitibo pay ti kadakkel ti letra).",
+       "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",
        "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 <strong>napuskol</strong>.",
-       "wlnote2": "Dita baba ket dagiti binalbaliwan {{PLURAL:$1|iti napalabas nga oras|kadagiti napalabas a <strong>$1</strong> nga oras}}, manipud idi $2, $3.",
+       "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...",
        "restriction-level-all": "aniaman nga agpang",
        "undelete": "Kitaen dagiti naikkat a panid",
        "undeletepage": "Kitaen ken isubli dagiti naikkat a panid",
-       "undeletepagetitle": "<strong>Ti sumaganad ket buklen dagiti naikkat a rebision ni [[:$1|$1]]</strong>.",
+       "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 rebision",
        "blanknamespace": "(Umuna)",
        "contributions": "Dagiti kontribusion ti {{GENDER:$1|agar-aramat}}",
        "contributions-title": "Kontribusion ti agar-aramat para kenni $1",
-       "mycontris": "Dagiti kontribusion",
+       "mycontris": "Inar-aramid",
        "contribsub2": "Para kenni {{GENDER:$3|$1}} ($2)",
        "contributions-userdoesnotexist": "Ti pakabilangan ti agar-aramat ni \"$1\" ket saan a nakarehistro.",
        "nocontribs": "Awan ti nasarakan a nasukatan a kapada dagitoy a kriteria.",
        "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 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 a partuaten.",
-       "import-error-interwiki": "Ti panid ti \"$1\" ket saan a naala ngamin ket ti nagan ket naireserba para iti ruar a panagsilpo (interwiki).",
-       "import-error-special": "Ti panid ti \"$1\" ket saan 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 a naala ngamin ket ti naganna ket imbalido.",
+       "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>",
        "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}}",
+       "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}} manipud ti $2",
+       "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.",
        "autosumm-replace": "Sinukatan ti linaon iti \"$1\"",
        "autoredircomment": "Naibaw-ing ti panid iti [[$1]]",
        "autosumm-new": "Pinartuat ti panid iti \"$1\"",
+       "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",
        "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 makaiarga kadagiti papeles.",
+       "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.",
index dd285a5..d9180fa 100644 (file)
@@ -89,6 +89,7 @@
        "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 le pagine dove ho effettuato un rollback agli osservati speciali",
        "tog-minordefault": "Indica ogni modifica come minore (solo come predefinito)",
        "tog-previewontop": "Mostra l'anteprima sopra la casella di modifica e non sotto",
        "tog-previewonfirst": "Mostra l'anteprima almeno una volta prima di salvare",
        "preview": "Anteprima",
        "showpreview": "Visualizza anteprima",
        "showdiff": "Mostra modifiche",
+       "blankarticle": "<strong>Attenzione:</strong> la pagina che stai creando è vuota.\nCliccando nuovamente su \"{{int:savearticle}}\", la pagina sarà creata senza alcun contenuto.",
        "anoneditwarning": "'''Attenzione:''' Accesso non effettuato. Nella cronologia della pagina verrà registrato il tuo indirizzo IP.",
        "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.",
        "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-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:",
        "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].",
        "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",
        "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:",
        "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...",
        "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.",
index 9554fe8..2abccf1 100644 (file)
        "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": "表示",
        "watchlist-details": "ウォッチリストには {{PLURAL:$1|$1 ページ}}が登録されています (トークページを除く)。",
        "wlheader-enotif": "メール通知が有効になっています。",
        "wlheader-showupdated": "最終訪問以降に変更されたページは、<strong>太字</strong>で表示されます。",
-       "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": "ウォッチリストに追加中...",
        "import-error-edit": "あなたにそのページを編集する許可がないため、ページ「$1」は取り込まれませんでした。",
        "import-error-create": "あなたにそのページを作成する許可がないため、ページ「$1」は取り込まれませんでした。",
        "import-error-interwiki": "ページ名が外部リンク (ウィキ間リンク) に予約されているため、ページ「$1」を取り込みませんでした。",
-       "import-error-special": "ページ「$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」に保存できません。",
index 32c88ba..13cea46 100644 (file)
        "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": "Әрекет орындалмады",
index bc8eef8..d49f438 100644 (file)
        "currentrev": "최신판",
        "currentrev-asof": "$1 기준 최신판",
        "revisionasof": "$1 판",
-       "revision-info": "{{GENDER:$6|$2}} 사용자의 $1 판$1",
+       "revision-info": "{{GENDER:$6|$2}} 사용자의 $1 판$7",
        "previousrevision": "← 이전 판",
        "nextrevision": "다음 판 →",
        "currentrevisionlink": "최신판",
        "right-browsearchive": "삭제된 문서 검색",
        "right-undelete": "삭제된 문서 되살리기",
        "right-suppressrevision": "관리자가 보지 못하도록 숨겨진 판을 검토하고 되살리기",
+       "right-viewsuppressed": "어떤 사용자가 숨긴 판 보기",
        "right-suppressionlog": "숨겨진 기록을 보기",
        "right-block": "다른 사용자가 편집을 못하도록 차단",
        "right-blockemail": "다른 사용자가 이메일을 보내지 못하도록 차단",
        "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": "주시 추가 중…",
        "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": "주시문서 목록 편집하기",
index 611f1a2..3cf2b88 100644 (file)
        "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",
        "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 6505da6..1d04b98 100644 (file)
        "preview": "Kucken ouni ofzespäicheren",
        "showpreview": "Kucken ouni ofzespäicheren",
        "showdiff": "Ännerunge weisen",
+       "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": "'''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.",
        "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.",
        "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].",
        "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",
        "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:",
        "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.",
+       "broken-file-category-desc": "Kategorie, déi derbäigesat gëtt, wann et op der Säit e futtise Link op e Fichier gëtt (e Link op en agebonnene Fichier wann et de Fichier net gëtt).",
        "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.",
        "trackingcategories-nodesc": "Keng Beschreiwung disponibel.",
        "trackingcategories-disabled": "Kategorie ass desaktivéiert",
        "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 …",
        "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.",
        "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.",
        "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",
index 97903fc..e76302d 100644 (file)
        "gotaccount": "Tev jau ir lietotājvārds? '''$1'''!",
        "gotaccountlink": "Pieslēgties",
        "userlogin-resetlink": "Esat aizmirsis savu pieslēgšanās informāciju?",
+       "userlogin-helplink2": "Palīdzība ar pieslēgšanos",
        "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",
        "createacct-emailrequired": "E-pasta adrese",
        "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:",
        "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",
        "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",
        "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",
        "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",
index 967370c..6d4b38f 100644 (file)
@@ -11,7 +11,8 @@
                        "Super Wang",
                        "Xiaomingyan",
                        "Yanteng3",
-                       "아라"
+                       "아라",
+                       "LNDDYL"
                ]
        },
        "tog-underline": "鏈墊線:",
        "talkpagelinktext": "議",
        "specialpage": "特查",
        "personaltools": "家私",
-       "postcomment": "評",
        "articlepage": "閱內文",
        "talk": "議",
        "views": "覽",
        "externaldberror": "認庫之錯或禁更爾之外簿。",
        "login": "登簿",
        "nav-login-createaccount": "登簿、增簿",
-       "loginprompt": "登簿{{SITENAME}}須cookies,請准之。",
        "userlogin": "登簿、增簿",
        "userloginnocreate": "登簿",
        "logout": "去簿",
        "prefs-watchlist-token": "哨幣:",
        "prefs-misc": "雜",
        "prefs-resetpass": "更符節",
+       "prefs-changeemail": "更郵址",
        "prefs-email": "傳書",
        "prefs-rendering": "觀",
        "saveprefs": "儲",
        "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": "出陣…",
        "cannotundelete": "無以還檔;或復矣。",
        "undeletedpage": "'''$1還矣'''\n近刪新還,見[[Special:Log/delete|刪還誌]]。",
        "undelete-header": "欲覽近刪,見[[Special:Log/delete|誌刪]]。",
+       "undelete-search-title": "尋刪頁",
        "undelete-search-box": "尋刪",
        "undelete-search-prefix": "見頁始如",
        "undelete-search-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": "鈎",
        "sqlite-no-fts": "$1 不含全文之尋",
        "revdelete-restricted": "應限至有秩",
        "revdelete-unrestricted": "除限自有秩",
-       "rightsnone": "(凡)"
+       "rightsnone": "(凡)",
+       "searchsuggest-search": "尋"
 }
index 9728a18..272c889 100644 (file)
@@ -31,6 +31,7 @@
        "tog-watchdefault": "Додавај ги страниците и податотеките што ги уредувам во списокот на набљудувања",
        "tog-watchmoves": "Додавај ги страниците и податотеките што ги преместувам во списокот на набљудувања",
        "tog-watchdeletion": "Додавај ги страниците и податотеките што ги бришам во списокот на набљудувања",
+       "tog-watchrollback": "Додај ги страниците сум ги отповикал во набљудувани",
        "tog-minordefault": "Обележувај ги сите уредувања како ситни по основно",
        "tog-previewontop": "Прикажи го прегледот пред кутијата за уредување",
        "tog-previewonfirst": "Прикажи преглед на првото уредување",
        "preview": "Преглед",
        "showpreview": "Преглед",
        "showdiff": "Прикажи промени",
+       "blankarticle": "<strong>Предупредување:</strong> Страницата што ја создавате е празна.\nАко повторно стиснете на „{{int:savearticle}}“, страницата ќе биде создадена без никаква содржина во неа.",
        "anoneditwarning": "'''Предупредување:''' Не сте најавени.\nВашата IP-адреса ќе биде заведена во историјата на уредување на страницата.",
        "anonpreviewwarning": "''Не сте најавени. Ако ја зачувате, Вашата IP-адреса ќе биде заведена во историјата на уредување на страницата.''",
        "missingsummary": "'''Потсетник:''' Не внесовте опис на измените. Ако притиснете Зачувај повторно, вашите измени ќе се зачуваат без опис.",
        "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}}}} дневникот на бришења].",
        "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": "Прикажи",
        "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": "Побарај име на податотека:",
        "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": "Набљудување...",
        "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.",
        "autosumm-replace": "Ја заменувам страницата со '$1'",
        "autoredircomment": "Пренасочување кон [[$1]]",
        "autosumm-new": "Создадена страница со: $1",
+       "autosumm-newblank": "Создадена празна страница",
        "size-bytes": "$1 Б",
        "size-kilobytes": "$1 КБ",
        "size-megabytes": "$1 МБ",
index 0369fc7..79ea47a 100644 (file)
        "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.",
        "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].",
        "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:",
        "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.",
        "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]]",
        "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)",
        "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": "Berikut ialah {{PLURAL:$1|perubahan|'''$1''' perubahan}} yang terkini dalam {{PLURAL:$2|sejam|'''$2''' jam}} yang lalu, tepat pada $3, $4.",
        "wlshowlast": "Tunjukkan $1 jam / $2 hari yang lalu / $3.",
        "watchlist-options": "Pilihan senarai pantau",
        "watching": "Memantau...",
index e2999cb..b194711 100644 (file)
        "watchlist-details": "بدون حیساب گپ ولگ‌ئون، {{PLURAL:$1|$1 صفحه|$1 صفحه}} شمه دمبال‌هاکردنی‌ئون میون قرار {{PLURAL:$1|دارنه|دانه}}.",
        "wlheader-enotif": "*تونی ایمیل جه مطلع بواشین.",
        "wlheader-showupdated": "*صفحه‌ئونی که بعد از آخرین سربزوئنتون عوض بینه '''پر رنگ''' نشون هدائه بیّه.",
+       "wlnote": "ایجه {{PLURAL:$1|پایانی دأچیه‌ن|پایانی '''$1''' دأچیه‌ن‌ئونی}} هأسه که ای $2 ساعت ده‌له دأکه‌ته.",
        "watchlist-options": "دمبال هاکردن گوزینه‌ها",
        "watching": "ده‌مـبـال هـه‌کـارده‌ن...",
        "unwatching": "ده‌مـبـال نـه‌کـارده‌ن...",
index f29574c..d659ff7 100644 (file)
        "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",
        "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": "Ē-kha sī '''$2''' tiám-cheng í-lāi siōng sin ê $1 ê 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",
index e6ad0f0..aaedc84 100644 (file)
        "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",
        "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",
        "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",
        "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)",
        "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",
        "watchlist-details": "{{PLURAL:$1|Én side|$1 sider}} på din overvåkningsliste, teller ikke 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.",
+       "wlnote": "Nedenfor er {{PLURAL:$1|den siste endringen|de siste '''$1''' endringene}} {{PLURAL:$2|den siste timen|de siste '''$2''' timene}}, fra den $3, kl. $4",
        "wlshowlast": "Vis siste $1 timer $2 dager $3",
        "watchlist-options": "Alternativ for overvåkningslisten",
        "watching": "Overvåker…",
        "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": "Installerte drakter",
index 0ba4a58..91597b1 100644 (file)
        "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",
        "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 2b794c1..1af8c9f 100644 (file)
@@ -58,7 +58,8 @@
                        "아라",
                        "Mar(c)",
                        "Calak",
-                       "Arg"
+                       "Arg",
+                       "NCoppens"
                ]
        },
        "tog-underline": "Koppelingen onderstrepen:",
@@ -75,7 +76,7 @@
        "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-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",
        "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.",
        "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.",
        "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",
        "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…",
        "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",
        "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."
 }
index b2e931e..f3c6636 100644 (file)
        "unusedtemplateswlh": "andre lenkjer",
        "randompage": "Tilfeldig side",
        "randompage-nopages": "Det finst ingen sider i {{PLURAL:$2|dette namnerommet|desse namneromma}}: $1.",
+       "randomincategory-selectcategory": "Hent tilfeldig side frå kategori: $1 $2.",
+       "randomincategory-selectcategory-submit": "Hent",
        "randomredirect": "Tilfeldig omdirigering",
        "randomredirect-nopages": "Det finst ingen omdirigeringar i namnerommet «$1».",
        "statistics": "Statistikk",
        "watchlist-details": "{{PLURAL:$1|Éi side|$1 sider}} er overvaka, utanom 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...",
        "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 3803f4a..6d6cb71 100644 (file)
        "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.",
        "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ęć].",
        "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",
        "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ż",
        "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",
        "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...",
        "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>",
        "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",
index 3d0f725..f9cc76c 100644 (file)
        "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...",
index 21846c9..003602c 100644 (file)
@@ -77,6 +77,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 à minha lista de artigos vigiados",
        "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",
        "preview": "Antevisão",
        "showpreview": "Antever resultado",
        "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": "'''Aviso''': Não iniciou sessão.\nO seu endereço IP será registado no histórico de edições desta página.",
        "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.",
        "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].",
        "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>).",
+       "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 $3 $2",
        "rcshowhideminor": "$1 edições menores",
        "rcshowhideminor-show": "Mostrar",
        "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:",
        "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.",
        "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 '''$1''' alterações ocorridas}} {{PLURAL:$2|na última hora|nas últimas '''$2''' 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...",
        "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",
index ad5b288..9a1d2e1 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}}",
        "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}}",
+       "blankarticle": "Notice displayed once after the user tries to save an empty page.",
        "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}}",
        "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}}",
        "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}}",
        "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}}",
        "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.",
        "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.",
        "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).",
index 07288f6..8c084e4 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",
        "preview": "Previzualizare",
        "showpreview": "Previzualizare",
        "showdiff": "Afișare diferențe",
+       "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": "'''Atenție:''' Nu v-ați autentificat. Adresa IP vă va fi înregistrată în istoricul acestei pagini.",
        "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.",
        "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].",
        "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ă",
        "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:",
        "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...",
        "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.",
        "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",
index 402be56..5760970 100644 (file)
        "preview": "Предпросмотр",
        "showpreview": "Предварительный просмотр",
        "showdiff": "Внесённые изменения",
+       "blankarticle": "<strong>Предупреждение:</strong> Страница, которую вы создаёте, пуста.\nЕсли снова нажмёте кнопку «{{int:savearticle}}», страница будет создана без какого-либо содержания.",
        "anoneditwarning": "'''Внимание!''' Вы не авторизовались на сайте.\nВ истории изменений этой страницы будет записан ваш IP-адрес.",
        "anonpreviewwarning": "''Вы не представились системе. Сохранение приведёт к записи вашего IP-адреса в историю изменений страницы.''",
        "missingsummary": "'''Напоминание.''' Вы не дали краткого описания изменений. При повторном нажатии на кнопку «{{int:savearticle}}», ваши изменения будут сохранены без комментария.",
        "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}}}} журнале удалений].",
        "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": "Показать",
        "nolicense": "Отсутствует",
        "licenses-edit": "Изменить параметры лицензии",
        "license-nopreview": "(Предпросмотр недоступен)",
-       "upload_source_url": " (правильный, публично доступный интернет-адрес)",
-       "upload_source_file": " (файл на вашем компьютере)",
+       "upload_source_url": "(вы выбрали правильный, публично доступный интернет-адрес)",
+       "upload_source_file": "(вы выбрали файл на вашем компьютере)",
        "listfiles-delete": "удалить",
        "listfiles-summary": "Эта служебная страница показывает все загруженные файлы.",
        "listfiles_search_for": "Поиск по имени файла:",
        "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": "Добавление в список наблюдения…",
        "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 МБ",
index b2c68bb..c3484c8 100644 (file)
@@ -7,54 +7,55 @@
                        "Node ue",
                        "לערי ריינהארט",
                        "아라",
-                       "Via maxima"
+                       "Via maxima",
+                       "Uharteko"
                ]
        },
-       "tog-underline": "Sutalìnea is cullegamentos",
-       "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-underline": "Sutalìnia sos collegamentos",
+       "tog-hideminor": "Cua sos càmbios minores in sa pàgina de sos ùrtimas càmbios",
+       "tog-hidepatrolled": "Cua sos càmbios verificados in sos ù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-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 su primu càmbiu",
+       "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 sos utentes chi sunt castiende 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-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 sos càmbios meos dae sa watclist",
+       "tog-watchlisthidebots": "Cua sos càmbios de sos bots dae sa watchlist",
+       "tog-watchlisthideminor": "Cua sos càmbios minores dae sa watchlist",
+       "tog-watchlisthideliu": "Cua sos càmbios de sos utentes intrados dae sa watchlist",
+       "tog-watchlisthideanons": "Cua sos càmbios de sos utentes anònimos dae sa watchlist",
+       "tog-watchlisthidepatrolled": "Cua càmbios verificados dae sa watchlist",
+       "tog-ccmeonemails": "Imbia·mi sas còpias de sas post.els chi imbio a sos àteros utentes",
+       "tog-showhiddencats": "Ammustra sas 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-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 browser 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",
        "oct": "Stg",
        "nov": "Std",
        "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 b't peruna pàgina o mèdiu.''",
        "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 inditada|$1 subcategorias inditadas}} in suta, de $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 inditada|is $1 pàginas inditadas}} 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": "(aberit in una ventana noa)",
        "cancel": "Burra",
        "moredotdotdot": "Àteru…",
        "morenotlisted": "Sa lista no est cumpreta",
        "mypage": "Pàgina",
        "mytalk": "Cuntierras meas",
-       "anontalk": "Cuntierras pro custu IP",
-       "navigation": "Navigadura",
+       "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/Rispostas (FAQ)",
        "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àmene 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}}",
+       "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": "Ampara",
-       "protect_change": "mudàntzia",
+       "protect_change": "càmbiu",
        "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": "Vistas",
        "toolbox": "Ainas",
-       "userpage": "Càstia sa pàgina usuàriu",
+       "userpage": "Càstia sa pàgina utente",
        "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",
+       "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 provare luego.\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-errorunknown": "Faddina disconnota",
        "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",
-       "privacy": "Polìtica pro is datos privados",
-       "privacypage": "Project:Polìtica pro is datos privados",
+       "portal-url": "Project:Portale Comunidade",
+       "privacy": "Polìtica pro sos datos privados",
+       "privacypage": "Project:Polìtica pro sos 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 boles est limitada a utentes in {{PLURAL:$2|su grupu|unu de sos 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).",
+       "youhavenewmessagesmanyusers": "Tenes $1 dae utentes ($2).",
        "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",
-       "toc": "Cuntènnidu",
+       "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": "Cuntenutu",
        "showtoc": "ammustra",
        "hidetoc": "cua",
-       "collapsible-collapse": "Serra e stringi",
+       "collapsible-collapse": "Serra e istringhe",
        "collapsible-expand": "Aberi",
        "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:",
        "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 utente",
+       "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-template": "Modellu",
        "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 l'agatas in [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Faddina",
-       "databaseerror": "Faddina de su database",
-       "readonly": "Database bloccadu",
-       "enterlockreason": "Inserta su motivu de su bloccu, ispetzifichende su momentu probabile chi su bloccu at a acabai",
+       "databaseerror": "Faddina de sa base de datos",
+       "readonly": "Base de datos blocada",
+       "enterlockreason": "Inserta su motivu de su blocu, ispetzifichende su momentu probàbile chi su blocu at a agabbare",
        "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.",
        "missingarticle-rev": "(revisione nùmeru: $1)",
        "yourdomainname": "Spetzificare su domìniu",
        "login": "Intra",
        "nav-login-createaccount": "Intra / crea account",
-       "loginprompt": "Est netzessàriu abilitare is ''cookies'' pro si registrare in {{SITENAME}}.",
        "userlogin": "Intra / crea account",
        "userloginnocreate": "Intra",
        "logout": "Serra sessione",
index 5c60e43..628e67f 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",
        "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.",
        "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 83a0252..73d1f14 100644 (file)
        "preview": "Predogled",
        "showpreview": "Prikaži predogled",
        "showdiff": "Prikaži spremembe",
+       "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": "'''Opozorilo''': niste prijavljeni. V zgodovino strani se bo zapisal vaš IP-naslov.",
        "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.",
        "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-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 bodo še vedno lahko dostopali do skrite vsebine in jo obnovili, 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-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}}",
        "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",
        "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:",
        "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 ...",
        "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",
index ccfaf09..5a5cc53 100644 (file)
        "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 поткатегорија}}, од укупно $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 датотека је}} у овој категорији, од укупно $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": "промени",
        "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": "Вашој ИП адреси је онемогућено уређивање страница, као и могућност захтевања нове лозинке.",
        "preview": "Претпреглед",
        "showpreview": "Прикажи претпреглед",
        "showdiff": "Прикажи измене",
+       "blankarticle": "<strong>Упозорење:</strong> страница коју правите нема никакав садржај.\nАко још једном притиснете „{{int:savearticle}}“ направићете страницу без садржаја.",
        "anoneditwarning": "'''Упозорење:''' нисте пријављени.\nВаша ИП адреса ће бити забележена у историји ове странице.",
        "anonpreviewwarning": "''Нисте пријављени. Ваша ИП адреса ће бити забележена у историји ове странице.''",
        "missingsummary": "'''Напомена:''' нисте унели опис измене.\nАко поново кликнете на „{{int:savearticle}}“, ваша измена ће бити сачувана без описа.",
        "revdelete-reasonotherlist": "Други разлог",
        "revdelete-edit-reasonlist": "Уреди разлоге за брисање",
        "revdelete-offender": "Аутор измене:",
-       "suppressionlog": "Ð\98Ñ\81Ñ\82оÑ\80иÑ\98а сакривања",
+       "suppressionlog": "Ð\94невник сакривања",
        "suppressionlogtext": "Испод се налази списак брисања и блокирања који укључује садржај сакривен од администратора. Текуће забране и блокирања можете наћи [[Special:BlockList|овде]].",
        "mergehistory": "Споји историје страница",
        "mergehistory-header": "Ова страница вам омогућава да спојите измене неке изворне странице у нову страницу.\nЗапамтите да ће ова измена оставити непромењен садржај историје странице.",
        "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": "пÑ\80емеÑ\81Ñ\82и Ð¾Ð²Ñ\83 Ð´Ð°Ñ\82оÑ\82екÑ\83",
+       "action-movefile": "пÑ\80емеÑ\88Ñ\82аÑ\9aе Ð¾Ð²Ðµ Ð´Ð°Ñ\82оÑ\82еке",
        "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": "уређивање ваших личних података",
        "license-header": "Лиценца:",
        "nolicense": "није изабрано",
        "license-nopreview": "(преглед није доступан)",
-       "upload_source_url": " (исправна и јавно доступна адреса)",
+       "upload_source_url": "(исправна и јавно доступна адреса)",
        "upload_source_file": "(датотека на вашем рачунару)",
        "listfiles-delete": "обриши",
        "listfiles-summary": "Ова посебна страница приказује све послате датотеке.",
        "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": "Надгледање…",
        "delete-edit-reasonlist": "Уреди разлоге брисања",
        "delete-toobig": "Ова страница има велику историју, преко $1 {{PLURAL:$1|измене|измене|измена}}.\nБрисање таквих страница је ограничено да би се спречило случајно оптерећење сервера.",
        "delete-warning-toobig": "Ова страница има велику историју, преко $1 {{PLURAL:$1|измене|изменe|измена}}.\nЊено брисање може пореметити базу података, стога поступајте с опрезом.",
-       "deleting-backlinks-warning": "'''УпозоÑ\80еÑ\9aе:''' Ð\91Ñ\80иÑ\88еÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83 ÐºÐ¾Ñ\98а Ñ\98е Ñ\83кÑ\99Ñ\83Ñ\87ена Ñ\83 Ð´Ñ\80Ñ\83ге Ñ\81Ñ\82Ñ\80аниÑ\86е или друге странице воде на њу.",
+       "deleting-backlinks-warning": "'''УпозоÑ\80еÑ\9aе:''' Ð±Ñ\80иÑ\88еÑ\82е Ñ\81Ñ\82Ñ\80аниÑ\86Ñ\83 ÐºÐ¾Ñ\98а Ñ\98е Ñ\83кÑ\99Ñ\83Ñ\87ена Ñ\83 [[Special:WhatLinksHere/{{FULLPAGENAME}}|дÑ\80Ñ\83ге Ñ\81Ñ\82Ñ\80аниÑ\86е]] или друге странице воде на њу.",
        "rollback": "Врати измене",
        "rollback_short": "Врати",
        "rollbacklink": "врати",
        "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“",
        "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": "Не могу да преместим на жељени наслов.",
        "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": "Јаваскрипт тест",
        "javascripttest-title": "Извршавање тестова за $1",
        "javascripttest-pagetext-noframework": "Ова страница је резервисана за извршавање јаваскрипт тестова.",
        "autosumm-replace": "Замена садржаја странице са „$1“",
        "autoredircomment": "Преусмерење на [[$1]]",
        "autosumm-new": "Нова страница: $1",
+       "autosumm-newblank": "Направљена празна страница",
        "size-bytes": "$1 B",
        "size-kilobytes": "$1 kB",
        "size-megabytes": "$1 MB",
        "pagelang-name": "Страница",
        "pagelang-language": "Језик",
        "pagelang-select-lang": "Изабери језик",
-       "right-pagelang": "пÑ\80омена језика странице",
+       "right-pagelang": "меÑ\9aаÑ\9aе језика странице",
        "action-pagelang": "промену језика странице"
 }
index a1bcf4c..89d2c88 100644 (file)
@@ -40,7 +40,7 @@
        "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|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|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",
        "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.",
        "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.",
        "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-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-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",
        "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": "Vikimedijina ostava",
        "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…",
        "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",
        "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“",
        "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.",
        "importlogpage": "Dnevnik uvoza",
        "importlogpagetext": "Administrativni uvozi stranica s istorijama izmena s drugih vikija.",
        "import-logentry-upload": "uvezeno [[$1]] otpremanjem datoteke",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|izmena|izmene|izmena}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|izmena uvezena|izmene uvezene|izmena uvezeno}}",
        "import-logentry-interwiki": "premešteno s drugog vikija: $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|izmena|izmene|izmena}} od $2",
+       "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.",
index 50ad2f7..66c348e 100644 (file)
        "preview": "Förhandsgranska",
        "showpreview": "Visa förhandsgranskning",
        "showdiff": "Visa ändringar",
+       "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": "'''Varning:''' Du är inte inloggad.\nDin IP-adress kommer att sparas i historiken för den här sidan.",
        "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.",
        "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].",
        "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",
        "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 '''$1''' ändringarna}} under {{PLURAL:$2|den senaste timmen|de senaste '''$2''' timmarna}} från den $3 kl. $4.",
        "wlshowlast": "Visa senaste $1 timmarna $2 dygnen $3",
        "watchlist-options": "Alternativ för bevakningslistan",
        "watching": "Bevakar...",
        "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.",
        "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",
index df1295c..61e3cf9 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:",
        "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..9698a35 100644 (file)
        "talkpagelinktext": "பேச்சு",
        "specialpage": "சிறப்புப் பக்கம்",
        "personaltools": "தனிப்பட்ட பயன்பாட்டுக் கருவிகள்",
-       "postcomment": "புதிய பகுதி",
        "articlepage": "உள்ளடக்கப் பக்கத்தைப் பார்",
        "talk": "உரையாடல்",
        "views": "பார்வைகள்",
        "externaldberror": "வெளி உறுதிப்படுத்தலில் ஏற்பட்ட தவறு காரணமாக உங்கள் வெளி கணக்கை இற்றைப்படுத்த முடியாது.",
        "login": "புகுபதிகை",
        "nav-login-createaccount": "புகுபதிகை/பயனர் கணக்கு தொடக்கம்",
-       "loginprompt": "{{SITENAME}} தளத்துக்கு புகுபதிகை செய்ய உங்கள் இணைய உலாவியின் ஞாபகிகளை செயற்படுத்த வேண்டும்.",
        "userlogin": "புகுபதிகை/பயனர் கணக்கு தொடக்கம்",
        "userloginnocreate": "புகுபதிகை",
        "logout": "விடுபதிகை",
        "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": "பயனர் மின்னஞ்சல் அனுப்புவதை தடுக்கவும்",
        "nolicense": "தெரிவுச் செய்யப்படவில்லை",
        "license-nopreview": "(முன்தோற்றம் கையிலிருப்பில் இல்லை)",
        "upload_source_url": " (செல்லுபடியான, இணைய முகவரி)",
-       "upload_source_file": " (உங்கள் கணணியில் உள்ள கோப்பு)",
+       "upload_source_file": "(தங்களி்ன் கணினியிலிருந்து தங்களால் தேர்ந்தெடுக்கப்பட்ட கோப்பு)",
        "listfiles-summary": "இச்சிறப்புப் பக்கம் பதிவேற்றப்பட்ட கோப்புகளைப் பட்டியலிடுகிறது.",
        "listfiles_search_for": "பின்வரும் பெயருள்ள ஊடகக் கோப்பைத் தேடு:",
        "imgfile": "கோப்பு",
        "watchlist-details": "பேச்சுப் பக்கங்களைத் தவிர்த்து, {{PLURAL:$1|$1 பக்கம் கவனிக்கப்பட்டது.|$1 பக்கங்கள் கவனிக்கப்பட்டன.}}",
        "wlheader-enotif": "மின்னஞ்சல் அறிவிப்புகள் செயல்படுத்தப்பட்டுள்ளன.",
        "wlheader-showupdated": "உங்கள் கடைசி வருகைக்குப் பின்னர் மாற்றங்கள் செய்யப்பட்ட பக்கங்கள் '''தடித்த எழுத்துக்களில்''' காட்டப்பட்டுள்ளன",
+       "wlnote": "பின்வருவன கடைசி {{PLURAL:$2|மணித்தியாலத்தில்|'''$2''' மணித்தியாலங்களில்}} செய்யப்பட்ட {{PLURAL:$1|கடைசி ஒரு மாற்றமாகும்|கடைசி $1 மாற்றங்களாகும்}}.",
        "wlshowlast": "கடைசி $1 மணித்தியாலங்கள் $2 நாட்களைக் காட்டு $3",
        "watchlist-options": "கவனிப்பு பட்டியலின் விருப்பத் தேர்வுகள்",
        "watching": "கவனிக்கப்படுகிறது...",
        "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 b265193..7858c2a 100644 (file)
        "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": "ตั้งการจำกัดทัศนวิสัย:",
        "right-deletedtext": "ดูข้อความที่ถูกลบและการเปลี่ยนแปลงระหว่างรุ่นที่ถูกลบ",
        "right-browsearchive": "ค้นหาหน้าที่ถูกลบ",
        "right-undelete": "กู้คืนหน้า",
-       "right-suppressrevision": "à¸\94ูà¹\81ละà¸\81ูà¹\89à¸\84ืà¸\99รุà¹\88à¸\99à¸\97ีà¹\88à¸\8bà¹\88อà¸\99à¸\88าà¸\81à¸\9cูà¹\89à¸\94ูà¹\81ลระà¸\9aà¸\9a",
+       "right-suppressrevision": "à¸\94ูรุà¹\88à¸\99à¸\95à¹\88าà¸\87 à¹\86 à¸«à¸£à¸·à¸­ à¸\8bà¹\88อà¸\99/à¹\80ลิà¸\81à¸\8bà¹\88อà¸\99รุà¹\88à¸\99à¸\97ีà¹\88à¸\81ำหà¸\99à¸\94à¸\88าà¸\81à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¹\83à¸\94 à¹\86",
        "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": "ด้านล่างเป็นการเปลี่ยนแปลงตั้งแต่ <strong>$3, $4</strong> (มากสุด <strong>$1</strong> รายการ)",
        "rclistfrom": "แสดงการเปลี่ยนแปลงใหม่เริ่มตั้งแต่ $3 $2",
        "rcshowhideminor": "$1การแก้ไขเล็กน้อย",
        "rcshowhideminor-show": "แสดง",
        "watchlist-details": "มี $1 หน้าในรายการเฝ้าดูของคุณ ไม่นับแยกหน้าอภิปราย",
        "wlheader-enotif": "การแจ้งเตือนผ่านอีเมลถูกเปิดใช้งาน",
        "wlheader-showupdated": "หน้าที่มีการเปลี่ยนแปลงตั้งแต่คุณเข้าชมล่าสุดแสดงใน'''ตัวหนา'''",
-       "wlnote2": "ด้านล่างเป็นการเปลี่ยนแปลงล่าสุดในช่วง <strong>$1</strong> ชั่วโมงล่าสุด จนถึงวันที่ $2 เวลา $3 น.",
+       "wlnote": "ด้านล่างเป็นการแก้ไข{{PLURAL:$1|ล่าสุด|ล่าสุด '''$1''' รายการ}} ใน{{PLURAL:$2|ชั่วโมง|ช่วง '''$2''' ชั่วโมง}}ที่ผ่านมา จนถึง $3, $4",
        "wlshowlast": "แสดง $1 ชั่วโมง $2 วันล่าสุด $3",
        "watchlist-options": "ตัวเลือกรายการเฝ้าดู",
        "watching": "เฝ้าดู...",
index d8d1b2d..82f0cef 100644 (file)
        "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",
        "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...",
index 5940869..6a640c8 100644 (file)
        "preview": "Попередній перегляд",
        "showpreview": "Попередній перегляд",
        "showdiff": "Показати зміни",
+       "blankarticle": "<strong>Попередження:</strong> Ви створюєте пусту сторінку.\nЯкщо Ви знову натиснете «{{int:savearticle}}», сторінку буде створено без вмісту.",
        "anoneditwarning": "'''Увага''': Ви не увійшли до системи. Ваша IP-адреса буде записана до історії змін цієї сторінки.",
        "anonpreviewwarning": "''Ви не увійшли в систему. Якщо ви виконаєте збереження, то в історію сторінки буде записана ваша IP-адреса.''",
        "missingsummary": "'''Нагадування''': Ви не дали короткого опису змін.\nНатиснувши кнопку «Зберегти» ще раз, ви збережете зміни без коментаря.",
        "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}}}} журналі вилучень].",
        "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": "показати",
        "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": "Додавання до списку спостереження…",
        "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 МБ",
        "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": "Тема оформлення",
index 6bba637..2394e91 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",
        "preview": "Xem trước",
        "showpreview": "Xem trước",
        "showdiff": "Xem thay đổi",
+       "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": "'''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.",
        "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.",
        "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].",
        "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",
        "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:",
        "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…",
        "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",
index 62b2328..af52399 100644 (file)
@@ -14,7 +14,8 @@
                        "Mywood",
                        "Cwek",
                        "Duolaimi",
-                       "Impersonator 1"
+                       "Impersonator 1",
+                       "LNDDYL"
                ]
        },
        "tog-underline": "鏈接下橫線:",
        "externaldberror": "迭个作兴是由于验证数据库错误或者侬拨禁止更新侬个外部账号。",
        "login": "登进去",
        "nav-login-createaccount": "登进去 / 建账号",
-       "loginprompt": "必须用缓存(cookies)好登进{{SITENAME}}。",
        "userlogin": "登进去 / 建账号",
        "userloginnocreate": "登录",
        "logout": "登出",
        "filedelete-maintenance-title": "文件刪弗爻",
        "download": "下载",
        "listredirects": "重定向列表",
-       "unusedtemplateswlh": "å\88¥æ¨£鏈接",
+       "unusedtemplateswlh": "å\85¶ä»\96鏈接",
        "randompage": "随便望望",
        "randomincategory": "分類裏個隨便一頁",
        "randomincategory-selectcategory-submit": "去",
index 33d03f5..5a8b7e7 100644 (file)
        "preview": "פֿאראויסקוק",
        "showpreview": "ווײַזן פֿאָרױסקוק",
        "showdiff": "ווײַז די ענדערונגען",
+       "blankarticle": "<strong>אזהרה:</strong> דער בלאט איר גייט שאפן איז ליידיק.\nטאמער איר וועט דריקן אויף \"{{int:savearticle}}\" נאכאמאל, וועט דער בלאט ווערן געשאפן אן קיין אינהאלט.",
        "anoneditwarning": "'''ווארענונג:''' איר זענט נישט אריינלאגירט אין אייער קאנטע. אייער איי פי אדרעס וועט ווערן דאקומענטירט אין דעם בלאטס היסטאריע פון ענדערונגען. אויב זארגט איר זיך פאר פריוואטקייטן, ביטע טוט זיך אריינלאגירן.",
        "anonpreviewwarning": "''איר זענט נישט אַרײַנלאגירט. אויפֿהיטן וועט ארײַנשרײַבן אײַער IP אַדרעס אין דער רעדאַקטירונג היסטאריע פונעם בלאַט.''",
        "missingsummary": "'''דערמאנונג:''' איר האט נישט אויסגעפילט דעם קורץ ווארט אויפקלערונג אויף אייער עדיט. אויב וועט איר דרוקן נאכאמאל אויף  \"היט אפ דעם בלאט\", וועט אייער ענדערונג ווערן געהיטן אן דעם.",
        "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": "ווײַזן",
        "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": "זוכן פֿאַר מעדיע נאָמען:",
        "unwatchedpages": "בלעטער וואס זענען נישט אויפגעפאסט",
        "listredirects": "ליסטע פון ווײַטערפֿירונגען",
        "listduplicatedfiles": "ליסטע פון טעקעס מיט דופליקאטן",
+       "listduplicatedfiles-summary": "דאס איז א רשימה פון טעקעס וואו די לעצטיקסטע ווערסיע פון דער טעקע איז א דופליקאט פון דער לעצטיקסטע ווערסיע פון אן אנדער טעקע. נאר לאקאלע טעקעס קומען אין באטראכט.",
        "listduplicatedfiles-entry": "[[:טעקע:$1|$1]] האט [[$3|{{PLURAL:$2|א דופליקאט|$2 דופליקאטן}}]].",
        "unusedtemplates": "נישט באניצטע מוסטערן",
        "unusedtemplatestext": "דער בלאט ווײַזט אלע בלעטער אינעם {{ns:template}} נאמענטייל וואס זענען נישט אײַנגעשלאסן אין אן אנדער בלאט. געדענקט צו באקוקן אנדערע בלעטער פאר לינקען צו די מוסטערן איידער איר מעקט זיי אויס.",
        "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": "מערסט פֿארבינדענע בלעטער",
        "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": "אויפפאסענדונג…",
        "imageinvalidfilename": "דער ציל טעקע נאָמען איז נישט גילטיק.",
        "fix-double-redirects": "דערהײַנטיקן ווײַטערפֿירונגען צום ארגינעלן טיטל",
        "move-leave-redirect": "איבערלאזן א ווײַטערפֿירונג",
+       "protectedpagemovewarning": "'''ווארענונג:  דער בלאט איז געווארן געשיצט אז בלויז באניצערס מיט סיסאפ פריווילעגיעס קענען אים באוועגן.'''\nדי פארגאנגענע לאגבוך באשרײַבונג ווערט געוויזן דא:",
+       "semiprotectedpagemovewarning": "'''באמערקונג:''' דער דאזיגער בלאַט איז געשיצט אז בלויז איינגעשריבענע באניצערס קענען אים באוועגן.\nדי פֿאַרגאַנגענע לאגבוך באשרײַבונג ווערט געוויזן דאָ:",
        "move-over-sharedrepo": "== טעקע עקזיסטירט ==\n[[:$1]] עקזיסטירט אויף א געטיילטן רעפאזיטאריום. ווען מען באוועגט א טעקע צו דעם טיטל וועט דאס איבערשרייבן די געטיילטע טעקע.",
        "file-exists-sharedrepo": "ס'איז שוין פאראן א טעקע מיטן געקליבענעם נאמען אויף א געמיינזאם רעפאזיטאריום.\nזייט אזוי גוט קלייבט אן אנדער נאמען.",
        "export": "עקספארטירן בלעטער",
        "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. פרואוון.",
index 71d1d7b..1bb63c5 100644 (file)
@@ -94,6 +94,7 @@
        "tog-watchdefault": "添加我编辑的页面和文件至我的监视列表",
        "tog-watchmoves": "添加我移动的页面和文件至我的监视列表",
        "tog-watchdeletion": "添加我删除的页面和文件至我的监视列表",
+       "tog-watchrollback": "当我对我的监视列表执行回退时加入页面",
        "tog-minordefault": "默认标记所有编辑为小编辑",
        "tog-previewontop": "将预览显示在编辑框上方",
        "tog-previewonfirst": "首次编辑时显示预览",
        "preview": "预览",
        "showpreview": "显示预览",
        "showdiff": "显示更改",
+       "blankarticle": "<strong>警告</strong>:您创建的页面是空白的。如果您再次点击“{{int:savearticle}}”,您将真的创建没有任何内容的页面。",
        "anoneditwarning": "<strong>警告:</strong>您没有登录。您的IP地址将被记录在该页面的编辑历史中。",
        "anonpreviewwarning": "''你没有登录。保存会记录你的IP地址于该页面的编辑历史中。''",
        "missingsummary": "'''提示:'''你没有提供编辑摘要。如果你再次点击“{{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-inclusion-category": "模板包含上限已经超过的页面",
        "post-expand-template-argument-warning": "'''警告:'''本页面包含至少一个模板参数有过大扩展大小。这些参数会被略过。",
        "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": "页面的节点数超出限制",
        "node-count-exceeded-category-desc": "节点数溢出页面的分类。",
        "node-count-exceeded-warning": "页面超出了节点数",
-       "expansion-depth-exceeded-category": "展开深度超限的页面",
+       "expansion-depth-exceeded-category": "扩展深度超出限制的页面",
        "expansion-depth-exceeded-category-desc": "这是超出拓展深度页面的分类。",
        "expansion-depth-exceeded-warning": "页面超过了扩展深度",
        "parser-unstrip-loop-warning": "检测到回圈",
        "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}}}} 删除日志]。",
        "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": "创建非讨论页面",
        "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": "显示",
        "nolicense": "未选定",
        "licenses-edit": "编辑许可选项",
        "license-nopreview": "(无预览可用)",
-       "upload_source_url": "ï¼\88æ\9c\89æ\95\88ã\80\81å\8f¯ä»¥å\85¬å¼\80访é\97®ç\9a\84URL)",
-       "upload_source_file": "ï¼\88æ\82¨è®¡ç®\97æ\9cºä¸\8aç\9a\84ä¸\80个文件)",
+       "upload_source_url": "ï¼\88æ\82¨é\80\89æ\8b©ç\9a\84æ\9d¥è\87ªæ\9c\89æ\95\88ã\80\81å\8f¯ä»¥å\85¬å¼\80访é\97®ç\9a\84URLç\9a\84æ\96\87件)",
+       "upload_source_file": "ï¼\88æ\9d¥è\87ªæ\82¨è®¡ç®\97æ\9cºä¸\8aæ\82¨é\80\89æ\8b©ç\9a\84文件)",
        "listfiles-delete": "删除",
        "listfiles-summary": "本特殊页面展示所有上传的文件。",
        "listfiles_search_for": "按媒体名称搜索:",
        "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": "正在监视...",
        "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-upload-detail": "已导入$1个{{PLURAL:$1|版本}}",
        "import-logentry-interwiki": "跨wiki$1",
-       "import-logentry-interwiki-detail": "来自$2的$1个{{PLURAL:$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将只影响机行政员 */",
        "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秒的更改未必会在这个列表中显示。",
index ce4477d..5c2a3d9 100644 (file)
        "tog-watchdefault": "將我編輯的頁面和檔案新增至監視清單",
        "tog-watchmoves": "將我移動的頁面和檔案加入監視清單",
        "tog-watchdeletion": "將我刪除的頁面和檔案新增至監視清單",
+       "tog-watchrollback": "將我曾經還原的頁面新增至監視清單",
        "tog-minordefault": "預設標記所有的編輯為小修訂",
        "tog-previewontop": "顯示預覽於編輯框上方",
        "tog-previewonfirst": "第一次編輯時顯示預覽",
        "tog-enotifwatchlistpages": "當我的監視清單中的頁面或檔案有變更時,傳送電子郵件通知我",
        "tog-enotifusertalkpages": "當我的對話頁面有變更時,傳送電子郵件通知我",
        "tog-enotifminoredits": "當頁面與檔案有小修訂時,傳送電子郵件通知我",
-       "tog-enotifrevealaddr": "在通知信件中顯示我的電子郵件址",
+       "tog-enotifrevealaddr": "在通知信件中顯示我的電子郵件址",
        "tog-shownumberswatching": "顯示正在監視的使用者數",
        "tog-oldsig": "現有簽名:",
        "tog-fancysig": "將簽名視為 Wikitext 語言 (不自動產生連結)",
        "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": "傳送電子郵件錯誤:$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": "此網站不能傳送電子郵件。",
        "accountcreated": "已建立帳號",
        "passwordreset-capture-help": "若您勾選此核選方塊,電子郵件 (包含臨時密碼) 將直接顯示,並寄給使用者。",
        "passwordreset-email": "電子郵件位址:",
        "passwordreset-emailtitle": "於 {{SITENAME}} 的帳號詳細資訊",
-       "passwordreset-emailtext-ip": "不明人士 (可能是您自己,來自 IP 位址 $1) 要求重設在 {{SITENAME}} ($4) 的密碼,下列是與此電子郵件址有關的使用者{{PLURAL:$3|帳號}}:\n\n$2\n\n{{PLURAL:$3|這個臨時密碼|這些臨時密碼}}將會在{{PLURAL:$5|一天|$5 天}}內到期,\n您應立即登入並更改新的密碼。如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略此訊息並且繼續使用您原本的密碼。",
+       "passwordreset-emailtext-ip": "不明人士 (可能是您自己,來自 IP 位址 $1) 要求重設在 {{SITENAME}} ($4) 的密碼,下列是與此電子郵件址有關的使用者{{PLURAL:$3|帳號}}:\n\n$2\n\n{{PLURAL:$3|這個臨時密碼|這些臨時密碼}}將會在{{PLURAL:$5|一天|$5 天}}內到期,\n您應立即登入並更改新的密碼。如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略此訊息並且繼續使用您原本的密碼。",
        "passwordreset-emailtext-user": "使用者 $1 要求重設在 {{SITENAME}} ($4) 的密碼,下列是與此電子郵件位址有關的使用者{{PLURAL:$3|帳號}}:\n\n$2\n\n{{PLURAL:$3|這個臨時密碼|這些臨時密碼}}將會在{{PLURAL:$5|一天|$5 天}}內到期,\n您應立即登入並更改新的密碼。如果不是您要求重設密碼,或您已想起密碼,並不準備修改,\n您可以忽略此訊息並且繼續使用您原本的密碼。",
        "passwordreset-emailelement": "使用者名稱:$1\n臨時密碼:$2",
        "passwordreset-emailsent": "已寄出重設密碼的電子郵件。",
        "preview": "預覽",
        "showpreview": "顯示預覽",
        "showdiff": "顯示變更",
+       "blankarticle": "<strong>警告:</strong>您正在建立的頁面是空白的。\n如果您再按一下\"{{int:savearticle}}\",將建立沒有任何內容的頁面。",
        "anoneditwarning": "<strong>警告:</strong>您尚未登入。\n您的 IP 位址將記錄在此頁的編輯歷史中。",
        "anonpreviewwarning": "<em>您尚未登入。儲存頁面會將您的 IP 位址記錄在此頁面的編輯歷史中。</em>",
        "missingsummary": "<strong>提醒:</strong>您未填寫編輯摘要。\n若您再點選 \"{{int:savearticle}}\" 一次,將略過摘要直接儲存您的編輯。",
        "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|偏好設定]] 設定並驗證您的電子郵件位址。",
        "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": "å\9c¨ {{SITENAME}} ä¸\8aç\9a\84å\85¶ä»\96管ç\90\86å\93¡ä»\8dæ\9c\89æ¬\8aé\99\90å\8f¯ä»¥å­\98å\8f\96é\9a±è\97\8fç\9a\84å\85§å®¹ï¼\8cä¸\94è\83½å¤ å\8f\96æ¶\88å\88ªé\99¤ï¼\8cé\99¤é\9d\9eæ\9c\89é¡\8då¤\96ç\9a\84設å®\9aé\99\90å\88¶ã\80\82",
+       "revdelete-text-others": "å\85¶ä»\96管ç\90\86å\93¡ä»\8dæ\9c\89æ¬\8aé\99\90檢è¦\96é\9a±è\97\8fç\9a\84å\85§å®¹ï¼\8cä¸\94è\83½å¤ å\8f\96æ¶\88å\88ªé\99¤ï¼\8cé\99¤é\9d\9eæ\9c\89é¡\8då¤\96ç\9a\84設å®\9aé\99\90å\88¶ã\80\82",
        "revdelete-confirm": "請確認您是否明白此動作會造成的後果,\n以及您所做的動作是否符合 [[{{MediaWiki:Policy-url}}|政策]] 規範。",
        "revdelete-suppress-text": "禁制顯示應<strong>只有</strong>在下述情形時使用:\n* 潛在誹謗的資訊\n* 不合適個人資料\n*: <em>住家地址、電話號碼、身分證字號等。</em>",
        "revdelete-legend": "設定顯示限制",
        "recentchangesdays-max": "最多 $1 {{PLURAL:$1|天}}",
        "recentchangescount": "預設顯示的編輯數:",
        "prefs-help-recentchangescount": "這包含最近變更、頁面歷史以及日誌。",
-       "prefs-help-watchlist-token2": "訂閱您的監視清單所需的密鑰。\n任何人只要知道密鑰就能夠讀取您的監視列表,所以請勿任意與它人共享。\n若有需要 [[Special:ResetTokens|您可重設密鑰]]。",
+       "prefs-help-watchlist-token2": "訂閱您的監視清單所需的密鑰。\n任何人只要知道密鑰就能夠讀取您的監視清单,所以請勿任意與它人共享。\n若有需要 [[Special:ResetTokens|您可重設密鑰]]。",
        "savedprefs": "您的偏好設定已儲存。",
        "timezonelegend": "時區:",
        "localtime": "當地時間:",
        "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": "基本資訊",
        "userrights-changeable-col": "您可變更的群組",
        "userrights-unchangeable-col": "您不可變更的群組",
        "userrights-conflict": "使用者權限更改發生衝突!請重新檢視並確認你的更改。",
-       "userrights-removed-self": "您已成功移除自己的權限,故此您沒法再次訪問此頁。",
+       "userrights-removed-self": "您已成功移除自己的權限,故此您無法再次存取此頁。",
        "group": "群組:",
        "group-user": "使用者",
        "group-autoconfirmed": "自動確認使用者",
        "right-deletedtext": "檢視已刪除修訂中已刪除的文字及變更",
        "right-browsearchive": "搜尋已刪除的頁面",
        "right-undelete": "取消刪除頁面",
-       "right-suppressrevision": "複查與還原由管理員隱藏的修訂",
+       "right-suppressrevision": "檢視、隱藏與還原某使用者對頁面的特定修訂",
+       "right-viewsuppressed": "檢視某使用者隱藏的修訂",
        "right-suppressionlog": "檢視非公開日誌",
        "right-block": "封鎖其他使用者的編輯權限",
        "right-blockemail": "封鎖使用者傳送電子郵件的權限",
        "right-editmyuserjs": "編輯自己的使用者 JavaScript 檔",
        "right-viewmywatchlist": "檢視自己的監視清單",
        "right-editmywatchlist": "編輯自己的監視清單。注意,即使無此權限,某些操作仍會新增頁面至監視清單。",
-       "right-viewmyprivateinfo": "檢視自己的私隱資料 (如:電子郵件址及真實姓名)",
-       "right-editmyprivateinfo": "編輯自己的私隱資料 (如:電子郵件址及真實姓名)",
+       "right-viewmyprivateinfo": "檢視自己的私隱資料 (如:電子郵件址及真實姓名)",
+       "right-editmyprivateinfo": "編輯自己的私隱資料 (如:電子郵件址及真實姓名)",
        "right-editmyoptions": "編輯自己的偏好設定",
        "right-rollback": "快速還原最後一位使用者對某一頁面的編輯",
        "right-markbotedits": "標示還原編輯為機械人編輯",
        "action-importupload": "由檔案上傳匯入頁面",
        "action-patrol": "標示其它人的編輯為已巡查",
        "action-autopatrol": "標示您的編輯為已巡查",
-       "action-unwatchedpages": "檢視未監視的頁面列表",
+       "action-unwatchedpages": "檢視未監視的頁面清單",
        "action-mergehistory": "合併此頁面的歷史",
        "action-userrights": "編輯所有使用者的權限",
        "action-userrights-interwiki": "編輯在其它 Wiki 上的使用者權限",
        "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": "顯示",
        "nolicense": "尚未選擇",
        "licenses-edit": "編輯授權條款選項",
        "license-nopreview": "(不可預覽)",
-       "upload_source_url": "(有效,可公開存取的 URL)",
-       "upload_source_file": "(在您電腦上的檔案)",
+       "upload_source_url": "(æ\82¨é\81¸æ\93\87ç\9a\84æª\94æ¡\88ä¾\86è\87ªæ\9c\89æ\95\88ï¼\8cå\8f¯å\85¬é\96\8bå­\98å\8f\96ç\9a\84 URL)",
+       "upload_source_file": "(在您電腦上您選擇的檔案)",
        "listfiles-delete": "刪除",
        "listfiles-summary": "此特殊頁面顯示所有上傳過的檔案。",
        "listfiles_search_for": "搜尋媒體名稱:",
        "trackingcategories-disabled": "分類被禁用",
        "mailnologin": "沒有傳送位址",
        "mailnologintext": "您必須先 [[Special:UserLogin|登入]]\n並在 [[Special:Preferences|偏好設定]]\n中設定一個有效的電子郵件位址才可以傳送信件給其他使用者。",
-       "emailuser": "寄信給此使用者",
-       "emailuser-title-target": "寄信給此{{GENDER:$1|使用者}}",
-       "emailuser-title-notarget": "寄信給使用者",
+       "emailuser": "E-mail該使用者",
+       "emailuser-title-target": "E-mail該{{GENDER:$1|使用者}}",
+       "emailuser-title-notarget": "E-mail給使用者",
        "emailpage": "E-mail 給使用者",
        "emailpagetext": "您可以使用以下表格傳送電子郵件給這位 {{Gender:$1|使用者}}。\n您在 [[Special:Preferences|偏好設定]] 中所輸入的電子郵件位址將會作為郵件的 \"寄件人\",因此該使用者可直接回覆您。",
        "defemailsubject": "來自使用者 \"$1\" 於 {{SITENAME}} 寄來的電子郵件",
        "emailsend": "傳送",
        "emailccme": "傳送一份副本到我的電子郵件信箱。",
        "emailccsubject": "您寄給 $1 的訊息副本:$2",
-       "emailsent": "電子郵件已出",
-       "emailsenttext": "您的電子郵件訊息已經出。",
-       "emailuserfooter": "這封電子郵件是由 $1 透過 {{SITENAME}} 的 \"傳送信件給使用者\" 功能寄給 $2。",
+       "emailsent": "電子郵件已出",
+       "emailsenttext": "您的電子郵件訊息已經出。",
+       "emailuserfooter": "這封電子郵件是由 $1 透過 {{SITENAME}} 的 \"E-mail該使用者\" 功能寄給 $2。",
        "usermessage-summary": "留給系統訊息。",
        "usermessage-editor": "系統訊息",
        "watchlist": "監視清單",
        "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": "正在監視...",
        "revertpage-nouser": "已還隱藏使用者的編輯為最後 {{GENDER:$1|[[User:$1|$1]]}} 修訂的版本",
        "rollback-success": "已還原 $1 做的編輯;\n更變回最後由 $2 修訂的版本。",
        "sessionfailure-title": "登入資訊失敗",
-       "sessionfailure": "似乎您的登會話有問題;\n為了防止會話劫持,這個操作已經被取消。\n請返回先前的頁面,重新載入該頁面,然後重試。",
+       "sessionfailure": "似乎您的登會話有問題;\n為了防止會話劫持,這個操作已經被取消。\n請返回先前的頁面,重新載入該頁面,然後重試。",
        "protectlogpage": "保護日誌",
        "protectlogtext": "以下為變更頁面保護的列表。\n請參考 [[Special:ProtectedPages|受保護頁面列表]] 檢視目前受保護頁面。",
        "protectedarticle": "已保護 \"[[$1]]\"",
        "unblock": "解除封鎖使用者",
        "blockip": "封鎖使用者",
        "blockip-legend": "封鎖使用者",
-       "blockiptext": "填寫以下單據可封鎖特定 IP 位或使用者名稱的存取權限。\n這個動作應用來避免破壞行為,可根據 [[{{MediaWiki:Policy-url}}|管理政策]]。\n請在下方填寫一個具體的原因 (例如:引述一段破壞頁面的事實)。",
+       "blockiptext": "填寫以下單據可封鎖特定 IP 位或使用者名稱的存取權限。\n這個動作應用來避免破壞行為,可根據 [[{{MediaWiki:Policy-url}}|管理政策]]。\n請在下方填寫一個具體的原因 (例如:引述一段破壞頁面的事實)。",
        "ipaddressorusername": "IP 位址或使用者名稱:",
        "ipbexpiry": "期限:",
        "ipbreason": "原因:",
        "import-error-create": "您沒有權限建立頁面 \"$1\",無法匯入。",
        "import-error-interwiki": "頁面 \"$1\" 的名稱已保留作為外部連結 (Interwiki) 使用,無法匯入。",
        "import-error-special": "頁面 \"$1\" 屬於不允許頁面的特殊命名空間,無法匯入。",
-       "import-error-invalid": "é \81é\9d¢ \"$1\" å\90\8d稱無效,無法匯入。",
+       "import-error-invalid": "é \81é\9d¢ \"$1\" å\9b å\85¶å\90\8d稱å\9c¨æ­¤wiki無效,無法匯入。",
        "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 測試使用。",
        "exif-contrast": "對比度",
        "exif-saturation": "飽和度",
        "exif-sharpness": "銳利度",
-       "exif-devicesettingdescription": "設å\82\99設定描述",
+       "exif-devicesettingdescription": "è£\9dç½®設定描述",
        "exif-subjectdistancerange": "主體距離範圍",
        "exif-imageuniqueid": "唯一影像識別碼",
        "exif-gpsversionid": "GPS 標籤版本",
        "namespacesall": "全部",
        "monthsall": "全部",
        "confirmemail": "確認郵箱位址",
-       "confirmemail_noemail": "您尚未於 [[Special:Preferences|偏好設定]] 輸入一個有效的電子郵件址。",
-       "confirmemail_text": "{{SITENAME}}要求您在使用郵件功能之前驗證您的郵箱位址。\n點選以下按鈕可向您的郵箱送一封確認郵件。該郵件包含有一行代碼連結;\n請在您的瀏覽器中載入此連結以確認您的郵箱位址是有效的。",
-       "confirmemail_pending": "確認碼已送至您的電子郵件,\n若您才剛建立好您的帳號,可能需要稍後幾分鐘才能收到。\n若沒有收到,請再重新申請一次確認碼。",
+       "confirmemail_noemail": "您尚未於 [[Special:Preferences|偏好設定]] 輸入一個有效的電子郵件址。",
+       "confirmemail_text": "{{SITENAME}}要求您在使用郵件功能之前驗證您的郵箱位址。\n點選以下按鈕可向您的郵箱送一封確認郵件。該郵件包含有一行代碼連結;\n請在您的瀏覽器中載入此連結以確認您的郵箱位址是有效的。",
+       "confirmemail_pending": "確認碼已送至您的電子郵件,\n若您才剛建立好您的帳號,可能需要稍後幾分鐘才能收到。\n若沒有收到,請再重新申請一次確認碼。",
        "confirmemail_send": "郵發確認代碼",
-       "confirmemail_sent": "確認郵件已發送。",
-       "confirmemail_oncreate": "一個確認代碼已經被送到您的郵箱。該代碼並不要求您進行登入,\n但若您要啟用在此 wiki 上的任何基於電子郵件的功能,您必須先提交此代碼。",
-       "confirmemail_sendfailed": "{{SITENAME}}無法送確認郵件,請檢查郵箱位址是否包含非法字元。\n\n郵件傳送員回應: $1",
+       "confirmemail_sent": "確認郵件已寄出。",
+       "confirmemail_oncreate": "一個確認代碼已經被送到您的郵箱。該代碼並不要求您進行登入,\n但若您要啟用在此 wiki 上的任何基於電子郵件的功能,您必須先提交此代碼。",
+       "confirmemail_sendfailed": "{{SITENAME}}無法送確認郵件,請檢查郵箱位址是否包含非法字元。\n\n郵件傳送員回應: $1",
        "confirmemail_invalid": "無效的確認碼,該代碼可能已經過期。",
        "confirmemail_needlogin": "您需要$1以確認您的郵箱位址。",
-       "confirmemail_success": "您的郵箱已經被確認。您現在可以[[Special:UserLogin|登]]並使用此網站了。",
+       "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": "電郵址確認已取消",
+       "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 讀取失敗]",
        "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|秒}}內的變更。",
        "api-error-nomodule": "內部錯誤:缺少上傳模塊集。",
        "api-error-ok-but-empty": "內部錯誤:伺服器沒有響應。",
        "api-error-overwrite": "不允許覆蓋現有檔案。",
-       "api-error-stashfailed": "內部錯誤:伺服器存臨時檔案失敗。",
+       "api-error-stashfailed": "內部錯誤:伺服器存臨時檔案失敗。",
        "api-error-publishfailed": "內部錯誤:伺服器發佈臨時檔案失敗。",
-       "api-error-stasherror": "上檔案存檔時出錯。",
+       "api-error-stasherror": "上檔案存檔時出錯。",
        "api-error-timeout": "伺服器沒有在預期的時間內回應。",
        "api-error-unclassified": "發生未知錯誤。",
        "api-error-unknown-code": "未知錯誤:$1",
        "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|位元組}}",
index 17a18c1..ccdd310 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();
 
@@ -437,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' ),
index 3836ad9..8682ab0 100644 (file)
@@ -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 a07cbc2..3d30b83 100644 (file)
@@ -30,11 +30,13 @@ 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 );
        }
 
        /**
@@ -59,7 +61,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 +137,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 +187,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 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 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 1fedefb..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 );
index 3b29452..b948b67 100644 (file)
  * @ingroup Maintenance
  */
 
-if ( !function_exists( 'version_compare' ) || ( version_compare( PHP_VERSION, '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 f0b6ec7..4ce9474 100644 (file)
@@ -160,7 +160,7 @@ 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
index 21e847b..d9e6fb9 100755 (executable)
@@ -33,7 +33,7 @@ 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"
index e56640f..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,214 +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 = microtime( true ); // 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" );
-
-                               // 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 ) );
-
-                               // 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 (for throttling and for errors)
-                               $ttw = $this->getBackoffTimeToWait( $job );
-                               if ( $status === false && mt_rand( 0, 49 ) == 0 ) {
-                                       $ttw = max( $ttw, 30 );
-                               }
-                               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 = 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
-               $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 );
        }
 }
 
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;
index ae95a56..d3f8f7d 100644 (file)
@@ -113,7 +113,6 @@ return array(
                // skin over-rides common content styling.
                'skinStyles' => array(
                        'default' => 'resources/src/mediawiki.skinning/content.parsoid.less',
-                       'minerva' => array(),
                ),
                'targets' => array( 'desktop', 'mobile' ),
        ),
@@ -329,10 +328,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 +339,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 +352,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 +363,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 +371,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 +456,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',
        ),
@@ -497,7 +487,6 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.menu.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.menu.css',
                ),
                'group' => 'jquery.ui',
        ),
@@ -518,7 +507,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',
        ),
@@ -531,7 +519,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',
        ),
@@ -544,7 +531,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',
        ),
@@ -557,7 +543,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',
        ),
@@ -579,7 +564,6 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.spinner.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.spinner.css',
                ),
                'group' => 'jquery.ui',
        ),
@@ -591,7 +575,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',
        ),
@@ -604,7 +587,6 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.tooltip.css',
-                       'vector' => 'resources/src/jquery.ui-themes/vector/jquery.ui.tooltip.css',
                ),
                'group' => 'jquery.ui',
        ),
@@ -1052,6 +1034,7 @@ return array(
        'mediawiki.action.edit.editWarning' => array(
                'scripts' => 'resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js',
                'dependencies' => array(
+                       'jquery.textSelection',
                        'mediawiki.jqueryMsg'
                ),
                'messages' => array(
@@ -1059,10 +1042,6 @@ return array(
                        'prefs-editing'
                ),
        ),
-       // Alias for backwards compatibility
-       'mediawiki.action.watch.ajax' => array(
-               'dependencies' => 'mediawiki.page.watch.ajax'
-       ),
 
        /* MediaWiki Language */
 
@@ -1200,7 +1179,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 */
@@ -1208,9 +1191,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',
@@ -1260,9 +1240,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',
                ),
@@ -1452,6 +1429,19 @@ return array(
                'position' => 'top',
                'targets' => array( 'desktop', 'mobile' ),
        ),
+       'mediawiki.ui.checkbox' => array(
+               'styles' => array(
+                       'resources/src/mediawiki.ui/components/checkbox.less',
+               ),
+       ),
+       // 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(
                'styles' => array(
@@ -1460,6 +1450,13 @@ return array(
                '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' ),
+       ),
 
        /* es5-shim */
        'es5-shim' => array(
@@ -1473,7 +1470,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(
@@ -1494,18 +1491,19 @@ return array(
                ),
                'skinStyles' => array(
                        'default' => 'resources/lib/oojs-ui/oojs-ui-apex.css',
+                       // FIXME As of July 2014, this is to be gone "in a couple of months".
                        'minerva' => 'resources/lib/oojs-ui/oojs-ui-agora.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 95001fb..3fb201c 100644 (file)
@@ -1,12 +1,9 @@
-/*jshint eqnull:true */
 /*!
- * jQuery Cookie Plugin v1.2
+ * 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 ($, document, undefined) {
 
        }
 
        function decoded(s) {
-               return decodeURIComponent(s.replace(pluses, ' '));
+               return unRfc2068(decodeURIComponent(s.replace(pluses, ' ')));
        }
 
-       $.cookie = function (key, value, options) {
+       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;
+       }
 
-               // key and at least value given, set cookie...
-               if (value !== undefined && !/Object/.test(Object.prototype.toString.call(value))) {
-                       options = $.extend({}, $.cookie.defaults, options);
+       var config = $.cookie = function (key, value, options) {
+
+               // write
+               if (value !== undefined) {
+                       options = $.extend({}, config.defaults, options);
 
                        if (value === null) {
                                options.expires = -1;
                                t.setDate(t.getDate() + days);
                        }
 
-                       value = String(value);
+                       value = config.json ? JSON.stringify(value) : String(value);
 
                        return (document.cookie = [
-                               encodeURIComponent(key), '=', options.raw ? value : encodeURIComponent(value),
+                               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 : '',
                        ].join(''));
                }
 
-               // key and possibly options given, get cookie...
-               options = value || $.cookie.defaults || {};
-               var decode = options.raw ? raw : decoded;
+               // read
+               var decode = config.raw ? raw : decoded;
                var cookies = document.cookie.split('; ');
-               for (var i = 0, parts; (parts = cookies[i] && cookies[i].split('=')); i++) {
-                       if (decode(parts.shift()) === key) {
-                               return decode(parts.join('='));
+               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 null;
+               return result;
        };
 
-       $.cookie.defaults = {};
+       config.defaults = {};
 
        $.removeCookie = function (key, options) {
-               if ($.cookie(key, options) !== null) {
+               if ($.cookie(key) !== null) {
                        $.cookie(key, null, options);
                        return true;
                }
index 4555c11..c3e80fe 100644 (file)
@@ -8,11 +8,13 @@
                        "QuimGil",
                        "SMP",
                        "Vriullop",
-                       "Toniher"
+                       "Toniher",
+                       "Edustus"
                ]
        },
        "ooui-outline-control-move-down": "Baixa element",
        "ooui-outline-control-move-up": "Puja element",
        "ooui-toolbar-more": "Més",
-       "ooui-dialog-process-dismiss": "Descarta"
+       "ooui-dialog-process-dismiss": "Descarta",
+       "ooui-dialog-process-retry": "Torneu-ho a provar"
 }
index 602efc8..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-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"
+       "@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 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..98b6bce 100644 (file)
@@ -8,9 +8,12 @@
                        "Njardarlogar"
                ]
        },
-       "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-reject": "Avbryt",
+       "ooui-dialog-process-error": "Noe gikk galt",
+       "ooui-dialog-process-dismiss": "Lukk",
+       "ooui-dialog-process-retry": "Prøv igjen"
 }
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 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 417bc96..3694391 100644 (file)
@@ -1,9 +1,7 @@
-<?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="anchor">
-       <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>
+<?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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 ad12773..802f295 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="window" opacity=".75">
         <path id="title" d="M7 10h10v1h-10z"/>
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 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 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 ae5383c..525304c 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (9cd400e3d5)
+ * OOjs UI v0.1.0-pre (dd294dc785)
  * 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-22T21:59:46Z
+ * Date: 2014-07-30T23:10:53Z
  */
 .oo-ui-dialog-content > .oo-ui-window-head,
 .oo-ui-dialog-content > .oo-ui-window-body,
 .oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-buttonedElement-button {
   min-width: 1.85em;
   min-height: 1.85em;
-  padding-top: 0.75em;
-  padding-bottom: 0.75em;
+  padding: 0.35em 0.75em;
+  border: 1px solid #dddddd;
+  border-radius: 4px;
 }
 
 .oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-labeledElement-label,
 .oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-labeledElement-label,
 .oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-labeledElement-label {
   padding: 0 1em;
+  font-weight: bold;
   line-height: 1.85em;
+  color: #777777;
 }
 
 .oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-iconedElement-icon,
   margin-top: -0.125em;
 }
 
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonedElement-framed,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonedElement-framed,
-.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonedElement-framed {
-  margin: 0.75em 0 0.75em 0.75em;
-  border: solid 1px #ccc;
-  border-radius: 0.25em;
-}
-
 .oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button,
 .oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button,
 .oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-  padding: 0;
   vertical-align: middle;
 }
 
-.oo-ui-processDialog-actions-safe.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button,
-.oo-ui-processDialog-actions-primary.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-  margin: 0.75em;
-}
-
-.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-buttonedElement-framed,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonedElement-framed {
-  margin: 0.75em;
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggableElement-destructive .oo-ui-buttonedElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggableElement-destructive .oo-ui-buttonedElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-flaggableElement-destructive .oo-ui-buttonedElement-button {
+  border: 1px solid transparent;
 }
 
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonedElement-framed .oo-ui-buttonedElement-button {
-  /* Adjust for border so text aligns with title */
-
-  margin: -1px;
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggableElement-destructive .oo-ui-labeledElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggableElement-destructive .oo-ui-labeledElement-label,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-flaggableElement-destructive .oo-ui-labeledElement-label {
+  color: #d11d13;
 }
 
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggableElement-primary:hover,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggableElement-primary:hover {
-  background-color: rgba(8, 126, 204, 0.05);
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-buttonedElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-buttonedElement-button {
+  padding: 0.75em 0.35em;
+  border: none;
+  border-radius: 0;
 }
 
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggableElement-primary:active,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggableElement-primary:active {
-  background-color: rgba(8, 126, 204, 0.1);
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggableElement-primary .oo-ui-buttonedElement-button {
+  background-color: #347bff;
 }
 
 .oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggableElement-primary .oo-ui-labeledElement-label,
 .oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggableElement-primary .oo-ui-labeledElement-label {
-  font-weight: bold;
-}
-
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggableElement-constructive:hover,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggableElement-constructive:hover {
-  background-color: rgba(118, 171, 54, 0.05);
-}
-
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggableElement-constructive:active,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggableElement-constructive:active {
-  background-color: rgba(118, 171, 54, 0.1);
-}
-
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggableElement-destructive:hover,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggableElement-destructive:hover {
-  background-color: rgba(212, 83, 83, 0.05);
-}
-
-.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggableElement-destructive:active,
-.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggableElement-destructive:active {
-  background-color: rgba(212, 83, 83, 0.1);
+  color: #ffffff;
 }
 
 .oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-iconedElement .oo-ui-iconedElement-icon {
   padding-right: 2.25em;
 }
 
+.oo-ui-processDialog-actions-other {
+  position: absolute;
+  bottom: 1em;
+}
+
 .oo-ui-processDialog > .oo-ui-window-frame {
   min-height: 5em;
 }
   padding: 0 0 1em;
 }
 
+.oo-ui-panelLayout {
+  padding: 1em 3.35em;
+}
+
 .oo-ui-optionWidget {
   padding: 0.8em 1em 0.8em 3.35em;
   font-weight: bold;
   background: #347bff;
 }
 
+.oo-ui-menuItemWidget .oo-ui-iconedElement-icon {
+  background-size: 24px auto;
+}
+
 .oo-ui-menuSectionItemWidget {
   font-weight: normal;
   color: #777777;
index b5a6eee..1267a3c 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (9cd400e3d5)
+ * OOjs UI v0.1.0-pre (dd294dc785)
  * 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-22T21:59:46Z
+ * Date: 2014-07-30T23:10:53Z
  */
 .oo-ui-dialog-content > .oo-ui-window-head,
 .oo-ui-dialog-content > .oo-ui-window-body,
index 170d207..737113e 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (9cd400e3d5)
+ * OOjs UI v0.1.0-pre (dd294dc785)
  * 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-22T21:59:46Z
+ * Date: 2014-07-30T23:10:53Z
  */
 ( 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
 };
 
 /**
@@ -208,9 +208,9 @@ OO.ui.ActionSet = function OoUiActionSet( config ) {
        // Properties
        this.list = [];
        this.categories = {
-               'actions': 'getAction',
-               'flags': 'getFlags',
-               'modes': 'getModes'
+               actions: 'getAction',
+               flags: 'getFlags',
+               modes: 'getModes'
        };
        this.categorized = {};
        this.special = {};
@@ -469,9 +469,9 @@ OO.ui.ActionSet.prototype.add = function ( actions ) {
        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' ]
+                       click: [ 'emit', 'click', action ],
+                       resize: [ 'emit', 'resize', action ],
+                       toggle: [ 'onActionChange' ]
                } );
                this.list.push( action );
        }
@@ -746,7 +746,7 @@ OO.ui.Element.getFrameOffset = function ( from, to, offset ) {
                to = window;
        }
        if ( !offset ) {
-               offset = { 'top': 0, 'left': 0 };
+               offset = { top: 0, left: 0 };
        }
        if ( from.parent === from ) {
                return offset;
@@ -784,7 +784,7 @@ OO.ui.Element.getFrameOffset = function ( from, to, offset ) {
 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 ) };
+       return { top: Math.round( from.top - to.top ), left: Math.round( from.left - to.left ) };
 };
 
 /**
@@ -807,10 +807,10 @@ OO.ui.Element.getBorders = function ( el ) {
                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 )
+               top: Math.round( top ),
+               left: Math.round( left ),
+               bottom: Math.round( bottom ),
+               right: Math.round( right )
        };
 };
 
@@ -829,32 +829,32 @@ OO.ui.Element.getDimensions = function ( el ) {
        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()
+                       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()
+                       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()
+                       borders: this.getBorders( el ),
+                       scroll: {
+                               top: $el.scrollTop(),
+                               left: $el.scrollLeft()
                        },
-                       'scrollbar': {
-                               'right': $el.innerWidth() - el.clientWidth,
-                               'bottom': $el.innerHeight() - el.clientHeight
+                       scrollbar: {
+                               right: $el.innerWidth() - el.clientWidth,
+                               bottom: $el.innerHeight() - el.clientHeight
                        },
-                       'rect': el.getBoundingClientRect()
+                       rect: el.getBoundingClientRect()
                };
        }
 };
@@ -922,18 +922,18 @@ OO.ui.Element.scrollIntoView = function ( el, config ) {
        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
+                       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
+                       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
                };
        }
 
@@ -1118,7 +1118,7 @@ OO.ui.Frame = function OoUiFrame( config ) {
        // Initialize
        this.$element
                .addClass( 'oo-ui-frame' )
-               .attr( { 'frameborder': 0, 'scrolling': 'no' } );
+               .attr( { frameborder: 0, scrolling: 'no' } );
 
 };
 
@@ -1292,10 +1292,13 @@ OO.ui.Frame.prototype.load = function () {
 
        // Initialize contents
        doc.open();
+       // The following classes can be used here:
+       // oo-ui-ltr
+       // oo-ui-rtl
        doc.write(
                '<!doctype html>' +
                '<html>' +
-                       '<body class="oo-ui-frame-content oo-ui-' + this.dir + '" style="direction:' + this.dir + ';" dir="' + this.dir + '">' +
+                       '<body class="oo-ui-frame-content oo-ui-' + this.dir + '" dir="' + this.dir + '">' +
                        '</body>' +
                '</html>'
        );
@@ -1324,7 +1327,7 @@ OO.ui.Frame.prototype.load = function () {
  * @chainable
  */
 OO.ui.Frame.prototype.setSize = function ( width, height ) {
-       this.$element.css( { 'width': width, 'height': height } );
+       this.$element.css( { width: width, height: height } );
        return this;
 };
 
@@ -1372,7 +1375,7 @@ OO.mixinClass( OO.ui.Layout, OO.EventEmitter );
  */
 OO.ui.Widget = function OoUiWidget( config ) {
        // Initialize config
-       config = $.extend( { 'disabled': false }, config );
+       config = $.extend( { disabled: false }, config );
 
        // Parent constructor
        OO.ui.Widget.super.call( this, config );
@@ -1546,7 +1549,7 @@ OO.ui.Window = function OoUiWindow( manager, config ) {
        this.opened = null;
        this.timing = null;
        this.size = config.size || this.constructor.static.size;
-       this.frame = new OO.ui.Frame( { '$': this.$ } );
+       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.' );
@@ -1800,14 +1803,14 @@ OO.ui.Window.prototype.setSize = function ( size ) {
 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 || '',
-               'min-width': dim.minWidth || '',
-               'max-width': dim.maxWidth || ''
+               width: dim.width || '',
+               minWidth: dim.minWidth || '',
+               maxWidth: dim.maxWidth || ''
        } );
        this.$frame.css( {
-               'height': ( dim.height !== undefined ? dim.height : this.getContentHeight() ) || '',
-               'min-height': dim.minHeight || '',
-               'max-height': dim.maxHeight || ''
+               height: ( dim.height !== undefined ? dim.height : this.getContentHeight() ) || '',
+               minHeight: dim.minHeight || '',
+               maxHeight: dim.maxHeight || ''
        } );
        return this;
 };
@@ -2024,9 +2027,9 @@ OO.ui.Dialog = function OoUiDialog( manager, config ) {
 
        // Events
        this.actions.connect( this, {
-               'click': 'onActionClick',
-               'resize': 'onActionResize',
-               'change': 'onActionsChange'
+               click: 'onActionClick',
+               resize: 'onActionResize',
+               change: 'onActionsChange'
        } );
 
        // Initialization
@@ -2188,7 +2191,7 @@ OO.ui.Dialog.prototype.getSetupProcess = function ( data ) {
                        );
                        for ( i = 0, len = actions.length; i < len; i++ ) {
                                items.push(
-                                       new OO.ui.ActionWidget( $.extend( { '$': this.$ }, actions[i] ) )
+                                       new OO.ui.ActionWidget( $.extend( { $: this.$ }, actions[i] ) )
                                );
                        }
                        this.actions.add( items );
@@ -2215,7 +2218,7 @@ OO.ui.Dialog.prototype.initialize = function () {
        OO.ui.Dialog.super.prototype.initialize.call( this );
 
        // Properties
-       this.title = new OO.ui.LabelWidget( { '$': this.$ } );
+       this.title = new OO.ui.LabelWidget( { $: this.$ } );
 
        // Events
        if ( this.constructor.static.escapable ) {
@@ -2321,7 +2324,7 @@ OO.ui.Dialog.prototype.popPending = function () {
  *
  * - {@link #closeWindow} or {@link OO.ui.Window#close} methods are used to start closing
  * - `opened` promise is resolved with `closing` promise
- * - {@link #event-opening} is emitted 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
@@ -2416,19 +2419,19 @@ OO.mixinClass( OO.ui.WindowManager, OO.EventEmitter );
  * @property {Object}
  */
 OO.ui.WindowManager.static.sizes = {
-       'small': {
-               'width': 300
+       small: {
+               width: 300
        },
-       'medium': {
-               'width': 500
+       medium: {
+               width: 500
        },
-       'large': {
-               'width': 700
+       large: {
+               width: 700
        },
-       'full': {
+       full: {
                // These can be non-numeric because they are never used in calculations
-               'width': '100%',
-               'height': '100%'
+               width: '100%',
+               height: '100%'
        }
 };
 
@@ -2606,7 +2609,7 @@ OO.ui.WindowManager.prototype.getWindow = function ( name ) {
                                        'Cannot auto-instantiate window: symbolic name is unrecognized by the factory'
                                ) );
                        } else {
-                               win = this.factory.create( name, this, { '$': this.$ } );
+                               win = this.factory.create( name, this, { $: this.$ } );
                                this.addWindows( [ win ] ).then(
                                        OO.ui.bind( deferred.resolve, deferred, win ),
                                        deferred.reject
@@ -2679,11 +2682,11 @@ OO.ui.WindowManager.prototype.openWindow = function ( win, data ) {
                        if ( manager.modal ) {
                                manager.$( manager.getElementDocument() ).on( {
                                        // Prevent scrolling by keys in top-level window
-                                       'keydown': manager.onDocumentKeyDownHandler
+                                       keydown: manager.onDocumentKeyDownHandler
                                } );
                                manager.$( manager.getElementWindow() ).on( {
                                        // Prevent scrolling by wheel in top-level window
-                                       'mousewheel': manager.onWindowMouseWheelHandler,
+                                       mousewheel: manager.onWindowMouseWheelHandler,
                                        // Start listening for top-level window dimension changes
                                        'orientationchange resize': manager.onWindowResizeHandler
                                } );
@@ -2699,10 +2702,10 @@ OO.ui.WindowManager.prototype.openWindow = function ( win, data ) {
                        manager.updateWindowSize( win );
                        setTimeout( function () {
                                win.setup( data ).then( function () {
-                                       manager.opening.notify( { 'state': 'setup' } );
+                                       manager.opening.notify( { state: 'setup' } );
                                        setTimeout( function () {
                                                win.ready( data ).then( function () {
-                                                       manager.opening.notify( { 'state': 'ready' } );
+                                                       manager.opening.notify( { state: 'ready' } );
                                                        manager.opening = null;
                                                        manager.opened = $.Deferred();
                                                        opening.resolve( manager.opened.promise(), data );
@@ -2769,18 +2772,18 @@ OO.ui.WindowManager.prototype.closeWindow = function ( win, data ) {
                        opened.resolve( closing.promise(), data );
                        setTimeout( function () {
                                win.hold( data ).then( function () {
-                                       closing.notify( { 'state': 'hold' } );
+                                       closing.notify( { state: 'hold' } );
                                        setTimeout( function () {
                                                win.teardown( data ).then( function () {
-                                                       closing.notify( { 'state': 'teardown' } );
+                                                       closing.notify( { state: 'teardown' } );
                                                        if ( manager.modal ) {
                                                                manager.$( manager.getElementDocument() ).off( {
                                                                        // Allow scrolling by keys in top-level window
-                                                                       'keydown': manager.onDocumentKeyDownHandler
+                                                                       keydown: manager.onDocumentKeyDownHandler
                                                                } );
                                                                manager.$( manager.getElementWindow() ).off( {
                                                                        // Allow scrolling by wheel in top-level window
-                                                                       'mousewheel': manager.onWindowMouseWheelHandler,
+                                                                       mousewheel: manager.onWindowMouseWheelHandler,
                                                                        // Stop listening for top-level window dimension changes
                                                                        'orientationchange resize': manager.onWindowResizeHandler
                                                                } );
@@ -3091,16 +3094,16 @@ OO.ui.Process.prototype.execute = function () {
 OO.ui.Process.prototype.createStep = function ( step, context ) {
        if ( typeof step === 'number' || $.isFunction( step.promise ) ) {
                return {
-                       'callback': function () {
+                       callback: function () {
                                return step;
                        },
-                       'context': null
+                       context: null
                };
        }
        if ( $.isFunction( step ) ) {
                return {
-                       'callback': step,
-                       'context': context
+                       callback: step,
+                       context: context
                };
        }
        throw new Error( 'Cannot create process step: number, promise or function expected' );
@@ -3176,8 +3179,8 @@ OO.ui.ToolFactory.prototype.getTools = function ( include, exclude, promote, dem
  *
  * 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: `'*'`
  *
  * @private
@@ -3210,7 +3213,7 @@ OO.ui.ToolFactory.prototype.extract = function ( collection, used ) {
                        item = collection[i];
                        // Allow plain strings as shorthand for named tools
                        if ( typeof item === 'string' ) {
-                               item = { 'name': item };
+                               item = { name: item };
                        }
                        if ( OO.isPlainObject( item ) ) {
                                if ( item.group ) {
@@ -3553,7 +3556,7 @@ OO.ui.ClippableElement.prototype.clip = function () {
        var buffer = 10,
                cOffset = this.$clippable.offset(),
                $container = this.$clippableContainer.is( 'body' ) ? this.$clippableWindow : this.$clippableContainer,
-               ccOffset = $container.offset() || { 'top': 0, 'left': 0 },
+               ccOffset = $container.offset() || { top: 0, left: 0 },
                ccHeight = $container.innerHeight() - buffer,
                ccWidth = $container.innerWidth() - buffer,
                scrollTop = this.$clippableScroller.scrollTop(),
@@ -3566,18 +3569,18 @@ OO.ui.ClippableElement.prototype.clip = function () {
                clipHeight = desiredHeight < naturalHeight;
 
        if ( clipWidth ) {
-               this.$clippable.css( { 'overflow-x': 'auto', 'width': desiredWidth } );
+               this.$clippable.css( { overflowX: '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', '' );
+               this.$clippable.css( 'overflowX', '' );
        }
        if ( clipHeight ) {
-               this.$clippable.css( { 'overflow-y': 'auto', 'height': desiredHeight } );
+               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( 'overflow-y', '' );
+               this.$clippable.css( 'overflowY', '' );
        }
 
        this.clipped = clipWidth || clipHeight;
@@ -3951,7 +3954,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
@@ -4027,7 +4030,7 @@ OO.ui.IndicatedElement = function OoUiIndicatedElement( $indicator, config ) {
        // 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.setIndicatorTitle( config.indicatorTitle || this.constructor.static.indicatorTitle );
 };
 
 /* Setup */
@@ -4211,7 +4214,7 @@ OO.ui.LabeledElement.prototype.getLabel = function () {
  */
 OO.ui.LabeledElement.prototype.fitLabel = function () {
        if ( this.$label.autoEllipsis && this.autoFitLabel ) {
-               this.$label.autoEllipsis( { 'hasSpan': false, 'tooltip': true } );
+               this.$label.autoEllipsis( { hasSpan: false, tooltip: true } );
        }
        return this;
 };
@@ -4233,9 +4236,9 @@ OO.ui.PopuppableElement = function OoUiPopuppableElement( config ) {
 
        // Properties
        this.popup = new OO.ui.PopupWidget( $.extend(
-               { 'autoClose': true },
+               { autoClose: true },
                config.popup,
-               { '$': this.$, '$autoCloseIgnore': this.$element }
+               { $: this.$, $autoCloseIgnore: this.$element }
        ) );
 };
 
@@ -4352,7 +4355,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' );
@@ -4612,7 +4615,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' );
@@ -4659,7 +4662,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] ) {
@@ -4680,8 +4683,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
@@ -4713,7 +4716,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 );
@@ -4788,8 +4791,8 @@ OO.ui.Toolbar.prototype.getToolAccelerator = 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: `'*'`
  *
  * @abstract
@@ -4828,14 +4831,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' );
@@ -4918,8 +4921,9 @@ 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 );
@@ -4938,9 +4942,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 );
 };
 
 /**
@@ -4948,10 +4952,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();
        }
 
@@ -5161,8 +5166,8 @@ OO.ui.MessageDialog.static.title = null;
 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' }
+       { 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 */
@@ -5200,7 +5205,7 @@ OO.ui.MessageDialog.prototype.toggleVerticalActionLayout = function ( value ) {
 OO.ui.MessageDialog.prototype.getActionProcess = function ( action ) {
        if ( action ) {
                return new OO.ui.Process( function () {
-                       this.close( { 'action': action } );
+                       this.close( { action: action } );
                }, this );
        }
        return OO.ui.MessageDialog.super.prototype.getActionProcess.call( this, action );
@@ -5252,13 +5257,13 @@ OO.ui.MessageDialog.prototype.initialize = function () {
        // Properties
        this.$actions = this.$( '<div>' );
        this.container = new OO.ui.PanelLayout( {
-               '$': this.$, 'scrollable': true, 'classes': [ 'oo-ui-messageDialog-container' ]
+               $: 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.$, padded: true, expanded: false, classes: [ 'oo-ui-messageDialog-text' ]
        } );
        this.message = new OO.ui.LabelWidget( {
-               '$': this.$, 'classes': [ 'oo-ui-messageDialog-message' ]
+               $: this.$, classes: [ 'oo-ui-messageDialog-message' ]
        } );
 
        // Initialization
@@ -5408,19 +5413,19 @@ OO.ui.ProcessDialog.prototype.initialize = function () {
        this.$primaryActions = this.$( '<div>' );
        this.$otherActions = this.$( '<div>' );
        this.dismissButton = new OO.ui.ButtonWidget( {
-               '$': this.$,
-               'label': OO.ui.msg( 'ooui-dialog-process-dismiss' )
+               $: 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.$,
+               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' } );
+       this.dismissButton.connect( this, { click: 'onDismissErrorButtonClick' } );
+       this.retryButton.connect( this, { click: 'onRetryButtonClick' } );
 
        // Initialization
        this.title.$element.addClass( 'oo-ui-processDialog-title' );
@@ -5495,7 +5500,7 @@ OO.ui.ProcessDialog.prototype.fitLabel = function () {
                this.$safeActions.is( ':visible' ) ? this.$safeActions.width() : 0,
                this.$primaryActions.is( ':visible' ) ? this.$primaryActions.width() : 0
        );
-       this.$location.css( { 'padding-left': width, 'padding-right': width } );
+       this.$location.css( { paddingLeft: width, paddingRight: width } );
 
        return this;
 };
@@ -5563,31 +5568,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.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
@@ -5663,7 +5668,7 @@ OO.ui.BookletLayout.prototype.onStackLayoutFocus = function ( e ) {
 OO.ui.BookletLayout.prototype.onStackLayoutSet = function ( page ) {
        var $input, layout = this;
        if ( page ) {
-               page.scrollElementIntoView( { 'complete': function () {
+               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 ) {
@@ -5843,7 +5848,7 @@ OO.ui.BookletLayout.prototype.addPages = function ( pages, index ) {
                name = page.getName();
                this.pages[page.getName()] = page;
                if ( this.outlined ) {
-                       item = new OO.ui.OutlineItemWidget( name, page, { '$': this.$ } );
+                       item = new OO.ui.OutlineItemWidget( name, page, { $: this.$ } );
                        page.setOutlineItem( item );
                        items.push( item );
                }
@@ -5974,13 +5979,13 @@ OO.ui.BookletLayout.prototype.updateOutlineWidget = function () {
  * @mixins OO.ui.LabeledElement
  *
  * Available label alignment modes include:
- *  - 'left': Label is before the field and aligned away from it, best for when the user will be
+ *  - 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
+ *  - 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
+ *  - 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
+ *  - inline: Label is after the field and aligned toward it, best for small boolean fields like
  *    checkboxes or radio buttons
  *
  * @constructor
@@ -5992,7 +5997,7 @@ OO.ui.BookletLayout.prototype.updateOutlineWidget = function () {
 OO.ui.FieldLayout = function OoUiFieldLayout( field, config ) {
        var popupButtonWidget;
        // Config initialization
-       config = $.extend( { 'align': 'left' }, config );
+       config = $.extend( { align: 'left' }, config );
 
        // Parent constructor
        OO.ui.FieldLayout.super.call( this, config );
@@ -6003,10 +6008,10 @@ OO.ui.FieldLayout = function OoUiFieldLayout( field, config ) {
        if ( config.help ) {
                popupButtonWidget = new OO.ui.PopupButtonWidget( $.extend(
                        {
-                               '$': this.$,
-                               'frameless': true,
-                               'icon': 'info',
-                               'title': config.help
+                               $: this.$,
+                               frameless: true,
+                               icon: 'info',
+                               title: config.help
                        },
                        config,
                        { label: null }
@@ -6024,7 +6029,7 @@ OO.ui.FieldLayout = function OoUiFieldLayout( field, config ) {
        if ( this.field instanceof OO.ui.InputWidget ) {
                this.$label.on( 'click', OO.ui.bind( this.onLabelClick, this ) );
        }
-       this.field.connect( this, { 'disable': 'onFieldDisable' } );
+       this.field.connect( this, { disable: 'onFieldDisable' } );
 
        // Initialization
        this.$element.addClass( 'oo-ui-fieldLayout' );
@@ -6093,6 +6098,11 @@ OO.ui.FieldLayout.prototype.setAlignment = function ( value ) {
                        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 );
        }
 
@@ -6324,11 +6334,11 @@ OO.ui.GridLayout.prototype.update = function () {
                        panel = this.panels[i];
                        width = this.widths[x];
                        dimensions = {
-                               'width': Math.round( width * 100 ) + '%',
-                               'height': Math.round( height * 100 ) + '%',
-                               'top': Math.round( top * 100 ) + '%',
+                               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' : ''
+                               visibility: width === 0 || height === 0 ? 'hidden' : ''
                        };
                        // If RTL, reverse:
                        if ( OO.ui.Element.getDir( this.$.context ) === 'rtl' ) {
@@ -6411,7 +6421,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 );
@@ -6527,7 +6537,7 @@ 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 );
@@ -6622,7 +6632,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 {
@@ -6752,8 +6762,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
@@ -6817,11 +6827,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 );
 };
 
 /**
@@ -6829,7 +6840,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;
 };
 
@@ -6838,8 +6849,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;
@@ -6912,7 +6924,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' );
@@ -7121,9 +7133,9 @@ OO.ui.LookupInputWidget = function OoUiLookupInputWidget( input, config ) {
        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
+               $: OO.ui.Element.getJQuery( this.$overlay ),
+               input: this.lookupInput,
+               $container: config.$container
        } );
        this.lookupCache = {};
        this.lookupQuery = null;
@@ -7134,11 +7146,11 @@ OO.ui.LookupInputWidget = function OoUiLookupInputWidget( input, config ) {
        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 )
+               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' } );
+       this.lookupInput.connect( this, { change: 'onLookupInputChange' } );
 
        // Initialization
        this.$element.addClass( 'oo-ui-lookupWidget' );
@@ -7352,7 +7364,7 @@ OO.ui.LookupInputWidget.prototype.getLookupMenuItemsFromData = function () {
  */
 OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) {
        // Configuration initialization
-       config = $.extend( { 'icon': 'add-item' }, config );
+       config = $.extend( { icon: 'add-item' }, config );
 
        // Parent constructor
        OO.ui.OutlineControlsWidget.super.call( this, config );
@@ -7365,33 +7377,33 @@ OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, confi
        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.$,
+               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.$,
+               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' )
+               $: this.$,
+               framed: false,
+               icon: 'remove',
+               title: OO.ui.msg( 'ooui-outline-control-remove' )
        } );
 
        // Events
        outline.connect( this, {
-               'select': 'onOutlineChange',
-               'add': 'onOutlineChange',
-               'remove': 'onOutlineChange'
+               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' ] } );
+       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-outlineControlsWidget' );
@@ -7562,7 +7574,7 @@ OO.mixinClass( OO.ui.ButtonGroupWidget, OO.ui.GroupElement );
  */
 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 );
@@ -7582,8 +7594,8 @@ OO.ui.ButtonWidget = function OoUiButtonWidget( config ) {
 
        // 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
@@ -7718,7 +7730,7 @@ OO.ui.ButtonWidget.prototype.setTarget = function ( target ) {
  */
 OO.ui.ActionWidget = function OoUiActionWidget( config ) {
        // Config intialization
-       config = $.extend( { 'framed': false }, config );
+       config = $.extend( { framed: false }, config );
 
        // Parent constructor
        OO.ui.ActionWidget.super.call( this, config );
@@ -8056,7 +8068,7 @@ OO.ui.IndicatorWidget.static.tagName = 'span';
  */
 OO.ui.InlineMenuWidget = function OoUiInlineMenuWidget( config ) {
        // Configuration initialization
-       config = $.extend( { 'indicator': 'down' }, config );
+       config = $.extend( { indicator: 'down' }, config );
 
        // Parent constructor
        OO.ui.InlineMenuWidget.super.call( this, config );
@@ -8068,12 +8080,12 @@ OO.ui.InlineMenuWidget = function OoUiInlineMenuWidget( config ) {
        OO.ui.TitledElement.call( this, this.$label, config );
 
        // Properties
-       this.menu = new OO.ui.MenuWidget( $.extend( { '$': this.$, 'widget': this }, config.menu ) );
+       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' } );
+       this.$element.on( { click: OO.ui.bind( this.onClick, this ) } );
+       this.menu.connect( this, { select: 'onMenuSelect' } );
 
        // Initialization
        this.$handle
@@ -8162,7 +8174,7 @@ OO.ui.InlineMenuWidget.prototype.onClick = function ( e ) {
  */
 OO.ui.InputWidget = function OoUiInputWidget( config ) {
        // Config intialization
-       config = $.extend( { 'readOnly': false }, config );
+       config = $.extend( { readOnly: false }, config );
 
        // Parent constructor
        OO.ui.InputWidget.super.call( this, config );
@@ -8437,7 +8449,7 @@ OO.ui.CheckboxInputWidget.prototype.onEdit = function () {
  */
 OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
        var widget = this;
-       config = $.extend( { 'maxRows': 10 }, config );
+       config = $.extend( { maxRows: 10 }, config );
 
        // Parent constructor
        OO.ui.TextInputWidget.super.call( this, config );
@@ -8518,6 +8530,17 @@ OO.ui.TextInputWidget.prototype.onEdit = function () {
        return OO.ui.TextInputWidget.super.prototype.onEdit.call( this );
 };
 
+/**
+ * @inheritdoc
+ */
+OO.ui.TextInputWidget.prototype.setValue = function ( value ) {
+       // Parent method
+       OO.ui.TextInputWidget.super.prototype.setValue.call( this, value );
+
+       this.adjustSize();
+       return this;
+};
+
 /**
  * Automatically adjust the size of the text input.
  *
@@ -8531,7 +8554,7 @@ OO.ui.TextInputWidget.prototype.adjustSize = function () {
        if ( this.multiline && this.autosize ) {
                $clone = this.$input.clone()
                        .val( this.$input.val() )
-                       .css( { 'height': 0 } )
+                       .css( { height: 0 } )
                        .insertAfter( this.$input );
                // Set inline height property to 0 to measure scroll height
                scrollHeight = $clone[0].scrollHeight;
@@ -8989,7 +9012,7 @@ OO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {
  */
 OO.ui.MenuItemWidget = function OoUiMenuItemWidget( data, config ) {
        // Configuration initialization
-       config = $.extend( { 'icon': 'check' }, config );
+       config = $.extend( { icon: 'check' }, config );
 
        // Parent constructor
        OO.ui.MenuItemWidget.super.call( this, data, config );
@@ -9202,11 +9225,11 @@ OO.ui.PopupWidget = function OoUiPopupWidget( config ) {
        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.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' } );
+       this.closeButton.connect( this, { click: 'onCloseButtonClick' } );
 
        // Initialization
        this.toggleAnchor( config.anchor === undefined || config.anchor );
@@ -9381,7 +9404,7 @@ OO.ui.PopupWidget.prototype.updateDimensions = function ( transition ) {
                containerLeft = Math.round( this.$container.offset().left ),
                containerWidth = this.$container.innerWidth(),
                containerRight = containerLeft + containerWidth,
-               popupOffset = this.width * ( { 'left': 0, 'center': -0.5, 'right': -1 } )[this.align],
+               popupOffset = this.width * ( { left: 0, center: -0.5, right: -1 } )[this.align],
                anchorWidth = this.$anchor.width(),
                popupLeft = popupOffset - padding,
                popupRight = popupOffset + padding + this.width + padding,
@@ -9410,9 +9433,9 @@ OO.ui.PopupWidget.prototype.updateDimensions = function ( transition ) {
 
        // Position body relative to anchor and resize
        this.$popup.css( {
-               'left': popupOffset,
-               'width': this.width,
-               'height': this.height !== null ? this.height : 'auto'
+               left: popupOffset,
+               width: this.width,
+               height: this.height !== null ? this.height : 'auto'
        } );
 
        if ( transition ) {
@@ -9451,23 +9474,23 @@ OO.ui.SearchWidget = function OoUiSearchWidget( config ) {
 
        // Properties
        this.query = new OO.ui.TextInputWidget( {
-               '$': this.$,
-               'icon': 'search',
-               'placeholder': config.placeholder,
-               'value': config.value
+               $: this.$,
+               icon: 'search',
+               placeholder: config.placeholder,
+               value: config.value
        } );
-       this.results = new OO.ui.SelectWidget( { '$': this.$ } );
+       this.results = new OO.ui.SelectWidget( { $: this.$ } );
        this.$query = this.$( '<div>' );
        this.$results = this.$( '<div>' );
 
        // Events
        this.query.connect( this, {
-               'change': 'onQueryChange',
-               'enter': 'onQueryEnter'
+               change: 'onQueryChange',
+               enter: 'onQueryEnter'
        } );
        this.results.connect( this, {
-               'highlight': 'onResultsHighlight',
-               'select': 'onResultsSelect'
+               highlight: 'onResultsHighlight',
+               select: 'onResultsSelect'
        } );
        this.query.$input.on( 'keydown', OO.ui.bind( this.onQueryKeydown, this ) );
 
@@ -9618,9 +9641,9 @@ OO.ui.SelectWidget = function OoUiSelectWidget( config ) {
 
        // 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 )
+               mousedown: OO.ui.bind( this.onMouseDown, this ),
+               mouseover: OO.ui.bind( this.onMouseOver, this ),
+               mouseleave: OO.ui.bind( this.onMouseLeave, this )
        } );
 
        // Initialization
index c7b7d8d..bffc230 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.1.0-pre (9cd400e3d5)
+ * OOjs UI v0.1.0-pre (dd294dc785)
  * 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-22T21:59:46Z
+ * Date: 2014-07-30T23:10:53Z
  */
 /* Textures */
 
   margin: 0;
 }
 
-.oo-ui-frame-body {
+.oo-ui-frame-content {
   padding: 0;
   margin: 0;
-  background: none;
 }
 
 .oo-ui-frame-content:focus {
   line-height: 1em;
 }
 
-.oo-ui-toolbar-bottom .oo-ui-toolbar-bar {
-  position: absolute;
-}
-
 .oo-ui-toolbar-actions {
   float: right;
 }
   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;
diff --git a/resources/lib/oojs/oojs.jquery.js b/resources/lib/oojs/oojs.jquery.js
new file mode 100644 (file)
index 0000000..8be7665
--- /dev/null
@@ -0,0 +1,832 @@
+/*!
+ * OOjs v1.0.11
+ * 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-07-23T20:15:47Z
+ */
+( 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 $ */
+
+oo.isPlainObject = $.isPlainObject;
+
+/*global hasOwn */
+
+/**
+ * @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.
+ *
+ * @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 bindings;
+
+       // 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 ( hasOwn.call( this.bindings, event ) ) {
+               bindings = this.bindings[event];
+       } 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
+               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-- ) {
+                               // 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].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/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/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 bffcf35..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 8e211d8..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 66329e9..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 495a561..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 e088e7d..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 53d4b24..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 b217d9e..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 b1fc456..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 252bf0f..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 84b601b..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 ff1c26f..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 76cecfc..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 9d07914..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 4f624bb..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 d429fd2..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*!
- * jQuery UI Accordion 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Accordion#theming
- */
-.ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; zoom: 1; }
-.ui-accordion .ui-accordion-icons { padding-left: 2.2em; }
-.ui-accordion .ui-accordion-noicons { padding-left: .7em; }
-.ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; }
-.ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
-.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; zoom: 1; }
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 e08d14e..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*!
- * jQuery UI Autocomplete 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Autocomplete#theming
- */
-.ui-autocomplete {
-       position: absolute;
-       top: 0;
-       left: 0;
-       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 */
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 1838f48..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/*!
- * jQuery UI Button 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Button#theming
- */
-.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
-.ui-button, .ui-button:link, .ui-button:visited, .ui-button:hover, .ui-button:active { text-decoration: none; }
-.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
-button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
-.ui-button-icons-only { width: 3.4em; }
-button.ui-button-icons-only { width: 3.7em; }
-
-/*button text element */
-.ui-button .ui-button-text { display: block; line-height: 1.4;  }
-.ui-button-text-only .ui-button-text { padding: .125em .25em; }
-.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
-.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
-.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 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: .4em 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-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
-.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
-.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
-.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
-.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .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 2e088ca..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*!
- * jQuery UI CSS Framework 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Theming/API
- */
-
-/* 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:before, .ui-helper-clearfix:after { content: ""; display: table; }
-.ui-helper-clearfix:after { clear: both; }
-.ui-helper-clearfix { zoom: 1; }
-.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 c946ce4..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*!
- * jQuery UI Datepicker 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Datepicker#theming
- */
-.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: .7em 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%; font-size:0em; }
-
-/* 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 {
-    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 78f8f8f..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*!
- * jQuery UI Dialog 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Dialog#theming
- */
-.ui-dialog { position: absolute; top: 0; left: 0; 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 { position: relative; 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-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
-.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.menu.css b/resources/src/jquery.ui-themes/vector/jquery.ui.menu.css
deleted file mode 100644 (file)
index 83fd84e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*!
- * jQuery UI Menu 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Menu#theming
- */
-.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; }
-.ui-menu .ui-menu { margin-top: -3px; position: absolute; }
-.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1; width: 100%; }
-.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
-.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
-.ui-menu .ui-menu-item a.ui-state-focus,
-.ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; }
-
-.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }
-.ui-menu .ui-state-disabled a { cursor: default; }
-
-/* icon support */
-.ui-menu-icons { position: relative; }
-.ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; }
-
-/* left-aligned */
-.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
-
-/* right-aligned */
-.ui-menu .ui-menu-icon { position: static; float: right; }
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 bd7e403..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/*!
- * jQuery UI Progressbar 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Progressbar#theming
- */
-.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
-.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 f8822e8..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*!
- * jQuery UI Resizable 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Resizable#theming
- */
-.ui-resizable { position: relative;}
-.ui-resizable-handle { position: absolute;font-size: 0.1px; 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 5854c41..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/*!
- * jQuery UI Selectable 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Selectable#theming
- */
-.ui-selectable-helper { position: absolute; z-index: 100; 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 e579478..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*!
- * jQuery UI Slider 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Slider#theming
- */
-.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.spinner.css b/resources/src/jquery.ui-themes/vector/jquery.ui.spinner.css
deleted file mode 100644 (file)
index e89b720..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*!
- * jQuery UI Spinner 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Spinner#theming
- */
-.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }
-.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }
-.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }
-.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */
-.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */
-.ui-spinner-up { top: 0; }
-.ui-spinner-down { bottom: 0; }
-
-/* TR overrides */
-.ui-spinner .ui-icon-triangle-1-s {
-       /* need to fix icons sprite */
-       background-position:-65px -16px;
-}
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 11a000f..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-/*!
- * jQuery UI Tabs 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Tabs#theming
- */
-.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: 0; margin: 1px .2em 0 0; border-bottom: 0; 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-active { margin-bottom: -1px; padding-bottom: 1px; }
-.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
-.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active 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; }
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 7452e97..0000000
+++ /dev/null
@@ -1,245 +0,0 @@
-/*!
- * jQuery UI CSS Framework 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- *
- * http://docs.jquery.com/UI/Theming/API
- *
- * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=sans-serif&fwDefault=normal&fsDefault=1.0em&cornerRadius=3px&bgColorHeader=ffffff&bgTextureHeader=highlight_soft&bgImgOpacityHeader=100&borderColorHeader=aed0ea&fcHeader=222222&iconColorHeader=72a7cf&bgColorContent=f2f5f7&bgTextureContent=highlight_hard&bgImgOpacityContent=100&borderColorContent=cccccc&fcContent=362b36&iconColorContent=72a7cf&bgColorDefault=d7ebf9&bgTextureDefault=highlight_hard&bgImgOpacityDefault=80&borderColorDefault=aed0ea&fcDefault=2779aa&iconColorDefault=3d80b3&bgColorHover=e4f1fb&bgTextureHover=highlight_soft&bgImgOpacityHover=100&borderColorHover=74b2e2&fcHover=0070a3&iconColorHover=2694e8&bgColorActive=f0f0f0&bgTextureActive=inset_hard&bgImgOpacityActive=100&borderColorActive=cccccc&fcActive=000000&iconColorActive=666666&bgColorHighlight=ffef8f&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=25&borderColorHighlight=f9dd34&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=cd0a0a&bgTextureError=flat&bgImgOpacityError=15&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffffff&bgColorOverlay=000000&bgTextureOverlay=glow_ball&bgImgOpacityOverlay=100&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&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-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; }
-
-/* 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, .ui-state-hover a:link, .ui-state-hover a:visited { 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; }
-
-/* 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; }
-.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */
-
-/* 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-on { background-position: -96px -144px; }
-.ui-icon-radio-off { 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-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 0; -webkit-border-top-left-radius: 0; -khtml-border-top-left-radius: 0; border-top-left-radius: 0; }
-.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 0; -webkit-border-top-right-radius: 0; -khtml-border-top-right-radius: 0; border-top-right-radius: 0; }
-.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 0; -webkit-border-bottom-left-radius: 0; -khtml-border-bottom-left-radius: 0; border-bottom-left-radius: 0; }
-.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 0; -webkit-border-bottom-right-radius: 0; -khtml-border-bottom-right-radius: 0; border-bottom-right-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); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
\ No newline at end of file
diff --git a/resources/src/jquery.ui-themes/vector/jquery.ui.tooltip.css b/resources/src/jquery.ui-themes/vector/jquery.ui.tooltip.css
deleted file mode 100644 (file)
index 88b0d02..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*!
- * jQuery UI Tooltip 1.9.2
- * http://jqueryui.com
- *
- * Copyright 2012 jQuery Foundation and other contributors
- * Released under the MIT license.
- * http://jquery.org/license
- */
-.ui-tooltip {
-       padding: 8px;
-       position: absolute;
-       z-index: 9999;
-       max-width: 300px;
-       -webkit-box-shadow: 0 0 5px #aaa;
-       box-shadow: 0 0 5px #aaa;
-}
-/* Fades and background-images don't work well together in IE6, drop the image */
-* html .ui-tooltip {
-       background-image: none;
-}
-body .ui-tooltip { border-width: 2px; }
index 0573f66..289cd22 100644 (file)
                        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)
                }
 
                context = $( this ).data( 'wikiEditor-context' );
-               hasWikiEditorSurface = ( context !== undefined );
+               hasWikiEditorSurface = ( context !== undefined && context.$iframe !== undefined );
 
                // IE selection restore voodoo
                needSave = false;
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 ae08c9f..ec9888f 100644 (file)
@@ -1,30 +1,6 @@
 // ----------------------------------------------------------------------------
 // Form styling mixins
 // ----------------------------------------------------------------------------
-
-// Font is not included.
-.agora-field-styling() {
-
-       border: 1px solid @colorFieldBorder;
-
-       &: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: lighten(@colorProgressive, 6%) 0 0 5px;
-
-               border-color: lighten(@colorProgressive, 6%);
-       }
-
-       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-size: 0.9em;
        color: @colorText;
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 2f1b795..47c3526 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 {
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,
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 );
+}
index 189dae8..ebf4779 100644 (file)
@@ -24,6 +24,7 @@
 //
 // Styleguide 2.1.
 .mw-ui-button {
+       font-size: 1em;
        // Container layout
        display: inline-block;
        padding: .5em 1em;
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..eced8cf
--- /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 we wrap a checkbox and label inside mw-ui-checkbox
+// 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
+// Ensure to markup the checkbox and label with 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;
+               }
+       }
+}
index 2e586a6..7c01350 100644 (file)
 // 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.
+// 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 value="input">
+//     <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>
@@ -41,7 +41,6 @@
        width: @defaultFormWidth;
 
        // MW currently doesn't use the type attribute everywhere on inputs.
-       input,
        select,
        .mw-ui-button {
                display: block;
                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 {
@@ -63,7 +56,7 @@
                vertical-align: middle;
        }
 
-       label {
+       label {
                display: block;
                .box-sizing(border-box);
                .agora-label-styling();
@@ -73,7 +66,6 @@
        }
 
        // Override input styling just for checkboxes and radio inputs.
-       input[type="checkbox"],
        input[type="radio"] {
                display: inline;
                .box-sizing(content-box);
        margin: 0 0 15px;
        padding: 0;
        width: 100%;
-
-       input {
-               font-size: 1em;
-               line-height: 1.4;
-       }
-}
-
-// 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
-       font-size: 1em;
-       line-height: 1.4em;
 }
 
 // Apply mw-ui-label to individual elements to style them.
        .agora-label-styling(); // mixins/forms.less
 }
 
-// Nesting an input checkbox or radio button inside a label with this class
+// Nesting an input  inside a label with this class
 // improves alignment, e.g.
-//     <label class="mw-ui-checkbox-label">
-//             <input type="checkbox">The label text
+//     <label class="mw-ui-radio-label">
+//             <input type="radio">The label text
 //     </label>
-.mw-ui-checkbox-label, .mw-ui-radio-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..25dba78
--- /dev/null
@@ -0,0 +1,109 @@
+// 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
+//
+// When using an input or textarea apply the mw-ui-input class.
+//
+// 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 value="input" class="mw-ui-input" value="input">
+// <textarea class="mw-ui-input">textarea</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;
+       // 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;
+       }
+
+       &:focus {
+               box-shadow: inset .45em 0 0 #5088f7;
+               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 value="input" class="mw-ui-input mw-ui-input-inline" value="input">
+// <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 more attention to one instance. For example add topic / reply to post forms.
+// Currently in draft status and subject to change. When used on an input, the text is styled
+// in a large font. When used alongside another mw-ui-input large they are pushed together to seem like
+// one contiguous input.
+//
+// Markup:
+// <input value="input" class="mw-ui-input mw-ui-input-large" value="input">
+// <textarea class="mw-ui-input mw-ui-input-large">textarea</textarea>
+//
+// Styleguide 1.3.
+.mw-ui-input-large {
+       margin-top: 0;
+       margin-bottom: 0;
+       & + .mw-ui-input-large {
+               border-top-width: 0;
+       }
+}
+
+input.mw-ui-input-large {
+       font-size: 1.75em;
+       font-weight: bold;
+       line-height: 1.25em;
+}
index ccfb677..0bbb440 100644 (file)
@@ -1,8 +1,6 @@
 // Utilities
 //
 // Other things which effect the behaviour of components
-//
-// Styleguide 4.
 
 // Flush left
 //
@@ -13,8 +11,6 @@
 //   <label>Username <a href="#" class="mw-ui-flush-left">?</a></label>
 //   <input>
 // </div>
-//
-// Styleguide 4.1.
 .mw-ui-flush-left {
        float: left;
        margin-left: 0;
@@ -30,8 +26,6 @@
 //   <label>Username <a href="#" class="mw-ui-flush-right">?</a></label>
 //   <input>
 // </div>
-//
-// Styleguide 4.2.
 .mw-ui-flush-right {
        float: right;
        padding-right: 0;
@@ -46,8 +40,6 @@
 // <div>
 //   <button class="mw-ui-center-block">click me</button>
 // </div>
-//
-// Styleguide 4.3.
 .mw-ui-center-block {
        display: block;
        margin-left: auto;
index d21b814..c9d6208 100644 (file)
@@ -1,6 +1,5 @@
 /**
  * Provide Agora appearance for mw-ui-* classes.
  */
-
 @import "components/forms";
 @import "components/utilities";
index 591acff..dd823ee 100644 (file)
@@ -1,3 +1,10 @@
 {
-       "skinname-monobook": "MonoBook"
+       "@metadata": {
+               "authors": [
+                       "Pikne"
+               ]
+       },
+       "skinname-monobook": "MonoBook",
+       "monobook.css": "/* Siin asuv kaskaadilaadistik puudutab kõiki MonoBooki-kujunduse kasutajaid. */",
+       "monobook.js": "/* Siin asuv JavaScript laaditakse MonoBooki-kujunduse kasutajate jaoks. */"
 }
index 89bfb40..9e4f058 100644 (file)
@@ -1,10 +1,12 @@
 {
        "@metadata": {
                "authors": [
-                       "Rotemliss"
+                       "Rotemliss",
+                       "Amire80"
                ]
        },
        "skinname-monobook": "מונובוק",
+       "monobook-desc": "העיצוב הקלאסי של מדיה־ויקי מ־2004, שנקרא על שם הצילום השחור־לבן של ספר ברקע",
        "monobook.css": "/* הסגנונות הנכתבים כאן ישפיעו על העיצוב MonoBook בלבד */",
        "monobook.js": "/* כל סקריפט JavaScript שנכתב כאן ירוץ רק עבור המשתמשים בעיצוב Monobook */"
 }
index cb76ae3..1fb9ad4 100644 (file)
@@ -892,11 +892,6 @@ div.mw-lag-warn-high {
        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;
index be8719a..a08d121 100644 (file)
@@ -62,3 +62,27 @@ $wgResourceModules['skins.vector.js'] = array(
        'remoteSkinPath' => 'Vector',
        'localBasePath' => __DIR__,
 );
+
+// Apply module customizations
+$wgResourceModuleSkinStyles['vector'] = array(
+       'jquery.tipsy' => 'skinStyles/jquery.tipsy.less',
+       'jquery.ui.core' => array(
+               'skinStyles/jquery.ui/jquery.ui.core.css',
+               'skinStyles/jquery.ui/jquery.ui.theme.css',
+       ),
+       'jquery.ui.accordion' => 'skinStyles/jquery.ui/jquery.ui.accordion.css',
+       'jquery.ui.autocomplete' => 'skinStyles/jquery.ui/jquery.ui.autocomplete.css',
+       'jquery.ui.button' => 'skinStyles/jquery.ui/jquery.ui.button.css',
+       'jquery.ui.datepicker' => 'skinStyles/jquery.ui/jquery.ui.datepicker.css',
+       'jquery.ui.dialog' => 'skinStyles/jquery.ui/jquery.ui.dialog.css',
+       'jquery.ui.progressbar' => 'skinStyles/jquery.ui/jquery.ui.progressbar.css',
+       'jquery.ui.resizable' => 'skinStyles/jquery.ui/jquery.ui.resizable.css',
+       'jquery.ui.selectable' => 'skinStyles/jquery.ui/jquery.ui.selectable.css',
+       'jquery.ui.slider' => 'skinStyles/jquery.ui/jquery.ui.slider.css',
+       'jquery.ui.tabs' => 'skinStyles/jquery.ui/jquery.ui.tabs.css',
+       'mediawiki.notification' => 'skinStyles/mediawiki.notification.less',
+       'mediawiki.special' => 'skinStyles/mediawiki.special.less',
+       'mediawiki.special.preferences' => 'skinStyles/mediawiki.special.preferences.less',
+       'remoteSkinPath' => 'Vector',
+       'localBasePath' => __DIR__,
+);
index 0ec031f..291b761 100644 (file)
@@ -492,7 +492,9 @@ class VectorTemplate extends BaseTemplate {
                                                echo ' emptyPortlet';
                                        }
                                        ?>" aria-labelledby="p-cactions-label">
-                                               <h3 id="p-cactions-label"><span><?php $this->msg( 'vector-more-actions' ) ?></span><a href="#"></a></h3>
+                                               <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' ) ?>>
index 33cd230..1aee34d 100644 (file)
@@ -132,9 +132,3 @@ pre, .mw-code {
        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/notifications.less b/skins/Vector/components/notifications.less
deleted file mode 100644 (file)
index 5bb6f1a..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/* mediawiki.notification */
-
-// This wrapper class is needed to ensure these rules have larger CSS
-// selector specificity than default styles
-.mediawiki {
-       .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);
-       }
-}
index f94be4c..f5e80ac 100644 (file)
@@ -3,7 +3,8 @@
                "authors": [
                        "CERminator",
                        "DzWiki",
-                       "KWiki"
+                       "KWiki",
+                       "Edinwiki"
                ]
        },
        "vector-action-addsection": "Dodaj temu",
@@ -16,5 +17,6 @@
        "vector-view-edit": "Uredi",
        "vector-view-history": "Pregled historije",
        "vector-view-view": "Čitanje",
-       "vector-view-viewsource": "Pogledaj izvor"
+       "vector-view-viewsource": "Pogledaj izvor",
+       "vector-more-actions": "Više"
 }
diff --git a/skins/Vector/i18n/bto.json b/skins/Vector/i18n/bto.json
new file mode 100644 (file)
index 0000000..4dd54b8
--- /dev/null
@@ -0,0 +1,18 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Filipinayzd"
+               ]
+       },
+       "vector-action-delete": "Puraon",
+       "vector-action-move": "Ilipat",
+       "vector-action-protect": "Protektaran",
+       "vector-action-undelete": "Ibalik",
+       "vector-action-unprotect": "Ribayan a proteksyon",
+       "vector-view-create": "Gumibo",
+       "vector-view-edit": "Balyowan",
+       "vector-view-history": "Baydon a kasaysayan",
+       "vector-view-view": "Basahon",
+       "vector-view-viewsource": "Baydon a ginikanan",
+       "vector-more-actions": "Dakul pa"
+}
index 718b93c..fc01b32 100644 (file)
@@ -7,6 +7,9 @@
                ]
        },
        "skinname-vector": "Vektor",
+       "vector-skin-desc": "MonoBooki uuem versioon värskema väljanägemise ja mitme kasutajasõbralikuma täiendusega",
+       "vector.css": "/* Siin asuv kaskaadilaadistik puudutab kõiki Vektori-kujunduse kasutajaid. */",
+       "vector.js": "/* Siin asuv JavaScript laaditakse kõigi Vektori-kujunduse kasutajate jaoks. */",
        "vector-action-addsection": "Lisa teema",
        "vector-action-delete": "Kustuta",
        "vector-action-move": "Teisalda",
index 08a9023..887d86b 100644 (file)
@@ -6,6 +6,7 @@
                ]
        },
        "skinname-vector": "וקטור",
+       "vector-skin-desc": "גרסה מודרנית של מונובוק עם מראה רענן והרבה שיפורי שמישות",
        "vector.css": "/* הסגנונות הנכתבים כאן ישפיעו על העיצוב Vector בלבד */",
        "vector.js": "/* כל סקריפט JavaScript שנכתב כאן ירוץ רק עבור המשתמשים בעיצוב Vector */",
        "vector-action-addsection": "הוספת נושא",
index f8b322d..79e4601 100644 (file)
@@ -3,7 +3,8 @@
                "authors": [
                        "Teak",
                        "Vadgt",
-                       "Xelgen"
+                       "Xelgen",
+                       "Arman musikyan"
                ]
        },
        "skinname-vector": "Սովորական",
@@ -17,5 +18,6 @@
        "vector-view-edit": "Խմբագրել",
        "vector-view-history": "Դիտել պատմությունը",
        "vector-view-view": "Կարդալ",
-       "vector-view-viewsource": "Դիտել ելատեքստը"
+       "vector-view-viewsource": "Դիտել ելատեքստը",
+       "vector-more-actions": "Ավելին"
 }
index 85e8574..cfacc3f 100644 (file)
@@ -6,6 +6,7 @@
                        "Yerpo"
                ]
        },
+       "vector-skin-desc": "Sodobna različica MonoBook s svežim videzom in mnogimi izboljšavami uporabnosti",
        "vector-action-addsection": "Dodaj temo",
        "vector-action-delete": "Izbriši",
        "vector-action-move": "Prestavi",
diff --git a/skins/Vector/skinStyles/jquery.tipsy.less b/skins/Vector/skinStyles/jquery.tipsy.less
new file mode 100644 (file)
index 0000000..0e0c8ec
--- /dev/null
@@ -0,0 +1,4 @@
+/* Tooltips are outside of the normal body code, so this helps make the size of the text sensible */
+.tipsy {
+       font-size: 0.8em;
+}
diff --git a/skins/Vector/skinStyles/jquery.ui/images/close.png b/skins/Vector/skinStyles/jquery.ui/images/close.png
new file mode 100644 (file)
index 0000000..ef0dd9e
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/close.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/titlebar-fade.png b/skins/Vector/skinStyles/jquery.ui/images/titlebar-fade.png
new file mode 100644 (file)
index 0000000..12a80c8
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/titlebar-fade.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-anim_basic_16x16.gif b/skins/Vector/skinStyles/jquery.ui/images/ui-anim_basic_16x16.gif
new file mode 100644 (file)
index 0000000..085ccae
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-anim_basic_16x16.gif differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-bg_flat_15_cd0a0a_40x100.png b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_flat_15_cd0a0a_40x100.png
new file mode 100644 (file)
index 0000000..09de537
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_flat_15_cd0a0a_40x100.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-bg_flat_70_000000_40x100.png b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_flat_70_000000_40x100.png
new file mode 100644 (file)
index 0000000..c06dd56
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_flat_70_000000_40x100.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png
new file mode 100644 (file)
index 0000000..5308b46
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-hard_100_f2f5f7_1x100.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png
new file mode 100644 (file)
index 0000000..0c8997f
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-hard_80_d7ebf9_1x100.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png
new file mode 100644 (file)
index 0000000..3149255
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-soft_100_e4f1fb_1x100.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-soft_100_ffffff_1x100.png b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-soft_100_ffffff_1x100.png
new file mode 100644 (file)
index 0000000..09b2376
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-soft_100_ffffff_1x100.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-soft_25_ffef8f_1x100.png b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-soft_25_ffef8f_1x100.png
new file mode 100644 (file)
index 0000000..66627c1
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_highlight-soft_25_ffef8f_1x100.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-bg_inset-hard_100_f0f0f0_1x100.png b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_inset-hard_100_f0f0f0_1x100.png
new file mode 100644 (file)
index 0000000..ccb6dc0
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-bg_inset-hard_100_f0f0f0_1x100.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-icons_2694e8_256x240.png b/skins/Vector/skinStyles/jquery.ui/images/ui-icons_2694e8_256x240.png
new file mode 100644 (file)
index 0000000..998ac3b
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-icons_2694e8_256x240.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-icons_2e83ff_256x240.png b/skins/Vector/skinStyles/jquery.ui/images/ui-icons_2e83ff_256x240.png
new file mode 100644 (file)
index 0000000..84b601b
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-icons_2e83ff_256x240.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-icons_3d80b3_256x240.png b/skins/Vector/skinStyles/jquery.ui/images/ui-icons_3d80b3_256x240.png
new file mode 100644 (file)
index 0000000..ec129a8
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-icons_3d80b3_256x240.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-icons_666666_256x240.png b/skins/Vector/skinStyles/jquery.ui/images/ui-icons_666666_256x240.png
new file mode 100644 (file)
index 0000000..a32c57d
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-icons_666666_256x240.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-icons_72a7cf_256x240.png b/skins/Vector/skinStyles/jquery.ui/images/ui-icons_72a7cf_256x240.png
new file mode 100644 (file)
index 0000000..88fad1a
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-icons_72a7cf_256x240.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/images/ui-icons_ffffff_256x240.png b/skins/Vector/skinStyles/jquery.ui/images/ui-icons_ffffff_256x240.png
new file mode 100644 (file)
index 0000000..29ba7d2
Binary files /dev/null and b/skins/Vector/skinStyles/jquery.ui/images/ui-icons_ffffff_256x240.png differ
diff --git a/skins/Vector/skinStyles/jquery.ui/jquery.ui.accordion.css b/skins/Vector/skinStyles/jquery.ui/jquery.ui.accordion.css
new file mode 100644 (file)
index 0000000..d429fd2
--- /dev/null
@@ -0,0 +1,16 @@
+/*!
+ * jQuery UI Accordion 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion#theming
+ */
+.ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; zoom: 1; }
+.ui-accordion .ui-accordion-icons { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-noicons { padding-left: .7em; }
+.ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; zoom: 1; }
diff --git a/skins/Vector/skinStyles/jquery.ui/jquery.ui.autocomplete.css b/skins/Vector/skinStyles/jquery.ui/jquery.ui.autocomplete.css
new file mode 100644 (file)
index 0000000..da6de45
--- /dev/null
@@ -0,0 +1,40 @@
+/* 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/skins/Vector/skinStyles/jquery.ui/jquery.ui.button.css b/skins/Vector/skinStyles/jquery.ui/jquery.ui.button.css
new file mode 100644 (file)
index 0000000..8c2286d
--- /dev/null
@@ -0,0 +1,347 @@
+/* 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/skins/Vector/skinStyles/jquery.ui/jquery.ui.core.css b/skins/Vector/skinStyles/jquery.ui/jquery.ui.core.css
new file mode 100644 (file)
index 0000000..2e088ca
--- /dev/null
@@ -0,0 +1,39 @@
+/*!
+ * jQuery UI CSS Framework 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ */
+
+/* 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:before, .ui-helper-clearfix:after { content: ""; display: table; }
+.ui-helper-clearfix:after { clear: both; }
+.ui-helper-clearfix { zoom: 1; }
+.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/skins/Vector/skinStyles/jquery.ui/jquery.ui.datepicker.css b/skins/Vector/skinStyles/jquery.ui/jquery.ui.datepicker.css
new file mode 100644 (file)
index 0000000..871bf69
--- /dev/null
@@ -0,0 +1,61 @@
+/* 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/skins/Vector/skinStyles/jquery.ui/jquery.ui.dialog.css b/skins/Vector/skinStyles/jquery.ui/jquery.ui.dialog.css
new file mode 100644 (file)
index 0000000..cd85f14
--- /dev/null
@@ -0,0 +1,37 @@
+/* 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/skins/Vector/skinStyles/jquery.ui/jquery.ui.progressbar.css b/skins/Vector/skinStyles/jquery.ui/jquery.ui.progressbar.css
new file mode 100644 (file)
index 0000000..bd7e403
--- /dev/null
@@ -0,0 +1,12 @@
+/*!
+ * jQuery UI Progressbar 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar#theming
+ */
+.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }
\ No newline at end of file
diff --git a/skins/Vector/skinStyles/jquery.ui/jquery.ui.resizable.css b/skins/Vector/skinStyles/jquery.ui/jquery.ui.resizable.css
new file mode 100644 (file)
index 0000000..f1bd7c5
--- /dev/null
@@ -0,0 +1,19 @@
+/* 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/skins/Vector/skinStyles/jquery.ui/jquery.ui.selectable.css b/skins/Vector/skinStyles/jquery.ui/jquery.ui.selectable.css
new file mode 100644 (file)
index 0000000..5854c41
--- /dev/null
@@ -0,0 +1,11 @@
+/*!
+ * jQuery UI Selectable 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectable#theming
+ */
+.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
diff --git a/skins/Vector/skinStyles/jquery.ui/jquery.ui.slider.css b/skins/Vector/skinStyles/jquery.ui/jquery.ui.slider.css
new file mode 100644 (file)
index 0000000..e579478
--- /dev/null
@@ -0,0 +1,25 @@
+/*!
+ * jQuery UI Slider 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider#theming
+ */
+.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/skins/Vector/skinStyles/jquery.ui/jquery.ui.tabs.css b/skins/Vector/skinStyles/jquery.ui/jquery.ui.tabs.css
new file mode 100644 (file)
index 0000000..11a000f
--- /dev/null
@@ -0,0 +1,18 @@
+/*!
+ * jQuery UI Tabs 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs#theming
+ */
+.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: 0; margin: 1px .2em 0 0; border-bottom: 0; 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-active { margin-bottom: -1px; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active 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; }
diff --git a/skins/Vector/skinStyles/jquery.ui/jquery.ui.theme.css b/skins/Vector/skinStyles/jquery.ui/jquery.ui.theme.css
new file mode 100644 (file)
index 0000000..6bde5d3
--- /dev/null
@@ -0,0 +1,246 @@
+
+
+/*
+* 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-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; }
+
+/* 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; }
diff --git a/skins/Vector/skinStyles/mediawiki.notification.less b/skins/Vector/skinStyles/mediawiki.notification.less
new file mode 100644 (file)
index 0000000..55cfe76
--- /dev/null
@@ -0,0 +1,24 @@
+@import "../variables";
+
+/* mediawiki.notification */
+
+// This wrapper class is needed to ensure these rules have larger CSS
+// selector specificity than default styles
+.mediawiki {
+       .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/skinStyles/mediawiki.special.less b/skins/Vector/skinStyles/mediawiki.special.less
new file mode 100644 (file)
index 0000000..6af4b1e
--- /dev/null
@@ -0,0 +1,7 @@
+/**
+ * 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/skinStyles/mediawiki.special.preferences.less b/skins/Vector/skinStyles/mediawiki.special.preferences.less
new file mode 100644 (file)
index 0000000..592a64d
--- /dev/null
@@ -0,0 +1,114 @@
+@import "mediawiki.mixins";
+@import "../variables";
+
+/**
+ * The following code is highly modified from monobook. It would be nice if the
+ * preftoc id was more human readable like preferences-toc for instance,
+ * howerver this would require backporting the other skins.
+ */
+
+#preftoc {
+       /* Tabs */
+       width: 100%;
+       float: left;
+       clear: both;
+       margin: 0 !important;
+       padding: 0 !important;
+       .background-image('images/preferences/break.png');
+       background-position: bottom left;
+       background-repeat: no-repeat;
+
+       li {
+               /* Tab */
+               float: left;
+               margin: 0;
+               padding: 0;
+               padding-right: 1px;
+               height: 2.25em;
+               white-space: nowrap;
+               list-style-type: none;
+               list-style-image: none;
+               .background-image('images/preferences/break.png');
+               background-position: bottom right;
+               background-repeat: no-repeat;
+
+               /* Sadly, IE6 won't understand this */
+               &:first-child {
+                       margin-left: 1px;
+               }
+
+               &.selected {
+                       a {
+                               .background-image('images/preferences/fade.png');
+                               background-position: bottom;
+                               background-repeat: repeat-x;
+                               color: #333;
+                               text-decoration: none;
+                       }
+               }
+       }
+
+       a,
+       a:active {
+               display: inline-block;
+               position: relative;
+               color: @menu-link-color;
+               padding: 0.5em;
+               text-decoration: none;
+               background-image: none;
+               font-size: 0.9em;
+       }
+
+       a:hover,
+       a:focus {
+               text-decoration: underline;
+       }
+}
+
+#preferences {
+       float: left;
+       width: 100%;
+       margin: 0;
+       margin-top: -2px;
+       clear: both;
+       border: solid 1px #ccc;
+       background-color: #fafafa;
+
+       fieldset {
+               border: none;
+               border-top: solid 1px #ccc;
+
+               &.prefsection {
+                       border: none;
+                       padding: 0;
+                       margin: 1em;
+
+                       legend.mainLegend {
+                               display: none;
+                       }
+               }
+       }
+
+       legend {
+               color: #666;
+       }
+
+       td {
+               padding-left: 0.5em;
+               padding-right: 0.5em;
+       }
+
+       div.mw-prefs-buttons {
+               padding: 1em;
+
+               input {
+                       margin-right: 0.25em;
+               }
+       }
+}
+
+.htmlform-tip {
+       font-size: x-small;
+       padding: .2em 2em;
+       color: #666;
+}
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;
-}
index 7b2cc40..392a2a6 100644 (file)
@@ -197,14 +197,18 @@ pre, code, tt, kbd, samp, .mw-code {
 }
 
 code {
+       color: black;
        background-color: #f9f9f9;
+       border: 1px solid #ddd;
+       border-radius: 2px;
+       padding: 1px 4px;
 }
 
 pre, .mw-code {
-       padding: 1em;
-       border: 1px solid #ddd;
        color: black;
        background-color: #f9f9f9;
+       border: 1px solid #ddd;
+       padding: 1em;
 }
 
 /* Tables */
index 5a8335d..17ec8c6 100644 (file)
@@ -386,60 +386,6 @@ p.mw-upload-editlicenses {
        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 */
index 37cf68f..eee34de 100644 (file)
@@ -41,6 +41,7 @@ $wgAutoloadClasses += array(
        'MediaWikiPHPUnitCommand' => "$testDir/phpunit/MediaWikiPHPUnitCommand.php",
        'MediaWikiPHPUnitTestListener' => "$testDir/phpunit/MediaWikiPHPUnitTestListener.php",
        'MediaWikiLangTestCase' => "$testDir/phpunit/MediaWikiLangTestCase.php",
+       'MediaWikiPasswordTestCase' => "$testDir/phpunit/MediaWikiPasswordTestCase.php",
        'ResourceLoaderTestCase' => "$testDir/phpunit/ResourceLoaderTestCase.php",
        'ResourceLoaderTestModule' => "$testDir/phpunit/ResourceLoaderTestCase.php",
        'ResourceLoaderFileModuleTestModule' => "$testDir/phpunit/ResourceLoaderTestCase.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",
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 027c7b9..e76b9df 100644 (file)
@@ -208,7 +208,6 @@ class ParserTest {
                $messageMemc = wfGetMessageCacheStorage();
                $parserMemc = wfGetParserCacheStorage();
 
-               // $wgContLang = new StubContLang;
                $wgUser = new User;
                $context = new RequestContext;
                $wgLang = $context->getLanguage();
@@ -734,11 +733,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];
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 9eeb251..8c761b9 100644 (file)
@@ -77,8 +77,6 @@ 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 ) {
                wfDebugLog(
@@ -91,7 +89,6 @@ 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 ) {
                wfDebugLog( $this->logChannel, 'START suite ' . $suite->getName() );
@@ -101,7 +98,6 @@ 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 ) {
                wfDebugLog( $this->logChannel, 'END suite ' . $suite->getName() );
diff --git a/tests/phpunit/MediaWikiPasswordTestCase.php b/tests/phpunit/MediaWikiPasswordTestCase.php
new file mode 100644 (file)
index 0000000..edf944b
--- /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 MediaWikiPasswordTestCase 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 ) );
+       }
+}
index 3015895..02330a4 100644 (file)
@@ -507,10 +507,10 @@ 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
index 28c35b3..6537364 100644 (file)
@@ -265,6 +265,19 @@ class EditPageTest extends MediaWikiLangTestCase {
                        null,
                        "expected MediaWiki: page not being created if text equals default message"
                );
+
+               $this->assertEdit(
+                       'EditPageTest_testCreatePage',
+                       null,
+                       null,
+                       array(
+                               'wpTextbox1' => "",
+                               'wpIgnoreBlankArticle' => 1,
+                       ),
+                       EditPage::AS_SUCCESS_NEW_ARTICLE,
+                       "",
+                       "expected empty article being created"
+               )->doDeleteArticleReal( 'EditPageTest_testCreatePage' );
        }
 
        public function testUpdatePage() {
index fd06441..84799ff 100644 (file)
@@ -721,5 +721,5 @@ class GlobalTest extends MediaWikiTestCase {
                        ),
                );
        }
-       /* @TODO many more! */
+       /* @todo many more! */
 }
index 041adb8..166d641 100644 (file)
@@ -97,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 c561e70..d4d9551 100644 (file)
@@ -707,6 +707,63 @@ 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>',
+                       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 {
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..6a36b4b 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' );
index a164ff9..2937790 100644 (file)
@@ -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 f68b3b1..2cfdfcd 100644 (file)
@@ -195,6 +195,7 @@ mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"
                $method = $class->getMethod( 'makeResourceLoaderLink' );
                $method->setAccessible( true );
                $ctx = new RequestContext();
+               $ctx->setSkin( Skin::newFromKey( 'vector' ) );
                $ctx->setLanguage( 'en' );
                $out = new OutputPage( $ctx );
                $rl = $out->getResourceLoader();
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 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 {
index 9e2f5b8..b2e4459 100644 (file)
@@ -327,7 +327,7 @@ class StatusTest extends MediaWikiLangTestCase {
        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",
@@ -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"
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 6871582..53e8dc2 100644 (file)
@@ -20,6 +20,19 @@ class TitleTest extends MediaWikiTestCase {
                ) );
        }
 
+       public function addDBData() {
+               $this->db->replace( 'interwiki', 'iw_prefix',
+                       array(
+                               'iw_prefix' => 'externalwiki',
+                               'iw_url' => '//example.com/$1',
+                               'iw_api' => '//example.com/api.php',
+                               'iw_wikiid' => '',
+                               'iw_local' => 0,
+                               'iw_trans' => 0,
+                       )
+               );
+       }
+
        /**
         * @covers Title::legalChars
         */
@@ -46,7 +59,7 @@ 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().
+        * @note This mainly tests MediaWikiTitleCodec::parseTitle().
         */
        public function testSecureAndSplit() {
                $this->setMwGlobals( array(
@@ -606,4 +619,28 @@ 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 ),
+                       array( 'externalwiki:Interwiki link', true ),
+               );
+       }
 }
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 87ad2cd..0976b1a 100644 (file)
@@ -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 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 ) );
+       }
 }
index d8765ee..bd15f04 100644 (file)
@@ -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 ) {
diff --git a/tests/phpunit/includes/changes/OldChangesListTest.php b/tests/phpunit/includes/changes/OldChangesListTest.php
new file mode 100644 (file)
index 0000000..9783ae3
--- /dev/null
@@ -0,0 +1,157 @@
+<?php
+
+/**
+ * @covers OldChangesList
+ *
+ * @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' );
+
+               $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'
+               );
+       }
+
+       private function getNewBotEditChange() {
+               $user = $this->getTestUser();
+
+               $recentChange = $this->testRecentChangesHelper->makeNewBotEditRecentChange(
+                       $user, 'Abc', '20131103212153', 0, 0
+               );
+
+               return $recentChange;
+       }
+
+       private function getLogChange( $logType ) {
+               $user = $this->getTestUser();
+
+               $recentChange = $this->testRecentChangesHelper->makeLogRecentChange(
+                       $logType, $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..c3b8ce6 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,24 @@ 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',
                                        $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 +167,7 @@ class RCCacheEntryFactoryTest extends MediaWikiLangTestCase {
                        array(
                                array(
                                        'title' => 'Zzz',
-                                       'user' => 'Mary',
+                                       'user' => 'TestRecentChangesUser',
                                        'diff' => '',
                                        'cur' => '',
                                        'timestamp' => '21:21',
@@ -204,9 +176,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 +186,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 +294,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 +308,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..bb6ebec
--- /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, 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' => $logType,
+                               '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 2add9f2..b564a29 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" );
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 f9b4ad5..5bdb7e7 100644 (file)
@@ -17,7 +17,8 @@ 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() {
@@ -26,7 +27,8 @@ class RepoGroupTest extends MediaWikiTestCase {
                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() {
index c8b20d2..407f11a 100644 (file)
@@ -221,6 +221,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 d779207..c0871f1 100644 (file)
@@ -62,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 253c10b..1dcc4cd 100644 (file)
@@ -495,19 +495,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
diff --git a/tests/phpunit/includes/password/BcryptPasswordTest.php b/tests/phpunit/includes/password/BcryptPasswordTest.php
new file mode 100644 (file)
index 0000000..b4d5f99
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+
+/**
+ * @group large
+ */
+class BcryptPasswordTestCase extends MediaWikiPasswordTestCase {
+       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..c552253
--- /dev/null
@@ -0,0 +1,51 @@
+<?php
+
+class LayeredParameterizedPasswordTest extends MediaWikiPasswordTestCase {
+       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/Pbkdf2PasswordTest.php b/tests/phpunit/includes/password/Pbkdf2PasswordTest.php
new file mode 100644 (file)
index 0000000..c1b65d3
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @group large
+ */
+class Pbkdf2PasswordTest extends MediaWikiPasswordTestCase {
+       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 d9cd57e..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,8 +45,8 @@ 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();
index fa22d34..e98f0e8 100644 (file)
@@ -2,6 +2,14 @@
 
 class ResourceLoaderModuleTest extends ResourceLoaderTestCase {
 
+       protected function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       'wgValidSkinNames' => array( 'vector' => 'Vector' ),
+               ) );
+       }
+
        /**
         * @covers ResourceLoaderFileModule::getAllSkinStyleFiles
         */
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' );
index 2689236..c042064 100644 (file)
@@ -11,7 +11,7 @@
 class SpecialListFilesTest extends MediaWikiTestCase {
        /**
         * @expectedException MWException
-        * @expectedExceptionMesage invalid_field
+        * @expectedExceptionMessage invalid_field
         * @covers ImageListPager::formatValue
         */
        public function testFormatValuesThrowException() {
diff --git a/tests/phpunit/includes/specials/SpecialMyLanguageTest.php b/tests/phpunit/includes/specials/SpecialMyLanguageTest.php
new file mode 100644 (file)
index 0000000..c09d68c
--- /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 $expected
+        * @param $subpage
+        * @param $langCode
+        * @param $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 f1425ef..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.
index 4f0d24f..dad30b7 100644 (file)
@@ -32,7 +32,7 @@ abstract class DumpTestCase extends MediaWikiLangTestCase {
         * @param string $text Revisions text
         * @param string $text Revisions summare
         *
-        * @throws MWExcepion
+        * @throws MWException
         */
        protected function addRevision( Page $page, $text, $summary ) {
                $status = $page->doEditContent(
index 42d1d0b..a13f7bf 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() );
        }
 
        /**
index 8c40ffe..43f2096 100644 (file)
@@ -102,7 +102,7 @@ class FetchTextTest extends MediaWikiTestCase {
         * @param string $text The revisions text
         * @param string $text The revisions summare
         *
-        * @throws MWExcepion
+        * @throws MWException
         */
        private function addRevision( $page, $text, $summary ) {
                $status = $page->doEditContent(
index d7742a6..647386d 100644 (file)
@@ -37,7 +37,11 @@ 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' );
 
@@ -52,6 +56,51 @@ 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'] );
+
+               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'] );
+
+               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.
         */
@@ -115,7 +164,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 +255,7 @@ class ResourcesTest extends MediaWikiTestCase {
                                $cases[] = array(
                                        $method->invoke( $module, $file ),
                                        $moduleName,
-                                       $file,
+                                       ( $file instanceof ResourceLoaderFilePath ? $file->getPath() : $file ),
                                );
                        }
                }
index b27337b..bd82d21 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();
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 8c24f39..717c5f3 100644 (file)
@@ -352,7 +352,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;
@@ -426,7 +430,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();
 
@@ -497,8 +503,10 @@ class TestFileIterator implements Iterator {
                                        }
 
                                        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( '/\\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
@@ -520,8 +528,8 @@ class TestFileIterator implements Iterator {
 
                                        $this->test = array(
                                                'test' => ParserTest::chomp( $this->sectionData['test'] ),
-                                               'input' => ParserTest::chomp( $this->sectionData[ $input ] ),
-                                               'result' => ParserTest::chomp( $this->sectionData[ $result ] ),
+                                               'input' => ParserTest::chomp( $this->sectionData[$input] ),
+                                               'result' => ParserTest::chomp( $this->sectionData[$result] ),
                                                'options' => ParserTest::chomp( $this->sectionData['options'] ),
                                                'config' => ParserTest::chomp( $this->sectionData['config'] ),
                                        );
@@ -530,7 +538,8 @@ class TestFileIterator implements Iterator {
                                }
 
                                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] = '';
@@ -579,7 +588,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 +614,7 @@ class TestFileIterator implements Iterator {
                }
 
                $tokens = array_values( $tokens );
-               return $tokens[ 0 ];
+               return $tokens[0];
        }
 }
 
@@ -640,7 +649,8 @@ class DelayedParserTest {
         */
        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
index 9a4b332..d53c10c 100644 (file)
--- a/thumb.php
+++ b/thumb.php
@@ -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 {
@@ -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/";
        }