Merge "Add autocomplete for WhatLinksHere subpages"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Sat, 10 Jan 2015 20:04:53 +0000 (20:04 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Sat, 10 Jan 2015 20:04:53 +0000 (20:04 +0000)
553 files changed:
.gitignore
RELEASE-NOTES-1.25
StartProfiler.sample
api.php
autoload.php
composer.json
docs/extension.schema.json [new file with mode: 0644]
docs/hooks.txt
img_auth.php
includes/AjaxDispatcher.php
includes/Block.php
includes/Category.php
includes/CategoryFinder.php
includes/CategoryViewer.php
includes/DefaultSettings.php
includes/DeferredStringifier.php [new file with mode: 0644]
includes/EditPage.php
includes/Export.php
includes/FeedUtils.php
includes/FileDeleteForm.php
includes/GlobalFunctions.php
includes/Html.php
includes/HtmlFormatter.php
includes/HttpFunctions.php
includes/Import.php
includes/Linker.php
includes/MagicWord.php
includes/MediaWiki.php
includes/MessageBlobStore.php
includes/OutputPage.php
includes/Preferences.php
includes/PrefixSearch.php
includes/Revision.php
includes/Sanitizer.php
includes/Setup.php
includes/SiteStats.php
includes/StreamFile.php
includes/StubObject.php
includes/Title.php
includes/User.php
includes/WatchedItem.php
includes/WebStart.php
includes/Xml.php
includes/actions/CreditsAction.php
includes/actions/HistoryAction.php
includes/actions/InfoAction.php
includes/actions/UnwatchAction.php
includes/actions/WatchAction.php
includes/api/ApiBase.php
includes/api/ApiImport.php
includes/api/ApiMain.php
includes/api/ApiPageSet.php
includes/api/ApiParse.php
includes/api/ApiQueryInfo.php
includes/api/ApiQueryRecentChanges.php
includes/api/ApiQuerySearch.php
includes/api/ApiQueryTokens.php
includes/api/ApiQueryWatchlist.php
includes/api/ApiStashEdit.php
includes/api/ApiTokens.php
includes/api/ApiUpload.php
includes/api/i18n/be-tarask.json
includes/api/i18n/ca.json
includes/api/i18n/en.json
includes/api/i18n/fa.json
includes/api/i18n/fi.json
includes/api/i18n/pl.json
includes/api/i18n/roa-tara.json [new file with mode: 0644]
includes/api/i18n/sv.json
includes/api/i18n/zh-hans.json
includes/cache/BacklinkCache.php
includes/cache/LinkBatch.php
includes/cache/LinkCache.php
includes/cache/LocalisationCache.php
includes/cache/MessageCache.php
includes/cache/UserCache.php
includes/cache/bloom/BloomCache.php
includes/changes/ChangesFeed.php
includes/changes/EnhancedChangesList.php
includes/changes/OldChangesList.php
includes/content/JsonContent.php
includes/content/WikitextContent.php
includes/context/RequestContext.php
includes/db/Database.php
includes/db/DatabaseError.php
includes/db/DatabaseMysqlBase.php
includes/db/LoadBalancer.php
includes/db/LoadMonitor.php
includes/deferred/DeferredUpdates.php
includes/deferred/HTMLCacheUpdate.php
includes/deferred/LinksUpdate.php
includes/deferred/SearchUpdate.php
includes/deferred/SquidUpdate.php
includes/diff/DairikiDiff.php
includes/diff/DiffFormatter.php
includes/diff/DifferenceEngine.php
includes/diff/TableDiffFormatter.php
includes/exception/MWExceptionHandler.php
includes/externalstore/ExternalStore.php
includes/filebackend/FSFile.php
includes/filebackend/FileBackendStore.php
includes/filebackend/FileOpBatch.php
includes/filebackend/SwiftFileBackend.php
includes/filebackend/TempFSFile.php
includes/filebackend/lockmanager/DBLockManager.php
includes/filebackend/lockmanager/LockManager.php
includes/filerepo/file/File.php
includes/filerepo/file/LocalFile.php
includes/filerepo/file/OldLocalFile.php
includes/htmlform/HTMLFormField.php
includes/installer/DatabaseInstaller.php
includes/installer/Installer.php
includes/installer/MssqlUpdater.php
includes/installer/MysqlUpdater.php
includes/installer/OracleUpdater.php
includes/installer/PostgresUpdater.php
includes/installer/SqliteUpdater.php
includes/installer/i18n/az.json
includes/installer/i18n/bg.json
includes/installer/i18n/cy.json
includes/installer/i18n/nap.json
includes/installer/i18n/roa-tara.json
includes/installer/i18n/tr.json
includes/jobqueue/JobQueue.php
includes/jobqueue/JobQueueGroup.php
includes/jobqueue/JobRunner.php
includes/jobqueue/aggregator/JobQueueAggregator.php
includes/jobqueue/jobs/AssembleUploadChunksJob.php
includes/jobqueue/jobs/PublishStashedFileJob.php
includes/libs/Cookie.php
includes/libs/MapCacheLRU.php
includes/libs/MultiHttpClient.php
includes/libs/Xhprof.php
includes/libs/composer/ComposerJson.php
includes/libs/virtualrest/ParsoidVirtualRESTService.php [new file with mode: 0644]
includes/libs/virtualrest/VirtualRESTServiceClient.php
includes/logging/LogPager.php
includes/mail/EmailNotification.php
includes/media/BMP.php
includes/media/Bitmap.php
includes/media/BitmapMetadataHandler.php
includes/media/DjVu.php
includes/media/DjVuImage.php
includes/media/FormatMetadata.php
includes/media/Jpeg.php
includes/media/SVG.php
includes/media/Tiff.php
includes/media/XCF.php
includes/media/XMP.php
includes/objectcache/MemcachedClient.php
includes/objectcache/MemcachedPeclBagOStuff.php
includes/objectcache/ObjectCache.php
includes/objectcache/RedisBagOStuff.php
includes/page/Article.php
includes/page/WikiPage.php
includes/pager/IndexPager.php
includes/parser/CoreParserFunctions.php
includes/parser/LinkHolderArray.php
includes/parser/MWTidy.php
includes/parser/Parser.php
includes/parser/ParserCache.php
includes/parser/ParserOptions.php
includes/parser/ParserOutput.php
includes/parser/Preprocessor_DOM.php
includes/parser/Preprocessor_Hash.php
includes/parser/StripState.php
includes/poolcounter/PoolCounterRedis.php
includes/profiler/ProfileSection.php
includes/profiler/Profiler.php
includes/profiler/ProfilerFunctions.php
includes/profiler/ProfilerSectionOnly.php [new file with mode: 0755]
includes/profiler/ProfilerSimpleTrace.php [deleted file]
includes/profiler/ProfilerStandard.php [deleted file]
includes/profiler/ProfilerStub.php
includes/profiler/ProfilerXhprof.php
includes/registration/ExtensionProcessor.php [new file with mode: 0644]
includes/registration/ExtensionRegistry.php [new file with mode: 0644]
includes/registration/Processor.php [new file with mode: 0644]
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderFileModule.php
includes/resourceloader/ResourceLoaderImageModule.php
includes/resourceloader/ResourceLoaderModule.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/search/SearchEngine.php
includes/search/SearchHighlighter.php
includes/search/SearchMySQL.php
includes/site/SiteSQLStore.php
includes/skins/BaseTemplate.php
includes/skins/MediaWikiI18N.php
includes/skins/Skin.php
includes/skins/SkinTemplate.php
includes/specialpage/SpecialPageFactory.php
includes/specials/SpecialActiveusers.php
includes/specials/SpecialAllMessages.php
includes/specials/SpecialBlockList.php
includes/specials/SpecialContributions.php
includes/specials/SpecialDeletedContributions.php
includes/specials/SpecialImport.php
includes/specials/SpecialJavaScriptTest.php
includes/specials/SpecialListusers.php
includes/specials/SpecialMergeHistory.php
includes/specials/SpecialNewimages.php
includes/specials/SpecialProtectedtitles.php
includes/specials/SpecialRandomInCategory.php
includes/specials/SpecialSearch.php
includes/specials/SpecialUpload.php
includes/specials/SpecialVersion.php
includes/specials/SpecialWhatlinkshere.php
includes/title/ForeignTitle.php [new file with mode: 0644]
includes/title/ForeignTitleFactory.php [new file with mode: 0644]
includes/title/ImportTitleFactory.php [new file with mode: 0644]
includes/title/NaiveForeignTitleFactory.php [new file with mode: 0644]
includes/title/NaiveImportTitleFactory.php [new file with mode: 0644]
includes/title/NamespaceAwareForeignTitleFactory.php [new file with mode: 0644]
includes/title/NamespaceImportTitleFactory.php [new file with mode: 0644]
includes/title/SubpageImportTitleFactory.php [new file with mode: 0644]
includes/upload/UploadBase.php
includes/utils/IP.php
includes/utils/MWCryptRand.php
includes/utils/StringUtils.php
includes/utils/UIDGenerator.php
languages/Language.php
languages/LanguageConverter.php
languages/classes/LanguageBe_tarask.php
languages/classes/LanguageKk.php
languages/classes/LanguageYue.php
languages/classes/LanguageZh.php
languages/classes/LanguageZh_hans.php
languages/i18n/af.json
languages/i18n/ar.json
languages/i18n/as.json
languages/i18n/awa.json
languages/i18n/az.json
languages/i18n/be-tarask.json
languages/i18n/bg.json
languages/i18n/bn.json
languages/i18n/ca.json
languages/i18n/cdo.json
languages/i18n/ce.json
languages/i18n/cs.json
languages/i18n/cy.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/egl.json
languages/i18n/el.json
languages/i18n/en.json
languages/i18n/es.json
languages/i18n/et.json
languages/i18n/eu.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/gl.json
languages/i18n/gu.json
languages/i18n/he.json
languages/i18n/hi.json
languages/i18n/hr.json
languages/i18n/hu.json
languages/i18n/ia.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/ka.json
languages/i18n/kk-cyrl.json
languages/i18n/ko.json
languages/i18n/lb.json
languages/i18n/lrc.json
languages/i18n/lt.json
languages/i18n/lv.json
languages/i18n/mk.json
languages/i18n/ms.json
languages/i18n/nap.json
languages/i18n/nb.json
languages/i18n/nds-nl.json
languages/i18n/nl.json
languages/i18n/nn.json
languages/i18n/pl.json
languages/i18n/pms.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ro.json
languages/i18n/roa-tara.json
languages/i18n/ru.json
languages/i18n/sa.json
languages/i18n/scn.json
languages/i18n/sh.json
languages/i18n/si.json
languages/i18n/sl.json
languages/i18n/sr-ec.json
languages/i18n/sr-el.json
languages/i18n/sv.json
languages/i18n/tr.json
languages/i18n/uz.json
languages/i18n/yi.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
load.php
maintenance/Maintenance.php
maintenance/archives/patch-drop-page_counter.sql [new file with mode: 0644]
maintenance/archives/patch-drop-ss_total_views.sql [new file with mode: 0644]
maintenance/convertExtensionToRegistration.php [new file with mode: 0644]
maintenance/dictionary/mediawiki.dic
maintenance/doMaintenance.php
maintenance/eval.php
maintenance/language/checkLanguage.php
maintenance/mssql/tables.sql
maintenance/oracle/tables.sql
maintenance/populateRevisionSha1.php
maintenance/postgres/compare_schemas.pl
maintenance/postgres/tables.sql
maintenance/preprocessorFuzzTest.php
maintenance/resources/update-oojs-ui.sh
maintenance/sqlite/archives/initial-indexes.sql
maintenance/sqlite/archives/patch-drop-page_counter.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-drop-ss_admins.sql
maintenance/sqlite/archives/patch-drop-ss_total_views.sql [new file with mode: 0644]
maintenance/tables.sql
maintenance/validateRegistrationFile.php [new file with mode: 0644]
resources/lib/jquery.ui/themes/smoothness/PATCHES [new file with mode: 0644]
resources/lib/jquery.ui/themes/smoothness/jquery.ui.theme.css
resources/lib/jquery/jquery.qunit.css
resources/lib/jquery/jquery.qunit.js
resources/lib/moment/locale/af.js
resources/lib/moment/locale/ar-ma.js
resources/lib/moment/locale/ar-sa.js
resources/lib/moment/locale/ar.js
resources/lib/moment/locale/az.js
resources/lib/moment/locale/be.js
resources/lib/moment/locale/bg.js
resources/lib/moment/locale/bn.js
resources/lib/moment/locale/bo.js
resources/lib/moment/locale/br.js
resources/lib/moment/locale/bs.js
resources/lib/moment/locale/ca.js
resources/lib/moment/locale/cs.js
resources/lib/moment/locale/cv.js
resources/lib/moment/locale/cy.js
resources/lib/moment/locale/da.js
resources/lib/moment/locale/de-at.js
resources/lib/moment/locale/de.js
resources/lib/moment/locale/el.js
resources/lib/moment/locale/en-au.js
resources/lib/moment/locale/en-ca.js
resources/lib/moment/locale/en-gb.js
resources/lib/moment/locale/eo.js
resources/lib/moment/locale/es.js
resources/lib/moment/locale/et.js
resources/lib/moment/locale/eu.js
resources/lib/moment/locale/fa.js
resources/lib/moment/locale/fi.js
resources/lib/moment/locale/fo.js
resources/lib/moment/locale/fr-ca.js
resources/lib/moment/locale/fr.js
resources/lib/moment/locale/gl.js
resources/lib/moment/locale/he.js
resources/lib/moment/locale/hi.js
resources/lib/moment/locale/hr.js
resources/lib/moment/locale/hu.js
resources/lib/moment/locale/hy-am.js
resources/lib/moment/locale/id.js
resources/lib/moment/locale/is.js
resources/lib/moment/locale/it.js
resources/lib/moment/locale/ja.js
resources/lib/moment/locale/ka.js
resources/lib/moment/locale/km.js
resources/lib/moment/locale/ko.js
resources/lib/moment/locale/lb.js
resources/lib/moment/locale/lt.js
resources/lib/moment/locale/lv.js
resources/lib/moment/locale/mk.js
resources/lib/moment/locale/ml.js
resources/lib/moment/locale/mr.js
resources/lib/moment/locale/ms-my.js
resources/lib/moment/locale/my.js
resources/lib/moment/locale/nb.js
resources/lib/moment/locale/ne.js
resources/lib/moment/locale/nl.js
resources/lib/moment/locale/nn.js
resources/lib/moment/locale/pl.js
resources/lib/moment/locale/pt-br.js
resources/lib/moment/locale/pt.js
resources/lib/moment/locale/ro.js
resources/lib/moment/locale/ru.js
resources/lib/moment/locale/sk.js
resources/lib/moment/locale/sl.js
resources/lib/moment/locale/sq.js
resources/lib/moment/locale/sr-cyrl.js
resources/lib/moment/locale/sr.js
resources/lib/moment/locale/sv.js
resources/lib/moment/locale/ta.js
resources/lib/moment/locale/th.js
resources/lib/moment/locale/tl-ph.js
resources/lib/moment/locale/tr.js
resources/lib/moment/locale/tzm-latn.js
resources/lib/moment/locale/tzm.js
resources/lib/moment/locale/uk.js
resources/lib/moment/locale/uz.js
resources/lib/moment/locale/vi.js
resources/lib/moment/locale/zh-cn.js
resources/lib/moment/locale/zh-tw.js
resources/lib/moment/moment.js
resources/lib/oojs-ui/i18n/bs.json
resources/lib/oojs-ui/i18n/lv.json
resources/lib/oojs-ui/i18n/sr-el.json
resources/lib/oojs-ui/oojs-ui-mediawiki.css
resources/lib/oojs-ui/oojs-ui-mediawiki.js
resources/lib/oojs-ui/oojs-ui-mediawiki.svg.css
resources/lib/oojs-ui/oojs-ui.js
resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-invert.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-invert.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/lock.png [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/icons/lock.svg [new file with mode: 0644]
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down.png
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down.svg
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr.png
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr.svg
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl.png
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl.svg
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up-invert.png
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up-invert.svg
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up.png
resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up.svg
resources/src/mediawiki.page/mediawiki.page.gallery.js
resources/src/mediawiki.ui/components/checkbox.less
resources/src/mediawiki.ui/components/icons.less
resources/src/mediawiki/mediawiki.js
tests/frontend/Gruntfile.js
tests/frontend/package.json
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/includes/ImportTest.php
tests/phpunit/includes/LanguageConverterTest.php [deleted file]
tests/phpunit/includes/LinkerTest.php
tests/phpunit/includes/api/ApiMainTest.php
tests/phpunit/includes/api/query/ApiQueryTest.php
tests/phpunit/includes/libs/JavaScriptMinifierTest.php
tests/phpunit/includes/media/MediaHandlerTest.php
tests/phpunit/includes/normal/CleanUpTest.php
tests/phpunit/includes/parser/ParserOutputTest.php
tests/phpunit/includes/registration/ExtensionProcessorTest.php [new file with mode: 0644]
tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php [new file with mode: 0644]
tests/phpunit/includes/resourceloader/ResourceLoaderStartupModuleTest.php [deleted file]
tests/phpunit/includes/site/SiteListFileCacheBuilderTest.php
tests/phpunit/includes/site/SiteListFileCacheTest.php
tests/phpunit/includes/title/ForeignTitleTest.php [new file with mode: 0644]
tests/phpunit/includes/title/NaiveForeignTitleFactoryTest.php [new file with mode: 0644]
tests/phpunit/includes/title/NaiveImportTitleFactoryTest.php [new file with mode: 0644]
tests/phpunit/includes/title/NamespaceAwareForeignTitleFactoryTest.php [new file with mode: 0644]
tests/phpunit/includes/title/NamespaceImportTitleFactoryTest.php [new file with mode: 0644]
tests/phpunit/includes/title/SubpageImportTitleFactoryTest.php [new file with mode: 0644]
tests/phpunit/languages/LanguageAmTest.php [deleted file]
tests/phpunit/languages/LanguageArTest.php [deleted file]
tests/phpunit/languages/LanguageArqTest.php [deleted file]
tests/phpunit/languages/LanguageBeTest.php [deleted file]
tests/phpunit/languages/LanguageBe_taraskTest.php [deleted file]
tests/phpunit/languages/LanguageBhoTest.php [deleted file]
tests/phpunit/languages/LanguageBsTest.php [deleted file]
tests/phpunit/languages/LanguageConverterTest.php [new file with mode: 0644]
tests/phpunit/languages/LanguageCsTest.php [deleted file]
tests/phpunit/languages/LanguageCuTest.php [deleted file]
tests/phpunit/languages/LanguageCyTest.php [deleted file]
tests/phpunit/languages/LanguageDsbTest.php [deleted file]
tests/phpunit/languages/LanguageFrTest.php [deleted file]
tests/phpunit/languages/LanguageGaTest.php [deleted file]
tests/phpunit/languages/LanguageGdTest.php [deleted file]
tests/phpunit/languages/LanguageGvTest.php [deleted file]
tests/phpunit/languages/LanguageHeTest.php [deleted file]
tests/phpunit/languages/LanguageHiTest.php [deleted file]
tests/phpunit/languages/LanguageHrTest.php [deleted file]
tests/phpunit/languages/LanguageHsbTest.php [deleted file]
tests/phpunit/languages/LanguageHuTest.php [deleted file]
tests/phpunit/languages/LanguageHyTest.php [deleted file]
tests/phpunit/languages/LanguageKshTest.php [deleted file]
tests/phpunit/languages/LanguageLnTest.php [deleted file]
tests/phpunit/languages/LanguageLtTest.php [deleted file]
tests/phpunit/languages/LanguageLvTest.php [deleted file]
tests/phpunit/languages/LanguageMgTest.php [deleted file]
tests/phpunit/languages/LanguageMkTest.php [deleted file]
tests/phpunit/languages/LanguageMlTest.php [deleted file]
tests/phpunit/languages/LanguageMoTest.php [deleted file]
tests/phpunit/languages/LanguageMtTest.php [deleted file]
tests/phpunit/languages/LanguageNlTest.php [deleted file]
tests/phpunit/languages/LanguageNsoTest.php [deleted file]
tests/phpunit/languages/LanguagePlTest.php [deleted file]
tests/phpunit/languages/LanguageRoTest.php [deleted file]
tests/phpunit/languages/LanguageRuTest.php [deleted file]
tests/phpunit/languages/LanguageSeTest.php [deleted file]
tests/phpunit/languages/LanguageSgsTest.php [deleted file]
tests/phpunit/languages/LanguageShTest.php [deleted file]
tests/phpunit/languages/LanguageSkTest.php [deleted file]
tests/phpunit/languages/LanguageSlTest.php [deleted file]
tests/phpunit/languages/LanguageSmaTest.php [deleted file]
tests/phpunit/languages/LanguageSrTest.php [deleted file]
tests/phpunit/languages/LanguageTiTest.php [deleted file]
tests/phpunit/languages/LanguageTlTest.php [deleted file]
tests/phpunit/languages/LanguageTrTest.php [deleted file]
tests/phpunit/languages/LanguageUkTest.php [deleted file]
tests/phpunit/languages/LanguageUzTest.php [deleted file]
tests/phpunit/languages/LanguageWaTest.php [deleted file]
tests/phpunit/languages/classes/LanguageAmTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageArTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageArqTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageBeTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageBe_taraskTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageBhoTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageBsTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageCsTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageCuTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageCyTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageDsbTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageFrTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageGaTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageGdTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageGvTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageHeTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageHiTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageHrTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageHsbTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageHuTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageHyTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageKshTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageLnTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageLtTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageLvTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageMgTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageMkTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageMlTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageMoTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageMtTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageNlTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageNsoTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguagePlTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageRoTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageRuTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageSeTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageSgsTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageShTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageSkTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageSlTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageSmaTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageSrTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageTiTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageTlTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageTrTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageUkTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageUzTest.php [new file with mode: 0644]
tests/phpunit/languages/classes/LanguageWaTest.php [new file with mode: 0644]
tests/qunit/data/testrunner.js
thumb.php

index 93c429f..550f017 100644 (file)
@@ -47,6 +47,7 @@ node_modules/
 /vendor
 /composer.lock
 /composer.json
+/composer.local.json
 
 # MediaWiki UI documentation
 /docs/kss/static
index ef0917e..2aa066c 100644 (file)
@@ -33,6 +33,9 @@ production.
 * (T46740) The temporary option $wgIncludejQueryMigrate was removed, along
   with the jQuery Migrate library, as indicated when this option was provided in
   MediaWiki 1.24.
+* ProfilerStandard and ProfilerSimpleTrace were removed. Make sure that any
+  StartProfiler.php config is updated to reflect this. Xhprof is available
+  for zend/hhvm. Also, for hhvm, one can consider using its xenon profiler.
 
 === New features in 1.25 ===
 * (T64861) Updated plural rules to CLDR 26. Includes incompatible changes
@@ -48,7 +51,7 @@ production.
 * (T69341) SVG images will no longer be base64-encoded when being embedded
   in CSS. This results in slight size increase before gzip compression (due to
   percent-encoding), but up to 20% decrease after it.
-* Upgrade jStorage to v0.4.12.
+* Update jStorage to v0.4.12.
 * MediaWiki now natively supports page status indicators: icons (or short text
   snippets) usually displayed in the top-right corner of the page. They have
   been in use on Wikipedia for a long time, implemented using templates and CSS
@@ -75,6 +78,8 @@ production.
   on Special:Version in their own section. Extensions or skins that are
   installed via composer will not be shown in this section as it is assumed
   they will add the proper credits to the skins or extensions section.
+* Update QUnit from v1.14.0 to v1.16.0.
+* Update Moment.js from v2.8.3 to v2.8.4.
 
 ==== External libraries ====
 * MediaWiki now requires certain external libraries to be installed. In the past
@@ -170,6 +175,12 @@ production.
 * (T78737) action=expandtemplates can now return page properties.
 * (T78690) list=allimages now accepts multiple pipe-separated values
   for the 'aimime' parameter.
+* prop=info with inprop=protections will now return applicable protection types
+  with the 'restrictiontypes' key.
+* (T85417) When resolving redirects, ApiPageSet will now add the targets of
+  interwiki redirects to the list of interwiki titles.
+* (T85417) When outputting the list of redirect titles, a 'tointerwiki'
+  property (like the existing 'tofragment' property) will be set.
 
 === Action API internal changes in 1.25 ===
 * ApiHelp has been rewritten to support i18n and paginated HTML output.
index d20c0e1..4721a9d 100644 (file)
@@ -1,10 +1,7 @@
 <?php
 
 /**
- * To use a profiler, copy this file to StartProfiler.php,
- * and add either:
- *  $wgProfiler['class'] = 'ProfilerStandard';
- *    or
+ * To use a profiler, copy this file to StartProfiler.php and add:
  *  $wgProfiler['class'] = 'ProfilerXhprof';
  *
  * For output, add:
@@ -22,7 +19,7 @@
  * maintenance/archives/patch-profiling.sql to your database.
  *
  * For a rudimentary sampling profiler:
- *   $wgProfiler['class'] = 'ProfilerStandard';
+ *   $wgProfiler['class'] = 'ProfilerXhprof';
  *   $wgProfiler['output'] = array( 'db' );
  *   $wgProfiler['sampling'] = 50; // one every 50 requests
  * This will use ProfilerStub for non-sampled cases.
diff --git a/api.php b/api.php
index 92e6704..d63f254 100644 (file)
--- a/api.php
+++ b/api.php
@@ -42,7 +42,6 @@ if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3
 
 require __DIR__ . '/includes/WebStart.php';
 
-wfProfileIn( 'api.php' );
 $starttime = microtime( true );
 
 // URL safety checks
@@ -94,7 +93,6 @@ DeferredUpdates::doUpdates();
 
 // Log what the user did, for book-keeping purposes.
 $endtime = microtime( true );
-wfProfileOut( 'api.php' );
 
 wfLogProfilingData();
 
index b36153a..674d4b0 100644 (file)
@@ -244,6 +244,7 @@ $wgAutoloadLocalClasses = array(
        'ContentHandler' => __DIR__ . '/includes/content/ContentHandler.php',
        'ContextSource' => __DIR__ . '/includes/context/ContextSource.php',
        'ContribsPager' => __DIR__ . '/includes/specials/SpecialContributions.php',
+       'ConvertExtensionToRegistration' => __DIR__ . '/maintenance/convertExtensionToRegistration.php',
        'ConvertLinks' => __DIR__ . '/maintenance/convertLinks.php',
        'ConvertUserOptions' => __DIR__ . '/maintenance/convertUserOptions.php',
        'ConverterRule' => __DIR__ . '/languages/ConverterRule.php',
@@ -291,6 +292,7 @@ $wgAutoloadLocalClasses = array(
        'DateFormatter' => __DIR__ . '/includes/parser/DateFormatter.php',
        'DeadendPagesPage' => __DIR__ . '/includes/specials/SpecialDeadendpages.php',
        'DeferrableUpdate' => __DIR__ . '/includes/deferred/DeferredUpdates.php',
+       'DeferredStringifier' => __DIR__ . '/includes/DeferredStringifier.php',
        'DeferredUpdates' => __DIR__ . '/includes/deferred/DeferredUpdates.php',
        'DeleteAction' => __DIR__ . '/includes/actions/DeleteAction.php',
        'DeleteArchivedFiles' => __DIR__ . '/maintenance/deleteArchivedFiles.php',
@@ -373,6 +375,8 @@ $wgAutoloadLocalClasses = array(
        'ExplodeIterator' => __DIR__ . '/includes/utils/StringUtils.php',
        'ExportProgressFilter' => __DIR__ . '/maintenance/backup.inc',
        'ExtensionLanguages' => __DIR__ . '/maintenance/language/languages.inc',
+       'ExtensionProcessor' => __DIR__ . '/includes/registration/ExtensionProcessor.php',
+       'ExtensionRegistry' => __DIR__ . '/includes/registration/ExtensionRegistry.php',
        'ExternalStore' => __DIR__ . '/includes/externalstore/ExternalStore.php',
        'ExternalStoreDB' => __DIR__ . '/includes/externalstore/ExternalStoreDB.php',
        'ExternalStoreHttp' => __DIR__ . '/includes/externalstore/ExternalStoreHttp.php',
@@ -431,6 +435,8 @@ $wgAutoloadLocalClasses = array(
        'ForeignDBFile' => __DIR__ . '/includes/filerepo/file/ForeignDBFile.php',
        'ForeignDBRepo' => __DIR__ . '/includes/filerepo/ForeignDBRepo.php',
        'ForeignDBViaLBRepo' => __DIR__ . '/includes/filerepo/ForeignDBViaLBRepo.php',
+       'ForeignTitle' => __DIR__ . '/includes/title/ForeignTitle.php',
+       'ForeignTitleFactory' => __DIR__ . '/includes/title/ForeignTitleFactory.php',
        'ForkController' => __DIR__ . '/includes/ForkController.php',
        'FormAction' => __DIR__ . '/includes/actions/FormAction.php',
        'FormOptions' => __DIR__ . '/includes/FormOptions.php',
@@ -530,6 +536,7 @@ $wgAutoloadLocalClasses = array(
        'ImportSiteScripts' => __DIR__ . '/maintenance/importSiteScripts.php',
        'ImportStreamSource' => __DIR__ . '/includes/Import.php',
        'ImportStringSource' => __DIR__ . '/includes/Import.php',
+       'ImportTitleFactory' => __DIR__ . '/includes/title/ImportTitleFactory.php',
        'IncludableSpecialPage' => __DIR__ . '/includes/specialpage/IncludableSpecialPage.php',
        'IndexPager' => __DIR__ . '/includes/pager/IndexPager.php',
        'InfoAction' => __DIR__ . '/includes/actions/InfoAction.php',
@@ -768,7 +775,11 @@ $wgAutoloadLocalClasses = array(
        'MySqlLockManager' => __DIR__ . '/includes/filebackend/lockmanager/DBLockManager.php',
        'MysqlInstaller' => __DIR__ . '/includes/installer/MysqlInstaller.php',
        'MysqlUpdater' => __DIR__ . '/includes/installer/MysqlUpdater.php',
+       'NaiveForeignTitleFactory' => __DIR__ . '/includes/title/NaiveForeignTitleFactory.php',
+       'NaiveImportTitleFactory' => __DIR__ . '/includes/title/NaiveImportTitleFactory.php',
+       'NamespaceAwareForeignTitleFactory' => __DIR__ . '/includes/title/NamespaceAwareForeignTitleFactory.php',
        'NamespaceConflictChecker' => __DIR__ . '/maintenance/namespaceDupes.php',
+       'NamespaceImportTitleFactory' => __DIR__ . '/includes/title/NamespaceImportTitleFactory.php',
        'NewFilesPager' => __DIR__ . '/includes/specials/SpecialNewimages.php',
        'NewPagesPager' => __DIR__ . '/includes/specials/SpecialNewpages.php',
        'NewUsersLogFormatter' => __DIR__ . '/includes/logging/NewUsersLogFormatter.php',
@@ -838,6 +849,7 @@ $wgAutoloadLocalClasses = array(
        'ParserDiffTest' => __DIR__ . '/includes/parser/ParserDiffTest.php',
        'ParserOptions' => __DIR__ . '/includes/parser/ParserOptions.php',
        'ParserOutput' => __DIR__ . '/includes/parser/ParserOutput.php',
+       'ParsoidVirtualRESTService' => __DIR__ . '/includes/libs/virtualrest/ParsoidVirtualRESTService.php',
        'Password' => __DIR__ . '/includes/password/Password.php',
        'PasswordError' => __DIR__ . '/includes/password/PasswordError.php',
        'PasswordFactory' => __DIR__ . '/includes/password/PasswordFactory.php',
@@ -880,14 +892,14 @@ $wgAutoloadLocalClasses = array(
        'Preprocessor_DOM' => __DIR__ . '/includes/parser/Preprocessor_DOM.php',
        'Preprocessor_Hash' => __DIR__ . '/includes/parser/Preprocessor_Hash.php',
        'ProcessCacheLRU' => __DIR__ . '/includes/libs/ProcessCacheLRU.php',
+       'Processor' => __DIR__ . '/includes/registration/Processor.php',
        'ProfileSection' => __DIR__ . '/includes/profiler/ProfileSection.php',
        'Profiler' => __DIR__ . '/includes/profiler/Profiler.php',
        'ProfilerOutput' => __DIR__ . '/includes/profiler/output/ProfilerOutput.php',
        'ProfilerOutputDb' => __DIR__ . '/includes/profiler/output/ProfilerOutputDb.php',
        'ProfilerOutputText' => __DIR__ . '/includes/profiler/output/ProfilerOutputText.php',
        'ProfilerOutputUdp' => __DIR__ . '/includes/profiler/output/ProfilerOutputUdp.php',
-       'ProfilerSimpleTrace' => __DIR__ . '/includes/profiler/ProfilerSimpleTrace.php',
-       'ProfilerStandard' => __DIR__ . '/includes/profiler/ProfilerStandard.php',
+       'ProfilerSectionOnly' => __DIR__ . '/includes/profiler/ProfilerSectionOnly.php',
        'ProfilerStub' => __DIR__ . '/includes/profiler/ProfilerStub.php',
        'ProfilerXhprof' => __DIR__ . '/includes/profiler/ProfilerXhprof.php',
        'Protect' => __DIR__ . '/maintenance/protect.php',
@@ -1147,6 +1159,7 @@ $wgAutoloadLocalClasses = array(
        'StubObject' => __DIR__ . '/includes/StubObject.php',
        'StubUserLang' => __DIR__ . '/includes/StubObject.php',
        'SubmitAction' => __DIR__ . '/includes/actions/SubmitAction.php',
+       'SubpageImportTitleFactory' => __DIR__ . '/includes/title/SubpageImportTitleFactory.php',
        'SvgHandler' => __DIR__ . '/includes/media/SVG.php',
        'SwiftFileBackend' => __DIR__ . '/includes/filebackend/SwiftFileBackend.php',
        'SwiftFileBackendDirList' => __DIR__ . '/includes/filebackend/SwiftFileBackend.php',
@@ -1256,6 +1269,7 @@ $wgAutoloadLocalClasses = array(
        'UsersPager' => __DIR__ . '/includes/specials/SpecialListusers.php',
        'UtfNormal' => __DIR__ . '/includes/normal/UtfNormal.php',
        'UzConverter' => __DIR__ . '/languages/classes/LanguageUz.php',
+       'ValidateRegistrationFile' => __DIR__ . '/maintenance/validateRegistrationFile.php',
        'ViewAction' => __DIR__ . '/includes/actions/ViewAction.php',
        'VirtualRESTService' => __DIR__ . '/includes/libs/virtualrest/VirtualRESTService.php',
        'VirtualRESTServiceClient' => __DIR__ . '/includes/libs/virtualrest/VirtualRESTServiceClient.php',
index 5901721..519274d 100644 (file)
                "wiki": "https://www.mediawiki.org/"
        },
        "require": {
+               "cssjanus/cssjanus": "1.1.1",
                "leafo/lessphp": "0.5.0",
+               "oojs/oojs-ui": "0.6.2",
                "php": ">=5.3.3",
                "psr/log": "1.0.0",
-               "cssjanus/cssjanus": "1.1.1",
                "wikimedia/cdb": "1.0.1",
-               "oojs/oojs-ui": "0.6.1"
+               "wikimedia/composer-merge-plugin": "0.5.0"
        },
        "require-dev": {
+               "justinrainbow/json-schema": "~1.3",
                "phpunit/phpunit": "*"
        },
        "suggest": {
        "config": {
                "prepend-autoloader": false,
                "optimize-autoloader": true
+       },
+       "extra": {
+               "merge-plugin": {
+                       "include": [
+                               "composer.local.json"
+                       ]
+               }
        }
 }
diff --git a/docs/extension.schema.json b/docs/extension.schema.json
new file mode 100644 (file)
index 0000000..4b29872
--- /dev/null
@@ -0,0 +1,609 @@
+{
+       "$schema": "http://json-schema.org/schema#",
+       "description": "MediaWiki extension.json schema",
+       "type": "object",
+       "properties": {
+               "name": {
+                       "type": "string",
+                       "description": "The extension's canonical name."
+               },
+               "info-files": {
+                       "type": "array",
+                       "description": "A list of filenames that should be loaded, in addition to this one"
+               },
+               "type": {
+                       "type": "string",
+                       "description": "The extension's type, as an index to $wgExtensionCredits.",
+                       "default": "other",
+                       "enum": [
+                               "api",
+                               "antispam",
+                               "datavalues",
+                               "media",
+                               "parserhook",
+                               "semantic",
+                               "skin",
+                               "specialpage",
+                               "variable",
+                               "other"
+                       ]
+               },
+               "author": {
+                       "type": [
+                               "string",
+                               "array"
+                       ],
+                       "description": "Extension's authors.",
+                       "items": {
+                               "type": "string"
+                       },
+                       "additionalItems": false
+               },
+               "path": {
+                       "type": "string"
+               },
+               "version": {
+                       "type": "string",
+                       "description": "The version of this release of the extension."
+               },
+               "url": {
+                       "type": "string",
+                       "description": "URL to the homepage for the extension.",
+                       "format": "uri"
+               },
+               "description": {
+                       "type": "string",
+                       "description": "Raw description of the extension."
+               },
+               "descriptionmsg": {
+                       "type": "string",
+                       "description": "Message key for a i18n message describing the extension."
+               },
+               "license-name": {
+                       "type": "string",
+                       "description": "Short identifier for the license under which the extension is released.",
+                       "enum": [
+                               "AFL-1.1",
+                               "AFL-1.2",
+                               "AFL-2.0",
+                               "AFL-2.1",
+                               "AFL-3.0",
+                               "APL-1.0",
+                               "Aladdin",
+                               "ANTLR-PD",
+                               "Apache-1.0",
+                               "Apache-1.1",
+                               "Apache-2.0",
+                               "APSL-1.0",
+                               "APSL-1.1",
+                               "APSL-1.2",
+                               "APSL-2.0",
+                               "Artistic-1.0",
+                               "Artistic-1.0-cl8",
+                               "Artistic-1.0-Perl",
+                               "Artistic-2.0",
+                               "AAL",
+                               "BitTorrent-1.0",
+                               "BitTorrent-1.1",
+                               "BSL-1.0",
+                               "BSD-2-Clause",
+                               "BSD-2-Clause-FreeBSD",
+                               "BSD-2-Clause-NetBSD",
+                               "BSD-3-Clause",
+                               "BSD-3-Clause-Clear",
+                               "BSD-4-Clause",
+                               "BSD-4-Clause-UC",
+                               "CECILL-1.0",
+                               "CECILL-1.1",
+                               "CECILL-2.0",
+                               "CECILL-B",
+                               "CECILL-C",
+                               "ClArtistic",
+                               "CNRI-Python",
+                               "CNRI-Python-GPL-Compatible",
+                               "CPOL-1.02",
+                               "CDDL-1.0",
+                               "CDDL-1.1",
+                               "CPAL-1.0",
+                               "CPL-1.0",
+                               "CATOSL-1.1",
+                               "Condor-1.1",
+                               "CC-BY-1.0",
+                               "CC-BY-2.0",
+                               "CC-BY-2.5",
+                               "CC-BY-3.0",
+                               "CC-BY-ND-1.0",
+                               "CC-BY-ND-2.0",
+                               "CC-BY-ND-2.5",
+                               "CC-BY-ND-3.0",
+                               "CC-BY-NC-1.0",
+                               "CC-BY-NC-2.0",
+                               "CC-BY-NC-2.5",
+                               "CC-BY-NC-3.0",
+                               "CC-BY-NC-ND-1.0",
+                               "CC-BY-NC-ND-2.0",
+                               "CC-BY-NC-ND-2.5",
+                               "CC-BY-NC-ND-3.0",
+                               "CC-BY-NC-SA-1.0",
+                               "CC-BY-NC-SA-2.0",
+                               "CC-BY-NC-SA-2.5",
+                               "CC-BY-NC-SA-3.0",
+                               "CC-BY-SA-1.0",
+                               "CC-BY-SA-2.0",
+                               "CC-BY-SA-2.5",
+                               "CC-BY-SA-3.0",
+                               "CC0-1.0",
+                               "CUA-OPL-1.0",
+                               "D-FSL-1.0",
+                               "WTFPL",
+                               "EPL-1.0",
+                               "eCos-2.0",
+                               "ECL-1.0",
+                               "ECL-2.0",
+                               "EFL-1.0",
+                               "EFL-2.0",
+                               "Entessa",
+                               "ErlPL-1.1",
+                               "EUDatagrid",
+                               "EUPL-1.0",
+                               "EUPL-1.1",
+                               "Fair",
+                               "Frameworx-1.0",
+                               "FTL",
+                               "AGPL-1.0",
+                               "AGPL-3.0",
+                               "GFDL-1.1",
+                               "GFDL-1.2",
+                               "GFDL-1.3",
+                               "GPL-1.0",
+                               "GPL-1.0+",
+                               "GPL-2.0",
+                               "GPL-2.0+",
+                               "GPL-2.0-with-autoconf-exception",
+                               "GPL-2.0-with-bison-exception",
+                               "GPL-2.0-with-classpath-exception",
+                               "GPL-2.0-with-font-exception",
+                               "GPL-2.0-with-GCC-exception",
+                               "GPL-3.0",
+                               "GPL-3.0+",
+                               "GPL-3.0-with-autoconf-exception",
+                               "GPL-3.0-with-GCC-exception",
+                               "LGPL-2.1",
+                               "LGPL-2.1+",
+                               "LGPL-3.0",
+                               "LGPL-3.0+",
+                               "LGPL-2.0",
+                               "LGPL-2.0+",
+                               "gSOAP-1.3b",
+                               "HPND",
+                               "IBM-pibs",
+                               "IPL-1.0",
+                               "Imlib2",
+                               "IJG",
+                               "Intel",
+                               "IPA",
+                               "ISC",
+                               "JSON",
+                               "LPPL-1.3a",
+                               "LPPL-1.0",
+                               "LPPL-1.1",
+                               "LPPL-1.2",
+                               "LPPL-1.3c",
+                               "Libpng",
+                               "LPL-1.02",
+                               "LPL-1.0",
+                               "MS-PL",
+                               "MS-RL",
+                               "MirOS",
+                               "MIT",
+                               "Motosoto",
+                               "MPL-1.0",
+                               "MPL-1.1",
+                               "MPL-2.0",
+                               "MPL-2.0-no-copyleft-exception",
+                               "Multics",
+                               "NASA-1.3",
+                               "Naumen",
+                               "NBPL-1.0",
+                               "NGPL",
+                               "NOSL",
+                               "NPL-1.0",
+                               "NPL-1.1",
+                               "Nokia",
+                               "NPOSL-3.0",
+                               "NTP",
+                               "OCLC-2.0",
+                               "ODbL-1.0",
+                               "PDDL-1.0",
+                               "OGTSL",
+                               "OLDAP-2.2.2",
+                               "OLDAP-1.1",
+                               "OLDAP-1.2",
+                               "OLDAP-1.3",
+                               "OLDAP-1.4",
+                               "OLDAP-2.0",
+                               "OLDAP-2.0.1",
+                               "OLDAP-2.1",
+                               "OLDAP-2.2",
+                               "OLDAP-2.2.1",
+                               "OLDAP-2.3",
+                               "OLDAP-2.4",
+                               "OLDAP-2.5",
+                               "OLDAP-2.6",
+                               "OLDAP-2.7",
+                               "OPL-1.0",
+                               "OSL-1.0",
+                               "OSL-2.0",
+                               "OSL-2.1",
+                               "OSL-3.0",
+                               "OLDAP-2.8",
+                               "OpenSSL",
+                               "PHP-3.0",
+                               "PHP-3.01",
+                               "PostgreSQL",
+                               "Python-2.0",
+                               "QPL-1.0",
+                               "RPSL-1.0",
+                               "RPL-1.1",
+                               "RPL-1.5",
+                               "RHeCos-1.1",
+                               "RSCPL",
+                               "Ruby",
+                               "SAX-PD",
+                               "SGI-B-1.0",
+                               "SGI-B-1.1",
+                               "SGI-B-2.0",
+                               "OFL-1.0",
+                               "OFL-1.1",
+                               "SimPL-2.0",
+                               "Sleepycat",
+                               "SMLNJ",
+                               "SugarCRM-1.1.3",
+                               "SISSL",
+                               "SISSL-1.2",
+                               "SPL-1.0",
+                               "Watcom-1.0",
+                               "NCSA",
+                               "VSL-1.0",
+                               "W3C",
+                               "WXwindows",
+                               "Xnet",
+                               "X11",
+                               "XFree86-1.1",
+                               "YPL-1.0",
+                               "YPL-1.1",
+                               "Zimbra-1.3",
+                               "Zlib",
+                               "ZPL-1.1",
+                               "ZPL-2.0",
+                               "ZPL-2.1",
+                               "Unlicense"
+                       ]
+               },
+               "ResourceLoaderModules": {
+                       "type": "object",
+                       "description": "ResourceLoader modules to register",
+                       "additionalProperties": false,
+                       "patternProperties": {
+                               "^[a-zA-Z0-9\\.]+$": {
+                                       "type": "object",
+                                       "description": "A single ResourceLoader module descriptor",
+                                       "properties": {
+                                               "localBasePath": {
+                                                       "type": "string",
+                                                       "description": "Base path to prepend to all local paths in $options. Defaults to $IP"
+                                               },
+                                               "remoteBasePath": {
+                                                       "type": "string",
+                                                       "description": "Base path to prepend to all remote paths in $options. Defaults to $wgScriptPath"
+                                               },
+                                               "remoteExtPath": {
+                                                       "type": "string",
+                                                       "description": "Equivalent of remoteBasePath, but relative to $wgExtensionAssetsPath"
+                                               },
+                                               "scripts": {
+                                                       "type": "array",
+                                                       "description": "Scripts to always include (array of file paths)",
+                                                       "items": {
+                                                               "type": "string"
+                                                       }
+                                               },
+                                               "languageScripts": {
+                                                       "type": "object",
+                                                       "description": "Scripts to include in specific language contexts (mapping of language code to file path(s))",
+                                                       "patternProperties": {
+                                                               "^[a-zA-Z0-9-]{2,}$": {
+                                                                       "type": [
+                                                                               "string",
+                                                                               "array"
+                                                                       ],
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               }
+                                                       }
+                                               },
+                                               "skinScripts": {
+                                                       "type": "object",
+                                                       "description": "Scripts to include in specific skin contexts (mapping of skin name to script(s)",
+                                                       "patternProperties": {
+                                                               ".+": {
+                                                                       "type": [
+                                                                               "string",
+                                                                               "array"
+                                                                       ],
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               }
+                                                       }
+                                               },
+                                               "debugScripts": {
+                                                       "type": "array",
+                                                       "description": "Scripts to include in debug contexts",
+                                                       "items": {
+                                                               "type": "string"
+                                                       }
+                                               },
+                                               "loaderScripts": {
+                                                       "type": "array",
+                                                       "description": "Scripts to include in the startup module",
+                                                       "items": {
+                                                               "type": "string"
+                                                       }
+                                               },
+                                               "dependencies": {
+                                                       "type": "array",
+                                                       "description": "Modules which must be loaded before this module",
+                                                       "items": {
+                                                               "type": "string"
+                                                       }
+                                               },
+                                               "styles": {
+                                                       "type": "array",
+                                                       "description": "Styles to always load",
+                                                       "items": {
+                                                               "type": "string"
+                                                       }
+                                               },
+                                               "skinStyles": {
+                                                       "type": "object",
+                                                       "description": "Styles to include in specific skin contexts (mapping of skin name to style(s))",
+                                                       "patternProperties": {
+                                                               ".+": {
+                                                                       "type": [
+                                                                               "string",
+                                                                               "array"
+                                                                       ],
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               }
+                                                       }
+                                               },
+                                               "messages": {
+                                                       "type": "array",
+                                                       "description": "Messages to always load",
+                                                       "items": {
+                                                               "type": "string"
+                                                       }
+                                               },
+                                               "group": {
+                                                       "type": "string",
+                                                       "description": "Group which this module should be loaded together with"
+                                               },
+                                               "position": {
+                                                       "type": "string",
+                                                       "description": "Position on the page to load this module at",
+                                                       "enum": [
+                                                               "bottom",
+                                                               "top"
+                                                       ]
+                                               }
+                                       }
+                               }
+                       }
+               },
+               "ResourceLoaderSources": {
+                       "type": "object",
+                       "description": "ResourceLoader sources to register"
+               },
+               "ResourceLoaderLESSVars": {
+                       "type": "object",
+                       "description": "ResourceLoader LESS variables"
+               },
+               "ResourceLoaderLESSFunctions": {
+                       "type": "object",
+                       "description": "ResourceLoader LESS functions"
+               },
+               "ResourceLoaderLESSImportPaths": {
+                       "type": "object",
+                       "description": "ResourceLoader import paths"
+               },
+               "namespaces": {
+                       "type": "object",
+                       "description": "Method to add extra namespaces",
+                       "properties": {
+                               "id": {
+                                       "type": "integer"
+                               },
+                               "constant": {
+                                       "type": "string"
+                               },
+                               "name": {
+                                       "type": "string"
+                               },
+                               "gender": {
+                                       "type": "object",
+                                       "properties": {
+                                               "male": {
+                                                       "type": "string"
+                                               },
+                                               "female": {
+                                                       "type": "string"
+                                               }
+                                       }
+                               },
+                               "subpages": {
+                                       "type": "boolean",
+                                       "default": false
+                               },
+                               "content": {
+                                       "type": "boolean",
+                                       "default": false
+                               },
+                               "defaultcontentmodel": {
+                                       "type": "string"
+                               }
+                       }
+               },
+               "TrackingCategories": {
+                       "type": "array",
+                       "description": "Tracking category message keys"
+               },
+               "DefaultUserOptions": {
+                       "type": "object",
+                       "description": "Default values of user options"
+               },
+               "HiddenPrefs": {
+                       "type": "array",
+                       "description": "Preferences users cannot set"
+               },
+               "GroupPermissions": {
+                       "type": "object",
+                       "description": "Default permissions to give to user groups"
+               },
+               "RevokePermissions": {
+                       "type": "object",
+                       "description": "Default permissions to revoke from user groups"
+               },
+               "ImplicitGroups": {
+                       "type": "array",
+                       "description": "Implicit groups"
+               },
+               "GroupsAddToSelf": {
+                       "type": "object",
+                       "description": "Groups a user can add to themselves"
+               },
+               "GroupsRemoveFromSelf": {
+                       "type": "object",
+                       "description": "Groups a user can remove from themselves"
+               },
+               "AddGroups": {
+                       "type": "object",
+                       "description": "Groups a user can add to users"
+               },
+               "RemoveGroups": {
+                       "type": "object",
+                       "description": "Groups a user can remove from users"
+               },
+               "AvailableRights": {
+                       "type": "array",
+                       "description": "User rights added by the extension"
+               },
+               "ContentHandlers": {
+                       "type": "object",
+                       "description": "Mapping of model ID to class name"
+               },
+               "RateLimits": {
+                       "type": "object",
+                       "description": "Rate limits"
+               },
+               "ParserTestFiles": {
+                       "type": "array",
+                       "description": "Parser test files to run"
+               },
+               "RecentChangesFlags": {
+                       "type": "object",
+                       "description": "Flags (letter symbols) shown on RecentChanges pages"
+               },
+               "ExtensionFunctions": {
+                       "type": [
+                               "array",
+                               "string"
+                       ],
+                       "description": "Function to call after setup has finished"
+               },
+               "ExtensionMessagesFiles": {
+                       "type": "object",
+                       "description": "File paths containing PHP internationalization data"
+               },
+               "MessagesDirs": {
+                       "type": "object",
+                       "description": "Directory paths containing JSON internationalization data"
+               },
+               "ExtensionEntryPointListFiles": {
+                       "type": "object"
+               },
+               "SpecialPages": {
+                       "type": "object",
+                       "description": "SpecialPages implemented in this extension (mapping of page name to class name)"
+               },
+               "SpecialPageGroups": {
+                       "type": "object",
+                       "description": "Mapping of special page name to group it belongs to"
+               },
+               "AutoloadClasses": {
+                       "type": "object"
+               },
+               "Hooks": {
+                       "type": "object",
+                       "description": "Hooks this extension uses (mapping of hook name to callback)"
+               },
+               "JobClasses": {
+                       "type": "object",
+                       "description": "Job types this extension implements (mapping of job type to class name)"
+               },
+               "LogTypes": {
+                       "type": "array",
+                       "description": "List of new log types this extension uses"
+               },
+               "LogRestrictions": {
+                       "type": "object"
+               },
+               "FilterLogTypes": {
+                       "type": "array"
+               },
+               "LogNames": {
+                       "type": "object"
+               },
+               "LogHeaders": {
+                       "type": "object"
+               },
+               "LogActions": {
+                       "type": "object"
+               },
+               "LogActionsHandlers": {
+                       "type": "object"
+               },
+               "Actions": {
+                       "type": "object"
+               },
+               "APIModules": {
+                       "type": "object"
+               },
+               "APIFormatModules": {
+                       "type": "object"
+               },
+               "APIMetaModules": {
+                       "type": "object"
+               },
+               "APIPropModules": {
+                       "type": "object"
+               },
+               "APIListModules": {
+                       "type": "object"
+               },
+               "callback": {
+                       "type": [
+                               "array",
+                               "string"
+                       ],
+                       "description": "A function to be called right after MediaWiki processes this file"
+               },
+               "config": {
+                       "type": "object",
+                       "description": "Configuration options for this extension"
+               }
+       }
+}
index b48067b..2de78dd 100644 (file)
@@ -314,7 +314,7 @@ $output: The OutputPage object where output() was called
 
 'AfterImportPage': When a page import is completed.
 $title: Title under which the revisions were imported
-$origTitle: Title provided by the XML file
+$foreignTitle: ForeignTitle object based on data provided by the XML file
 $revCount: Number of revisions in the XML file
 $sRevCount: Number of successfully imported revisions
 $pageInfo: associative array of page information
index dcd171f..51470b6 100644 (file)
@@ -39,7 +39,6 @@
 
 define( 'MW_NO_OUTPUT_COMPRESSION', 1 );
 require __DIR__ . '/includes/WebStart.php';
-wfProfileIn( 'img_auth.php' );
 
 # Set action base paths so that WebRequest::getPathInfo()
 # recognizes the "X" as the 'title' in ../img_auth.php/X urls.
@@ -47,7 +46,6 @@ $wgArticlePath = false; # Don't let a "/*" article path clober our action path
 $wgActionPaths = array( "$wgUploadPath/" );
 
 wfImageAuthMain();
-wfProfileOut( 'img_auth.php' );
 wfLogProfilingData();
 // Commit and close up!
 $factory = wfGetLBFactory();
index 9bc92be..b14114d 100644 (file)
@@ -56,8 +56,6 @@ class AjaxDispatcher {
         * Load up our object with user supplied data
         */
        function __construct( Config $config ) {
-               wfProfileIn( __METHOD__ );
-
                $this->config = $config;
 
                $this->mode = "";
@@ -88,13 +86,11 @@ class AjaxDispatcher {
                                }
                                break;
                        default:
-                               wfProfileOut( __METHOD__ );
                                return;
                                # Or we could throw an exception:
                                # throw new MWException( __METHOD__ . ' called without any data (mode empty).' );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -110,11 +106,8 @@ class AjaxDispatcher {
                        return;
                }
 
-               wfProfileIn( __METHOD__ );
-
                if ( !in_array( $this->func_name, $this->config->get( 'AjaxExportList' ) ) ) {
                        wfDebug( __METHOD__ . ' Bad Request for unknown function ' . $this->func_name . "\n" );
-
                        wfHttpError(
                                400,
                                'Bad Request',
@@ -127,7 +120,6 @@ class AjaxDispatcher {
                                'You are not allowed to view pages.' );
                } else {
                        wfDebug( __METHOD__ . ' dispatching ' . $this->func_name . "\n" );
-
                        try {
                                $result = call_user_func_array( $this->func_name, $this->args );
 
@@ -162,6 +154,5 @@ class AjaxDispatcher {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
        }
 }
index 9079fb0..4698f45 100644 (file)
@@ -752,7 +752,6 @@ class Block {
         * @return bool
         */
        public function deleteIfExpired() {
-               wfProfileIn( __METHOD__ );
 
                if ( $this->isExpired() ) {
                        wfDebug( "Block::deleteIfExpired() -- deleting\n" );
@@ -763,7 +762,6 @@ class Block {
                        $retVal = false;
                }
 
-               wfProfileOut( __METHOD__ );
                return $retVal;
        }
 
@@ -1055,7 +1053,6 @@ class Block {
                        return array();
                }
 
-               wfProfileIn( __METHOD__ );
                $conds = array();
                foreach ( array_unique( $ipChain ) as $ipaddr ) {
                        # Discard invalid IP addresses. Since XFF can be spoofed and we do not
@@ -1077,7 +1074,6 @@ class Block {
                }
 
                if ( !count( $conds ) ) {
-                       wfProfileOut( __METHOD__ );
                        return array();
                }
 
@@ -1108,7 +1104,6 @@ class Block {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $blocks;
        }
 
@@ -1140,8 +1135,6 @@ class Block {
                        return $blocks[0];
                }
 
-               wfProfileIn( __METHOD__ );
-
                // Sort hard blocks before soft ones and secondarily sort blocks
                // that disable account creation before those that don't.
                usort( $blocks, function ( Block $a, Block $b ) {
@@ -1222,11 +1215,9 @@ class Block {
                } elseif ( $blocksList['auto'] ) {
                        $chosenBlock = $blocksList['auto'];
                } else {
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( "Proxy block found, but couldn't be classified." );
                }
 
-               wfProfileOut( __METHOD__ );
                return $chosenBlock;
        }
 
index 322b053..3a21e25 100644 (file)
@@ -60,8 +60,6 @@ class Category {
                        return true;
                }
 
-               wfProfileIn( __METHOD__ );
-
                $dbr = wfGetDB( DB_SLAVE );
                $row = $dbr->selectRow(
                        'category',
@@ -70,8 +68,6 @@ class Category {
                        __METHOD__
                );
 
-               wfProfileOut( __METHOD__ );
-
                if ( !$row ) {
                        # Okay, there were no contents.  Nothing to initialize.
                        if ( $this->mTitle ) {
@@ -258,7 +254,6 @@ class Category {
         * @return TitleArray TitleArray object for category members.
         */
        public function getMembers( $limit = false, $offset = '' ) {
-               wfProfileIn( __METHOD__ );
 
                $dbr = wfGetDB( DB_SLAVE );
 
@@ -284,8 +279,6 @@ class Category {
                        )
                );
 
-               wfProfileOut( __METHOD__ );
-
                return $result;
        }
 
@@ -318,8 +311,6 @@ class Category {
                        }
                }
 
-               wfProfileIn( __METHOD__ );
-
                $dbw = wfGetDB( DB_MASTER );
                $dbw->startAtomic( __METHOD__ );
 
@@ -363,8 +354,6 @@ class Category {
                );
                $dbw->endAtomic( __METHOD__ );
 
-               wfProfileOut( __METHOD__ );
-
                # Now we should update our local counts.
                $this->mPages = $result->pages;
                $this->mSubcats = $result->subcats;
index cf537e1..33de740 100644 (file)
@@ -185,7 +185,6 @@ class CategoryFinder {
         * Scans a "parent layer" of the articles/categories in $this->next
         */
        private function scanNextLayer() {
-               $profiler = new ProfileSection( __METHOD__ );
 
                # Find all parents of the article currently in $this->next
                $layer = array();
index f68da95..1a09d44 100644 (file)
@@ -104,7 +104,6 @@ class CategoryViewer extends ContextSource {
         * @return string HTML output
         */
        public function getHTML() {
-               wfProfileIn( __METHOD__ );
 
                $this->showGallery = $this->getConfig()->get( 'CategoryMagicGallery' )
                        && !$this->getOutput()->mNoGallery;
@@ -140,7 +139,6 @@ class CategoryViewer extends ContextSource {
                # put a div around the headings which are in the user language
                $r = Html::openElement( 'div', $langAttribs ) . $r . '</div>';
 
-               wfProfileOut( __METHOD__ );
                return $r;
        }
 
@@ -154,7 +152,7 @@ class CategoryViewer extends ContextSource {
                        $mode = $this->getRequest()->getVal( 'gallerymode', null );
                        try {
                                $this->gallery = ImageGalleryBase::factory( $mode, $this->getContext() );
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                // User specified something invalid, fallback to default.
                                $this->gallery = ImageGalleryBase::factory( false, $this->getContext() );
                        }
index 1884b5f..ee462d8 100644 (file)
@@ -2348,6 +2348,23 @@ $wgClockSkewFudge = 5;
  */
 $wgInvalidateCacheOnLocalSettingsChange = true;
 
+/**
+ * When loading extensions through the extension registration system, this
+ * can be used to invalidate the cache. A good idea would be to set this to
+ * one file, you can just `touch` that one to invalidate the cache
+ *
+ * @par Example:
+ * @code
+ * $wgExtensionInfoMtime = filemtime( "$IP/LocalSettings.php" );
+ * @endcode
+ *
+ * If set to false, the mtime for each individual JSON file will be checked,
+ * which can be slow if a large number of extensions are being loaded.
+ *
+ * @var int|bool
+ */
+$wgExtensionInfoMTime = false;
+
 /** @} */ # end of cache settings
 
 /************************************************************************//**
@@ -5416,11 +5433,6 @@ $wgUDPProfilerPort = null;
  */
 $wgUDPProfilerFormatString = null;
 
-/**
- * Output debug message on every wfProfileIn/wfProfileOut
- */
-$wgDebugFunctionEntry = false;
-
 /**
  * Destination for wfIncrStats() data...
  * 'cache' to go into the system cache, if enabled (memcached)
diff --git a/includes/DeferredStringifier.php b/includes/DeferredStringifier.php
new file mode 100644 (file)
index 0000000..bd32949
--- /dev/null
@@ -0,0 +1,55 @@
+<?php
+/**
+ * Class that defers a slow string generation until the string is actually needed.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+/**
+ * @since 1.25
+ */
+class DeferredStringifier {
+       /** @var callable Callback used for result string generation */
+       private $callback;
+       /** @var array */
+       private $params;
+       /** @var string */
+       private $result;
+
+       /**
+        * @param callable $callback Callback that gets called by __toString
+        * @param mixed $param,... Parameters to the callback
+        */
+       public function __construct( $callback /*...*/ ) {
+               $this->params = func_get_args();
+               array_shift( $this->params );
+               $this->callback = $callback;
+       }
+
+       /**
+        * Returns a string generated by callback
+        *
+        * @return string
+        */
+       public function __toString() {
+               if ( $this->result === null ) {
+                       $this->result = call_user_func_array( $this->callback, $this->params );
+               }
+               return $this->result;
+       }
+}
index 4370295..cb79fd1 100644 (file)
@@ -467,13 +467,11 @@ class EditPage {
                        return;
                }
 
-               wfProfileIn( __METHOD__ );
                wfDebug( __METHOD__ . ": enter\n" );
 
                // If they used redlink=1 and the page exists, redirect to the main article
                if ( $wgRequest->getBool( 'redlink' ) && $this->mTitle->exists() ) {
                        $wgOut->redirect( $this->mTitle->getFullURL() );
-                       wfProfileOut( __METHOD__ );
                        return;
                }
 
@@ -482,7 +480,6 @@ class EditPage {
 
                if ( $this->live ) {
                        $this->livePreview();
-                       wfProfileOut( __METHOD__ );
                        return;
                }
 
@@ -515,12 +512,9 @@ class EditPage {
 
                        $this->displayPermissionsError( $permErrors );
 
-                       wfProfileOut( __METHOD__ );
                        return;
                }
 
-               wfProfileIn( __METHOD__ . "-business-end" );
-
                $this->isConflict = false;
                // css / js subpages of user pages get a special treatment
                $this->isCssJsSubpage = $this->mTitle->isCssJsSubpage();
@@ -541,8 +535,6 @@ class EditPage {
 
                if ( 'save' == $this->formtype ) {
                        if ( !$this->attemptSave() ) {
-                               wfProfileOut( __METHOD__ . "-business-end" );
-                               wfProfileOut( __METHOD__ );
                                return;
                        }
                }
@@ -552,8 +544,6 @@ class EditPage {
                if ( 'initial' == $this->formtype || $this->firsttime ) {
                        if ( $this->initialiseForm() === false ) {
                                $this->noSuchSectionPage();
-                               wfProfileOut( __METHOD__ . "-business-end" );
-                               wfProfileOut( __METHOD__ );
                                return;
                        }
 
@@ -566,8 +556,6 @@ class EditPage {
                }
 
                $this->showEditForm();
-               wfProfileOut( __METHOD__ . "-business-end" );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -732,13 +720,10 @@ class EditPage {
        function importFormData( &$request ) {
                global $wgContLang, $wgUser;
 
-               wfProfileIn( __METHOD__ );
-
                # Section edit can come from either the form or a link
                $this->section = $request->getVal( 'wpSection', $request->getVal( 'section' ) );
 
                if ( $this->section !== null && $this->section !== '' && !$this->isSectionEditSupported() ) {
-                       wfProfileOut( __METHOD__ );
                        throw new ErrorPageError( 'sectioneditnotsupported-title', 'sectioneditnotsupported-text' );
                }
 
@@ -753,13 +738,10 @@ class EditPage {
                                // Skip this if wpTextbox2 has input, it indicates that we came
                                // from a conflict page with raw page text, not a custom form
                                // modified by subclasses
-                               wfProfileIn( get_class( $this ) . "::importContentFormData" );
                                $textbox1 = $this->importContentFormData( $request );
                                if ( $textbox1 !== null ) {
                                        $this->textbox1 = $textbox1;
                                }
-
-                               wfProfileOut( get_class( $this ) . "::importContentFormData" );
                        }
 
                        # Truncate for whole multibyte characters
@@ -931,7 +913,6 @@ class EditPage {
                // Allow extensions to modify form data
                Hooks::run( 'EditPage::importFormData', array( $this, $request ) );
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -992,8 +973,6 @@ class EditPage {
        protected function getContentObject( $def_content = null ) {
                global $wgOut, $wgRequest, $wgUser, $wgContLang;
 
-               wfProfileIn( __METHOD__ );
-
                $content = false;
 
                // For message page not locally set, use the i18n message.
@@ -1105,7 +1084,6 @@ class EditPage {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $content;
        }
 
@@ -1538,15 +1516,10 @@ class EditPage {
 
                $status = Status::newGood();
 
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-checks' );
-
                if ( !Hooks::run( 'EditPage::attemptSave', array( $this ) ) ) {
                        wfDebug( "Hook 'EditPage::attemptSave' aborted article saving\n" );
                        $status->fatal( 'hookaborted' );
                        $status->value = self::AS_HOOK_ERROR;
-                       wfProfileOut( __METHOD__ . '-checks' );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
 
@@ -1563,8 +1536,6 @@ class EditPage {
                        );
                        $status->fatal( 'spamprotectionmatch', false );
                        $status->value = self::AS_SPAM_ERROR;
-                       wfProfileOut( __METHOD__ . '-checks' );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
 
@@ -1579,8 +1550,6 @@ class EditPage {
                                $ex->getMessage()
                        );
                        $status->value = self::AS_PARSE_ERROR;
-                       wfProfileOut( __METHOD__ . '-checks' );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
 
@@ -1592,9 +1561,6 @@ class EditPage {
                                $code = $wgUser->isAnon() ? self::AS_IMAGE_REDIRECT_ANON : self::AS_IMAGE_REDIRECT_LOGGED;
                                $status->setResult( false, $code );
 
-                               wfProfileOut( __METHOD__ . '-checks' );
-                               wfProfileOut( __METHOD__ );
-
                                return $status;
                }
 
@@ -1623,8 +1589,6 @@ class EditPage {
                        wfDebugLog( 'SpamRegex', "$ip spam regex hit [[$pdbk]]: \"$match\"" );
                        $status->fatal( 'spamprotectionmatch', $match );
                        $status->value = self::AS_SPAM_ERROR;
-                       wfProfileOut( __METHOD__ . '-checks' );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
                if ( !Hooks::run(
@@ -1634,15 +1598,11 @@ class EditPage {
                        # Error messages etc. could be handled within the hook...
                        $status->fatal( 'hookaborted' );
                        $status->value = self::AS_HOOK_ERROR;
-                       wfProfileOut( __METHOD__ . '-checks' );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                } elseif ( $this->hookError != '' ) {
                        # ...or the hook could be expecting us to produce an error
                        $status->fatal( 'hookaborted' );
                        $status->value = self::AS_HOOK_ERROR_EXPECTED;
-                       wfProfileOut( __METHOD__ . '-checks' );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
 
@@ -1651,8 +1611,6 @@ class EditPage {
                        $wgUser->spreadAnyEditBlock();
                        # Check block state against master, thus 'false'.
                        $status->setResult( false, self::AS_BLOCKED_PAGE_FOR_USER );
-                       wfProfileOut( __METHOD__ . '-checks' );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
 
@@ -1661,22 +1619,16 @@ class EditPage {
                        // Error will be displayed by showEditForm()
                        $this->tooBig = true;
                        $status->setResult( false, self::AS_CONTENT_TOO_BIG );
-                       wfProfileOut( __METHOD__ . '-checks' );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
 
                if ( !$wgUser->isAllowed( 'edit' ) ) {
                        if ( $wgUser->isAnon() ) {
                                $status->setResult( false, self::AS_READ_ONLY_PAGE_ANON );
-                               wfProfileOut( __METHOD__ . '-checks' );
-                               wfProfileOut( __METHOD__ );
                                return $status;
                        } else {
                                $status->fatal( 'readonlytext' );
                                $status->value = self::AS_READ_ONLY_PAGE_LOGGED;
-                               wfProfileOut( __METHOD__ . '-checks' );
-                               wfProfileOut( __METHOD__ );
                                return $status;
                        }
                }
@@ -1685,23 +1637,17 @@ class EditPage {
                        && !$wgUser->isAllowed( 'editcontentmodel' )
                ) {
                        $status->setResult( false, self::AS_NO_CHANGE_CONTENT_MODEL );
-                       wfProfileOut( __METHOD__ . '-checks' );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
 
                if ( wfReadOnly() ) {
                        $status->fatal( 'readonlytext' );
                        $status->value = self::AS_READ_ONLY_PAGE;
-                       wfProfileOut( __METHOD__ . '-checks' );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
                if ( $wgUser->pingLimiter() || $wgUser->pingLimiter( 'linkpurge', 0 ) ) {
                        $status->fatal( 'actionthrottledtext' );
                        $status->value = self::AS_RATE_LIMITED;
-                       wfProfileOut( __METHOD__ . '-checks' );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
 
@@ -1709,13 +1655,9 @@ class EditPage {
                # confirmation
                if ( $this->wasDeletedSinceLastEdit() && !$this->recreate ) {
                        $status->setResult( false, self::AS_ARTICLE_WAS_DELETED );
-                       wfProfileOut( __METHOD__ . '-checks' );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
 
-               wfProfileOut( __METHOD__ . '-checks' );
-
                # Load the page data from the master. If anything changes in the meantime,
                # we detect it by using page_latest like a token in a 1 try compare-and-swap.
                $this->mArticle->loadPageData( 'fromdbmaster' );
@@ -1727,7 +1669,6 @@ class EditPage {
                                $status->fatal( 'nocreatetext' );
                                $status->value = self::AS_NO_CREATE_PERMISSION;
                                wfDebug( __METHOD__ . ": no create permission\n" );
-                               wfProfileOut( __METHOD__ );
                                return $status;
                        }
 
@@ -1745,12 +1686,10 @@ class EditPage {
                                $this->blankArticle = true;
                                $status->fatal( 'blankarticle' );
                                $status->setResult( false, self::AS_BLANK_ARTICLE );
-                               wfProfileOut( __METHOD__ );
                                return $status;
                        }
 
                        if ( !$this->runPostMergeFilters( $textbox_content, $status, $wgUser ) ) {
-                               wfProfileOut( __METHOD__ );
                                return $status;
                        }
 
@@ -1855,12 +1794,10 @@ class EditPage {
 
                        if ( $this->isConflict ) {
                                $status->setResult( false, self::AS_CONFLICT_DETECTED );
-                               wfProfileOut( __METHOD__ );
                                return $status;
                        }
 
                        if ( !$this->runPostMergeFilters( $content, $status, $wgUser ) ) {
-                               wfProfileOut( __METHOD__ );
                                return $status;
                        }
 
@@ -1870,7 +1807,6 @@ class EditPage {
                                        $this->missingSummary = true;
                                        $status->fatal( 'missingsummary' ); // or 'missingcommentheader' if $section == 'new'. Blegh
                                        $status->value = self::AS_SUMMARY_NEEDED;
-                                       wfProfileOut( __METHOD__ );
                                        return $status;
                                }
 
@@ -1879,7 +1815,6 @@ class EditPage {
                                        $this->missingComment = true;
                                        $status->fatal( 'missingcommenttext' );
                                        $status->value = self::AS_TEXTBOX_EMPTY;
-                                       wfProfileOut( __METHOD__ );
                                        return $status;
                                }
                        } elseif ( !$this->allowBlankSummary
@@ -1890,12 +1825,10 @@ class EditPage {
                                $this->missingSummary = true;
                                $status->fatal( 'missingsummary' );
                                $status->value = self::AS_SUMMARY_NEEDED;
-                               wfProfileOut( __METHOD__ );
                                return $status;
                        }
 
                        # All's well
-                       wfProfileIn( __METHOD__ . '-sectionanchor' );
                        $sectionanchor = '';
                        if ( $this->section == 'new' ) {
                                $this->summary = $this->newSectionSummary( $sectionanchor );
@@ -1912,7 +1845,6 @@ class EditPage {
                                }
                        }
                        $result['sectionanchor'] = $sectionanchor;
-                       wfProfileOut( __METHOD__ . '-sectionanchor' );
 
                        // Save errors may fall down to the edit form, but we've now
                        // merged the section into full text. Clear the section field
@@ -1934,7 +1866,6 @@ class EditPage {
                                $this->selfRedirect = true;
                                $status->fatal( 'selfredirect' );
                                $status->value = self::AS_SELF_REDIRECT;
-                               wfProfileOut( __METHOD__ );
                                return $status;
                        }
                }
@@ -1944,7 +1875,6 @@ class EditPage {
                if ( $this->kblength > $wgMaxArticleSize ) {
                        $this->tooBig = true;
                        $status->setResult( false, self::AS_MAX_ARTICLE_SIZE_EXCEEDED );
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
 
@@ -1974,7 +1904,6 @@ class EditPage {
                                // Destroys data doEdit() put in $status->value but who cares
                                $doEditStatus->value = self::AS_END;
                        }
-                       wfProfileOut( __METHOD__ );
                        return $doEditStatus;
                }
 
@@ -1985,7 +1914,6 @@ class EditPage {
                }
                $result['redirect'] = $content->isRedirect();
                $this->updateWatchlist();
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -2022,7 +1950,6 @@ class EditPage {
         * @return bool
         */
        private function mergeChangesIntoContent( &$editContent ) {
-               wfProfileIn( __METHOD__ );
 
                $db = wfGetDB( DB_MASTER );
 
@@ -2031,7 +1958,6 @@ class EditPage {
                $baseContent = $baseRevision ? $baseRevision->getContent() : null;
 
                if ( is_null( $baseContent ) ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -2040,7 +1966,6 @@ class EditPage {
                $currentContent = $currentRevision ? $currentRevision->getContent() : null;
 
                if ( is_null( $currentContent ) ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -2050,11 +1975,9 @@ class EditPage {
 
                if ( $result ) {
                        $editContent = $result;
-                       wfProfileOut( __METHOD__ );
                        return true;
                }
 
-               wfProfileOut( __METHOD__ );
                return false;
        }
 
@@ -2373,8 +2296,6 @@ class EditPage {
        function showEditForm( $formCallback = null ) {
                global $wgOut, $wgUser;
 
-               wfProfileIn( __METHOD__ );
-
                # need to parse the preview early so that we know which templates are used,
                # otherwise users with "show preview after edit box" will get a blank list
                # we parse this near the beginning so that setHeaders can do the title
@@ -2389,7 +2310,6 @@ class EditPage {
                $this->setHeaders();
 
                if ( $this->showHeader() === false ) {
-                       wfProfileOut( __METHOD__ );
                        return;
                }
 
@@ -2593,7 +2513,6 @@ class EditPage {
                        $this->displayPreviewArea( $previewOutput, false );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -3250,8 +3169,6 @@ HTML
                        return '';
                }
 
-               wfProfileIn( __METHOD__ );
-
                $limitReport = Html::rawElement( 'div', array( 'class' => 'mw-limitReportExplanation' ),
                        wfMessage( 'limitreport-title' )->parseAsBlock()
                );
@@ -3286,8 +3203,6 @@ HTML
                        Html::closeElement( 'table' ) .
                        Html::closeElement( 'div' );
 
-               wfProfileOut( __METHOD__ );
-
                return $limitReport;
        }
 
@@ -3473,8 +3388,6 @@ HTML
                global $wgOut, $wgUser, $wgRawHtml, $wgLang;
                global $wgAllowUserCss, $wgAllowUserJs;
 
-               wfProfileIn( __METHOD__ );
-
                if ( $wgRawHtml && !$this->mTokenOk ) {
                        // Could be an offsite preview attempt. This is very unsafe if
                        // HTML is enabled, as it could be an attack.
@@ -3486,7 +3399,6 @@ HTML
                                $parsedNote = $wgOut->parse( "<div class='previewnote'>" .
                                        wfMessage( 'session_fail_preview_html' )->text() . "</div>", true, /* interface */true );
                        }
-                       wfProfileOut( __METHOD__ );
                        return $parsedNote;
                }
 
@@ -3500,7 +3412,6 @@ HTML
                                'AlternateEditPreview',
                                array( $this, &$content, &$previewHTML, &$this->mParserOutput ) )
                        ) {
-                               wfProfileOut( __METHOD__ );
                                return $previewHTML;
                        }
 
@@ -3619,7 +3530,6 @@ HTML
                        'class' => 'mw-content-' . $pageViewLang->getDir() );
                $previewHTML = Html::rawElement( 'div', $attribs, $previewHTML );
 
-               wfProfileOut( __METHOD__ );
                return $previewhead . $previewHTML . $this->previewTextAfterContent;
        }
 
index dd5cb0c..4600feb 100644 (file)
@@ -213,7 +213,6 @@ class WikiExporter {
         * @param array $cond
         */
        protected function do_list_authors( $cond ) {
-               wfProfileIn( __METHOD__ );
                $this->author_list = "<contributors>";
                // rev_deleted
 
@@ -239,7 +238,6 @@ class WikiExporter {
                                "</contributor>";
                }
                $this->author_list .= "</contributors>";
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -248,7 +246,6 @@ class WikiExporter {
         * @throws Exception
         */
        protected function dumpFrom( $cond = '' ) {
-               wfProfileIn( __METHOD__ );
                # For logging dumps...
                if ( $this->history & self::LOGS ) {
                        $where = array( 'user_id = log_user' );
@@ -304,7 +301,6 @@ class WikiExporter {
                                }
 
                                // Inform caller about problem
-                               wfProfileOut( __METHOD__ );
                                throw $e;
                        }
                # For page dumps...
@@ -349,7 +345,6 @@ class WikiExporter {
                                $join['revision'] = array( 'INNER JOIN', 'page_id=rev_page AND page_latest=rev_id' );
                                # One, and only one hook should set this, and return false
                                if ( Hooks::run( 'WikiExporter::dumpStableQuery', array( &$tables, &$opts, &$join ) ) ) {
-                                       wfProfileOut( __METHOD__ );
                                        throw new MWException( __METHOD__ . " given invalid history dump type." );
                                }
                        } elseif ( $this->history & WikiExporter::RANGE ) {
@@ -358,7 +353,6 @@ class WikiExporter {
                                $opts['ORDER BY'] = array( 'rev_page ASC', 'rev_id ASC' );
                        } else {
                                # Unknown history specification parameter?
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( __METHOD__ . " given invalid history dump type." );
                        }
                        # Query optimization hacks
@@ -417,7 +411,6 @@ class WikiExporter {
                                throw $e;
                        }
                }
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -651,7 +644,6 @@ class XmlDumpWriter {
         * @access private
         */
        function writeRevision( $row ) {
-               wfProfileIn( __METHOD__ );
 
                $out = "    <revision>\n";
                $out .= "      " . Xml::element( 'id', null, strval( $row->rev_id ) ) . "\n";
@@ -726,7 +718,6 @@ class XmlDumpWriter {
 
                $out .= "    </revision>\n";
 
-               wfProfileOut( __METHOD__ );
                return $out;
        }
 
@@ -739,7 +730,6 @@ class XmlDumpWriter {
         * @access private
         */
        function writeLogItem( $row ) {
-               wfProfileIn( __METHOD__ );
 
                $out = "  <logitem>\n";
                $out .= "    " . Xml::element( 'id', null, strval( $row->log_id ) ) . "\n";
@@ -773,7 +763,6 @@ class XmlDumpWriter {
 
                $out .= "  </logitem>\n";
 
-               wfProfileOut( __METHOD__ );
                return $out;
        }
 
index 6937c32..15fdbc5 100644 (file)
@@ -106,7 +106,6 @@ class FeedUtils {
                $comment, $actiontext = ''
        ) {
                global $wgFeedDiffCutoff, $wgLang;
-               wfProfileIn( __METHOD__ );
 
                // log entries
                $completeText = '<p>' . implode( ' ',
@@ -124,12 +123,10 @@ class FeedUtils {
                // Can't diff special pages, unreadable pages or pages with no new revision
                // to compare against: just return the text.
                if ( $title->getNamespace() < 0 || $accErrors || !$newid ) {
-                       wfProfileOut( __METHOD__ );
                        return $completeText;
                }
 
                if ( $oldid ) {
-                       wfProfileIn( __METHOD__ . "-dodiff" );
 
                        #$diffText = $de->getDiff( wfMessage( 'revisionasof',
                        #       $wgLang->timeanddate( $timestamp ),
@@ -170,7 +167,6 @@ class FeedUtils {
                                $diffText = UtfNormal::cleanUp( $diffText );
                                $diffText = self::applyDiffStyle( $diffText );
                        }
-                       wfProfileOut( __METHOD__ . "-dodiff" );
                } else {
                        $rev = Revision::newFromId( $newid );
                        if ( $wgFeedDiffCutoff <= 0 || is_null( $rev ) ) {
@@ -208,7 +204,6 @@ class FeedUtils {
                }
                $completeText .= $diffText;
 
-               wfProfileOut( __METHOD__ );
                return $completeText;
        }
 
index 1c709e6..c1d14db 100644 (file)
@@ -201,7 +201,7 @@ class FileDeleteForm {
                                                $dbw->rollback( __METHOD__ );
                                        }
                                }
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                // Rollback before returning to prevent UI from displaying
                                // incorrect "View or restore N deleted edits?"
                                $dbw->rollback( __METHOD__ );
index 403566e..a1c39fb 100644 (file)
@@ -160,6 +160,80 @@ if ( !function_exists( 'hash_equals' ) ) {
 }
 /// @endcond
 
+/**
+ * Load an extension
+ *
+ * This is the closest equivalent to:
+ *   require_once "$IP/extensions/$name/$name.php";
+ * as it will process and load the extension immediately.
+ *
+ * However, batch loading with wfLoadExtensions will
+ * be more performant.
+ *
+ * @param string $name Name of the extension to load
+ * @param string|null $path Absolute path of where to find the extension.json file
+ */
+function wfLoadExtension( $name, $path = null ) {
+       if ( !$path ) {
+               global $IP;
+               $path = "$IP/extensions/$name/extension.json";
+       }
+       ExtensionRegistry::getInstance()->load( $path );
+}
+
+/**
+ * Load multiple extensions at once
+ *
+ * Same as wfLoadExtension, but more efficient if you
+ * are loading multiple extensions.
+ *
+ * If you want to specify custom paths, you should interact with
+ * ExtensionRegistry directly.
+ *
+ * @see wfLoadExtension
+ * @param string[] $exts Array of extension names to load
+ */
+function wfLoadExtensions( array $exts ) {
+       global $IP;
+       $registry = ExtensionRegistry::getInstance();
+       foreach ( $exts as $ext ) {
+               $registry->queue( "$IP/extensions/$ext/extension.json" );
+       }
+
+       $registry->loadFromQueue();
+}
+
+/**
+ * Load a skin
+ *
+ * @see wfLoadExtension
+ * @param string $name Name of the extension to load
+ * @param string|null $path Absolute path of where to find the skin.json file
+ */
+function wfLoadSkin( $name, $path = null ) {
+       if ( !$path ) {
+               global $IP;
+               $path = "$IP/skins/$name/skin.json";
+       }
+       ExtensionRegistry::getInstance()->load( $path );
+}
+
+/**
+ * Load multiple skins at once
+ *
+ * @see wfLoadExtensions
+ * @param string[] $skins Array of extension names to load
+ */
+function wfLoadSkins( array $skins ) {
+       global $IP;
+       $registry = ExtensionRegistry::getInstance();
+       foreach ( $skins as $skin ) {
+               $registry->queue( "$IP/skins/$skin/skin.json" );
+       }
+
+       $registry->loadFromQueue();
+}
+
 /**
  * Like array_diff( $a, $b ) except that it works with two-dimensional arrays.
  * @param array $a
@@ -1254,7 +1328,7 @@ function wfLogProfilingData() {
        // any knowledge about an URL and throw an exception instead.
        try {
                $ctx['url'] = urldecode( $wgRequest->getRequestURL() );
-       } catch ( MWException $ignored ) {
+       } catch ( Exception $ignored ) {
                // no-op
        }
 
@@ -1515,10 +1589,8 @@ function wfMsgForContentNoTrans( $key ) {
 function wfMsgReal( $key, $args, $useDB = true, $forContent = false, $transform = true ) {
        wfDeprecated( __METHOD__, '1.21' );
 
-       wfProfileIn( __METHOD__ );
        $message = wfMsgGetKey( $key, $useDB, $forContent, $transform );
        $message = wfMsgReplaceArgs( $message, $args );
-       wfProfileOut( __METHOD__ );
        return $message;
 }
 
@@ -4010,7 +4082,6 @@ function wfUnpack( $format, $data, $length = false ) {
  */
 function wfIsBadImage( $name, $contextTitle = false, $blacklist = null ) {
        static $badImageCache = null; // based on bad_image_list msg
-       wfProfileIn( __METHOD__ );
 
        # Handle redirects
        $redirectTitle = RepoGroup::singleton()->checkRedirect( Title::makeTitle( NS_FILE, $name ) );
@@ -4021,7 +4092,6 @@ function wfIsBadImage( $name, $contextTitle = false, $blacklist = null ) {
        # Run the extension hook
        $bad = false;
        if ( !Hooks::run( 'BadImage', array( $name, &$bad ) ) ) {
-               wfProfileOut( __METHOD__ );
                return $bad;
        }
 
@@ -4071,7 +4141,6 @@ function wfIsBadImage( $name, $contextTitle = false, $blacklist = null ) {
 
        $contextKey = $contextTitle ? $contextTitle->getPrefixedDBkey() : false;
        $bad = isset( $badImages[$name] ) && !isset( $badImages[$name][$contextKey] );
-       wfProfileOut( __METHOD__ );
        return $bad;
 }
 
index e033746..93a1a04 100644 (file)
@@ -198,8 +198,7 @@ class Html {
        /**
         * Returns an HTML element in a string.  The major advantage here over
         * manually typing out the HTML is that it will escape all attribute
-        * values.  If you're hardcoding all the attributes, or there are none, you
-        * should probably just type out the html element yourself.
+        * values.
         *
         * This is quite similar to Xml::tags(), but it implements some useful
         * HTML-specific logic.  For instance, there is no $allowShortTag
index f74c15a..b2926d1 100644 (file)
@@ -133,7 +133,6 @@ class HtmlFormatter {
         * @return array Array of removed DOMElements
         */
        public function filterContent() {
-               wfProfileIn( __METHOD__ );
                $removals = $this->parseItemsToRemove();
 
                // Bail out early if nothing to do
@@ -143,7 +142,6 @@ class HtmlFormatter {
                        },
                        true
                ) ) {
-                       wfProfileOut( __METHOD__ );
                        return array();
                }
 
@@ -202,7 +200,6 @@ class HtmlFormatter {
                        $removed = array_merge( $removed, $this->removeElements( $elements ) );
                }
 
-               wfProfileOut( __METHOD__ );
                return $removed;
        }
 
@@ -235,7 +232,6 @@ class HtmlFormatter {
         * @return string
         */
        private function fixLibXML( $html ) {
-               wfProfileIn( __METHOD__ );
                static $replacements;
                if ( !$replacements ) {
                        // We don't include rules like '&#34;' => '&amp;quot;' because entities had already been
@@ -249,7 +245,6 @@ class HtmlFormatter {
                }
                $html = $replacements->replace( $html );
                $html = mb_convert_encoding( $html, 'UTF-8', 'HTML-ENTITIES' );
-               wfProfileOut( __METHOD__ );
                return $html;
        }
 
@@ -264,10 +259,8 @@ class HtmlFormatter {
         * @return string Processed HTML
         */
        public function getText( $element = null ) {
-               wfProfileIn( __METHOD__ );
 
                if ( $this->doc ) {
-                       wfProfileIn( __METHOD__ . '-dom' );
                        if ( $element !== null && !( $element instanceof DOMElement ) ) {
                                $element = $this->doc->getElementById( $element );
                        }
@@ -283,9 +276,7 @@ class HtmlFormatter {
                                $body->appendChild( $element );
                        }
                        $html = $this->doc->saveHTML();
-                       wfProfileOut( __METHOD__ . '-dom' );
 
-                       wfProfileIn( __METHOD__ . '-fixes' );
                        $html = $this->fixLibXml( $html );
                        if ( wfIsWindows() ) {
                                // Cleanup for CRLF misprocessing of unknown origin on Windows.
@@ -294,7 +285,6 @@ class HtmlFormatter {
                                // XML code paths if possible and fix there.
                                $html = str_replace( '&#13;', '', $html );
                        }
-                       wfProfileOut( __METHOD__ . '-fixes' );
                } else {
                        $html = $this->html;
                }
@@ -302,14 +292,11 @@ class HtmlFormatter {
                $html = preg_replace( '/<!--.*?-->|^.*?<body>|<\/body>.*$/s', '', $html );
                $html = $this->onHtmlReady( $html );
 
-               wfProfileIn( __METHOD__ . '-flatten' );
                if ( $this->elementsToFlatten ) {
                        $elements = implode( '|', $this->elementsToFlatten );
                        $html = preg_replace( "#</?($elements)\\b[^>]*>#is", '', $html );
                }
-               wfProfileOut( __METHOD__ . '-flatten' );
 
-               wfProfileOut( __METHOD__ );
                return $html;
        }
 
@@ -350,7 +337,6 @@ class HtmlFormatter {
         * @return array
         */
        protected function parseItemsToRemove() {
-               wfProfileIn( __METHOD__ );
                $removals = array(
                        'ID' => array(),
                        'TAG' => array(),
@@ -372,7 +358,6 @@ class HtmlFormatter {
                        $removals['TAG'][] = 'video';
                }
 
-               wfProfileOut( __METHOD__ );
                return $removals;
        }
 }
index f9ee14b..d066df8 100644 (file)
@@ -59,7 +59,6 @@ class Http {
         */
        public static function request( $method, $url, $options = array() ) {
                wfDebug( "HTTP: $method: $url\n" );
-               wfProfileIn( __METHOD__ . "-$method" );
 
                $options['method'] = strtoupper( $method );
 
@@ -77,7 +76,6 @@ class Http {
                if ( $status->isOK() ) {
                        $content = $req->getContent();
                }
-               wfProfileOut( __METHOD__ . "-$method" );
                return $content;
        }
 
@@ -436,7 +434,6 @@ class MWHttpRequest {
         * @return Status
         */
        public function execute() {
-               wfProfileIn( __METHOD__ );
 
                $this->content = "";
 
@@ -454,7 +451,6 @@ class MWHttpRequest {
                        $this->setUserAgent( Http::userAgent() );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -463,7 +459,6 @@ class MWHttpRequest {
         * found in an array in the member variable headerList.
         */
        protected function parseHeader() {
-               wfProfileIn( __METHOD__ );
 
                $lastname = "";
 
@@ -482,7 +477,6 @@ class MWHttpRequest {
 
                $this->parseCookies();
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -616,7 +610,6 @@ class MWHttpRequest {
         * Parse the cookies in the response headers and store them in the cookie jar.
         */
        protected function parseCookies() {
-               wfProfileIn( __METHOD__ );
 
                if ( !$this->cookieJar ) {
                        $this->cookieJar = new CookieJar;
@@ -629,7 +622,6 @@ class MWHttpRequest {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -717,12 +709,10 @@ class CurlHttpRequest extends MWHttpRequest {
        }
 
        public function execute() {
-               wfProfileIn( __METHOD__ );
 
                parent::execute();
 
                if ( !$this->status->isOK() ) {
-                       wfProfileOut( __METHOD__ );
                        return $this->status;
                }
 
@@ -768,7 +758,6 @@ class CurlHttpRequest extends MWHttpRequest {
                $curlHandle = curl_init( $this->url );
 
                if ( !curl_setopt_array( $curlHandle, $this->curlOptions ) ) {
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( "Error setting curl options." );
                }
 
@@ -797,8 +786,6 @@ class CurlHttpRequest extends MWHttpRequest {
                $this->parseHeader();
                $this->setStatus();
 
-               wfProfileOut( __METHOD__ );
-
                return $this->status;
        }
 
@@ -834,7 +821,6 @@ class PhpHttpRequest extends MWHttpRequest {
        }
 
        public function execute() {
-               wfProfileIn( __METHOD__ );
 
                parent::execute();
 
@@ -940,13 +926,11 @@ class PhpHttpRequest extends MWHttpRequest {
 
                if ( $fh === false ) {
                        $this->status->fatal( 'http-request-error' );
-                       wfProfileOut( __METHOD__ );
                        return $this->status;
                }
 
                if ( $result['timed_out'] ) {
                        $this->status->fatal( 'http-timed-out', $this->url );
-                       wfProfileOut( __METHOD__ );
                        return $this->status;
                }
 
@@ -968,8 +952,6 @@ class PhpHttpRequest extends MWHttpRequest {
                }
                fclose( $fh );
 
-               wfProfileOut( __METHOD__ );
-
                return $this->status;
        }
 }
index daefb88..c3caecc 100644 (file)
  */
 class WikiImporter {
        private $reader = null;
+       private $foreignNamespaces = null;
        private $mLogItemCallback, $mUploadCallback, $mRevisionCallback, $mPageCallback;
-       private $mSiteInfoCallback, $mTargetNamespace, $mTargetRootPage, $mPageOutCallback;
+       private $mSiteInfoCallback, $mTargetNamespace, $mPageOutCallback;
        private $mNoticeCallback, $mDebug;
        private $mImportUploads, $mImageBasePath;
        private $mNoUpdates = false;
        /** @var Config */
        private $config;
+       /** @var ImportTitleFactory */
+       private $importTitleFactory;
 
        /**
         * Creates an ImportXMLReader drawing from the source provided
@@ -68,6 +71,8 @@ class WikiImporter {
                $this->setUploadCallback( array( $this, 'importUpload' ) );
                $this->setLogItemCallback( array( $this, 'importLogItem' ) );
                $this->setPageOutCallback( array( $this, 'finishImportPage' ) );
+
+               $this->importTitleFactory = new NaiveImportTitleFactory();
        }
 
        /**
@@ -199,6 +204,15 @@ class WikiImporter {
                return $previous;
        }
 
+       /**
+        * Sets the factory object to use to convert ForeignTitle objects into local
+        * Title objects
+        * @param ImportTitleFactory $factory
+        */
+       public function setImportTitleFactory( $factory ) {
+               $this->importTitleFactory = $factory;
+       }
+
        /**
         * Set a target namespace to override the defaults
         * @param null|int $namespace
@@ -208,9 +222,16 @@ class WikiImporter {
                if ( is_null( $namespace ) ) {
                        // Don't override namespaces
                        $this->mTargetNamespace = null;
-               } elseif ( $namespace >= 0 ) {
-                       // @todo FIXME: Check for validity
-                       $this->mTargetNamespace = intval( $namespace );
+                       $this->setImportTitleFactory( new NaiveImportTitleFactory() );
+                       return true;
+               } elseif (
+                       $namespace >= 0 &&
+                       MWNamespace::exists( intval( $namespace ) )
+               ) {
+                       $namespace = intval( $namespace );
+                       $this->mTargetNamespace = $namespace;
+                       $this->setImportTitleFactory( new NamespaceImportTitleFactory( $namespace ) );
+                       return true;
                } else {
                        return false;
                }
@@ -225,7 +246,7 @@ class WikiImporter {
                $status = Status::newGood();
                if ( is_null( $rootpage ) ) {
                        // No rootpage
-                       $this->mTargetRootPage = null;
+                       $this->setImportTitleFactory( new NaiveImportTitleFactory() );
                } elseif ( $rootpage !== '' ) {
                        $rootpage = rtrim( $rootpage, '/' ); //avoid double slashes
                        $title = Title::newFromText( $rootpage, !is_null( $this->mTargetNamespace )
@@ -244,9 +265,9 @@ class WikiImporter {
                                                : $wgContLang->getNsText( $title->getNamespace() );
                                        $status->fatal( 'import-rootpage-nosubpage', $displayNSText );
                                } else {
-                                       // set namespace to 'all', so the namespace check in processTitle() can passed
+                                       // set namespace to 'all', so the namespace check in processTitle() can pass
                                        $this->setTargetNamespace( null );
-                                       $this->mTargetRootPage = $title->getPrefixedDBkey();
+                                       $this->setImportTitleFactory( new SubpageImportTitleFactory( $title ) );
                                }
                        }
                }
@@ -320,13 +341,14 @@ class WikiImporter {
        /**
         * Mostly for hook use
         * @param Title $title
-        * @param string $origTitle
+        * @param ForeignTitle $foreignTitle
         * @param int $revCount
         * @param int $sRevCount
         * @param array $pageInfo
         * @return bool
         */
-       public function finishImportPage( $title, $origTitle, $revCount, $sRevCount, $pageInfo ) {
+       public function finishImportPage( $title, $foreignTitle, $revCount,
+                       $sRevCount, $pageInfo ) {
                $args = func_get_args();
                return Hooks::run( 'AfterImportPage', $args );
        }
@@ -348,6 +370,20 @@ class WikiImporter {
                $this->debug( "-- Text: " . $revision->text );
        }
 
+       /**
+        * Notify the callback function of site info
+        * @param array $siteInfo
+        * @return bool|mixed
+        */
+       private function siteInfoCallback( $siteInfo ) {
+               if ( isset( $this->mSiteInfoCallback ) ) {
+                       return call_user_func_array( $this->mSiteInfoCallback,
+                                       array( $siteInfo, $this ) );
+               } else {
+                       return false;
+               }
+       }
+
        /**
         * Notify the callback function when a new "<page>" is reached.
         * @param Title $title
@@ -361,12 +397,13 @@ class WikiImporter {
        /**
         * Notify the callback function when a "</page>" is closed.
         * @param Title $title
-        * @param Title $origTitle
+        * @param ForeignTitle $foreignTitle
         * @param int $revCount
         * @param int $sucCount Number of revisions for which callback returned true
         * @param array $pageInfo Associative array of page information
         */
-       private function pageOutCallback( $title, $origTitle, $revCount, $sucCount, $pageInfo ) {
+       private function pageOutCallback( $title, $foreignTitle, $revCount,
+                       $sucCount, $pageInfo ) {
                if ( isset( $this->mPageOutCallback ) ) {
                        $args = func_get_args();
                        call_user_func_array( $this->mPageOutCallback, $args );
@@ -493,18 +530,31 @@ class WikiImporter {
                return true;
        }
 
-       /**
-        * @return bool
-        * @throws MWException
-        */
        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 ) {
-                       $this->reader->next();
-                       return true;
+               $this->debug( "Enter site info handler." );
+               $siteInfo = array();
+
+               // Fields that can just be stuffed in the siteInfo object
+               $normalFields = array( 'sitename', 'base', 'generator', 'case' );
+
+               while ( $this->reader->read() ) {
+                       if ( $this->reader->nodeType == XmlReader::END_ELEMENT &&
+                                       $this->reader->name == 'siteinfo' ) {
+                               break;
+                       }
+
+                       $tag = $this->reader->name;
+
+                       if ( $tag == 'namespace' ) {
+                               $this->foreignNamespaces[ $this->nodeAttribute( 'key' ) ] =
+                                       $this->nodeContents();
+                       } elseif ( in_array( $tag, $normalFields ) ) {
+                               $siteInfo[$tag] = $this->nodeContents();
+                       }
                }
-               throw new MWException( "SiteInfo tag is not yet handled, do not set mSiteInfoCallback" );
+
+               $siteInfo['_namespaces'] = $this->foreignNamespaces;
+               $this->siteInfoCallback( $siteInfo );
        }
 
        private function handleLogItem() {
@@ -574,7 +624,7 @@ class WikiImporter {
                $pageInfo = array( 'revisionCount' => 0, 'successfulRevisionCount' => 0 );
 
                // Fields that can just be stuffed in the pageInfo object
-               $normalFields = array( 'title', 'id', 'redirect', 'restrictions' );
+               $normalFields = array( 'title', 'ns', 'id', 'redirect', 'restrictions' );
 
                $skip = false;
                $badTitle = false;
@@ -585,6 +635,8 @@ class WikiImporter {
                                break;
                        }
 
+                       $skip = false;
+
                        $tag = $this->reader->name;
 
                        if ( $badTitle ) {
@@ -605,29 +657,35 @@ class WikiImporter {
                                        $pageInfo[$tag] = $this->nodeAttribute( 'title' );
                                } else {
                                        $pageInfo[$tag] = $this->nodeContents();
-                                       if ( $tag == 'title' ) {
-                                               $title = $this->processTitle( $pageInfo['title'] );
+                               }
+                       } elseif ( $tag == 'revision' || $tag == 'upload' ) {
+                               if ( !isset( $title ) ) {
+                                       $title = $this->processTitle( $pageInfo['title'],
+                                               isset( $pageInfo['ns'] ) ? $pageInfo['ns'] : null );
+
+                                       if ( !$title ) {
+                                               $badTitle = true;
+                                               $skip = true;
+                                       }
 
-                                               if ( !$title ) {
-                                                       $badTitle = true;
-                                                       $skip = true;
-                                               }
+                                       $this->pageCallback( $title );
+                                       list( $pageInfo['_title'], $foreignTitle ) = $title;
+                               }
 
-                                               $this->pageCallback( $title );
-                                               list( $pageInfo['_title'], $origTitle ) = $title;
+                               if ( $title ) {
+                                       if ( $tag == 'revision' ) {
+                                               $this->handleRevision( $pageInfo );
+                                       } else {
+                                               $this->handleUpload( $pageInfo );
                                        }
                                }
-                       } elseif ( $tag == 'revision' ) {
-                               $this->handleRevision( $pageInfo );
-                       } elseif ( $tag == 'upload' ) {
-                               $this->handleUpload( $pageInfo );
                        } elseif ( $tag != '#text' ) {
                                $this->warn( "Unhandled page XML tag $tag" );
                                $skip = true;
                        }
                }
 
-               $this->pageOutCallback( $pageInfo['_title'], $origTitle,
+               $this->pageOutCallback( $pageInfo['_title'], $foreignTitle,
                                        $pageInfo['revisionCount'],
                                        $pageInfo['successfulRevisionCount'],
                                        $pageInfo );
@@ -852,28 +910,27 @@ class WikiImporter {
 
        /**
         * @param string $text
+        * @param string|null $ns
         * @return array|bool
         */
-       private function processTitle( $text ) {
-               $workTitle = $text;
-               $origTitle = Title::newFromText( $workTitle );
-
-               if ( !is_null( $this->mTargetNamespace ) && !is_null( $origTitle ) ) {
-                       # makeTitleSafe, because $origTitle can have a interwiki (different setting of interwiki map)
-                       # and than dbKey can begin with a lowercase char
-                       $title = Title::makeTitleSafe( $this->mTargetNamespace,
-                               $origTitle->getDBkey() );
+       private function processTitle( $text, $ns = null ) {
+               if ( is_null( $this->foreignNamespaces ) ) {
+                       $foreignTitleFactory = new NaiveForeignTitleFactory();
                } else {
-                       if ( !is_null( $this->mTargetRootPage ) ) {
-                               $workTitle = $this->mTargetRootPage . '/' . $workTitle;
-                       }
-                       $title = Title::newFromText( $workTitle );
+                       $foreignTitleFactory = new NamespaceAwareForeignTitleFactory(
+                               $this->foreignNamespaces );
                }
 
+               $foreignTitle = $foreignTitleFactory->createForeignTitle( $text,
+                       intval( $ns ) );
+
+               $title = $this->importTitleFactory->createTitleFromForeignTitle(
+                       $foreignTitle );
+
                $commandLineMode = $this->config->get( 'CommandLineMode' );
                if ( is_null( $title ) ) {
                        # Invalid page title? Ignore the page
-                       $this->notice( 'import-error-invalid', $workTitle );
+                       $this->notice( 'import-error-invalid', $foreignTitle->getFullText() );
                        return false;
                } elseif ( $title->isExternal() ) {
                        $this->notice( 'import-error-interwiki', $title->getPrefixedText() );
@@ -891,7 +948,7 @@ class WikiImporter {
                        return false;
                }
 
-               return array( $title, $origTitle );
+               return array( $title, $foreignTitle );
        }
 }
 
index 2bc36b1..7840868 100644 (file)
@@ -197,7 +197,6 @@ class Linker {
                        wfWarn( __METHOD__ . ': Requires $target to be a Title object.', 2 );
                        return "<!-- ERROR -->$html";
                }
-               wfProfileIn( __METHOD__ );
 
                if ( is_string( $query ) ) {
                        // some functions withing core using this still hand over query strings
@@ -212,7 +211,6 @@ class Linker {
                if ( !Hooks::run( 'LinkBegin',
                        array( $dummy, $target, &$html, &$customAttribs, &$query, &$options, &$ret ) )
                ) {
-                       wfProfileOut( __METHOD__ );
                        return $ret;
                }
 
@@ -220,7 +218,6 @@ class Linker {
                $target = self::normaliseSpecialPage( $target );
 
                # If we don't know whether the page exists, let's find out.
-               wfProfileIn( __METHOD__ . '-checkPageExistence' );
                if ( !in_array( 'known', $options ) && !in_array( 'broken', $options ) ) {
                        if ( $target->isKnown() ) {
                                $options[] = 'known';
@@ -228,7 +225,6 @@ class Linker {
                                $options[] = 'broken';
                        }
                }
-               wfProfileOut( __METHOD__ . '-checkPageExistence' );
 
                $oldquery = array();
                if ( in_array( "forcearticlepath", $options ) && $query ) {
@@ -255,7 +251,6 @@ class Linker {
                        $ret = Html::rawElement( 'a', $attribs, $html );
                }
 
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -280,7 +275,6 @@ class Linker {
         * @return string
         */
        private static function linkUrl( $target, $query, $options ) {
-               wfProfileIn( __METHOD__ );
                # We don't want to include fragments for broken links, because they
                # generally make no sense.
                if ( in_array( 'broken', $options ) && $target->hasFragment() ) {
@@ -306,7 +300,6 @@ class Linker {
                }
 
                $ret = $target->getLinkURL( $query, false, $proto );
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -320,12 +313,10 @@ class Linker {
         * @return array
         */
        private static function linkAttribs( $target, $attribs, $options ) {
-               wfProfileIn( __METHOD__ );
                global $wgUser;
                $defaults = array();
 
                if ( !in_array( 'noclasses', $options ) ) {
-                       wfProfileIn( __METHOD__ . '-getClasses' );
                        # Now build the classes.
                        $classes = array();
 
@@ -346,7 +337,6 @@ class Linker {
                        if ( $classes != array() ) {
                                $defaults['class'] = implode( ' ', $classes );
                        }
-                       wfProfileOut( __METHOD__ . '-getClasses' );
                }
 
                # Get a default title attribute.
@@ -370,7 +360,6 @@ class Linker {
                                $ret[$key] = $val;
                        }
                }
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -933,7 +922,6 @@ class Linker {
                }
 
                global $wgEnableUploads, $wgUploadMissingFileUrl, $wgUploadNavigationUrl;
-               wfProfileIn( __METHOD__ );
                if ( $label == '' ) {
                        $label = $title->getPrefixedText();
                }
@@ -946,19 +934,16 @@ class Linker {
                        $redir = RepoGroup::singleton()->getLocalRepo()->checkRedirect( $title );
 
                        if ( $redir ) {
-                               wfProfileOut( __METHOD__ );
                                return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) );
                        }
 
                        $href = self::getUploadUrl( $title, $query );
 
-                       wfProfileOut( __METHOD__ );
                        return '<a href="' . htmlspecialchars( $href ) . '" class="new" title="' .
                                htmlspecialchars( $title->getPrefixedText(), ENT_QUOTES ) . '">' .
                                $encLabel . '</a>';
                }
 
-               wfProfileOut( __METHOD__ );
                return self::linkKnown( $title, $encLabel, array(), wfCgiToArray( $query ) );
        }
 
@@ -1295,7 +1280,6 @@ class Linker {
         * @return mixed|string
         */
        public static function formatComment( $comment, $title = null, $local = false ) {
-               wfProfileIn( __METHOD__ );
 
                # Sanitize text a bit:
                $comment = str_replace( "\n", " ", $comment );
@@ -1306,7 +1290,6 @@ class Linker {
                $comment = self::formatAutocomments( $comment, $title, $local );
                $comment = self::formatLinksInComment( $comment, $title, $local );
 
-               wfProfileOut( __METHOD__ );
                return $comment;
        }
 
@@ -1402,9 +1385,11 @@ class Linker {
         * @param string $comment Text to format links in
         * @param Title|null $title An optional title object used to links to sections
         * @param bool $local Whether section links should refer to local page
+        * @param string|null $wikiId Id of the wiki to link to (if not the local wiki), as used by WikiMap
+        *
         * @return string
         */
-       public static function formatLinksInComment( $comment, $title = null, $local = false ) {
+       public static function formatLinksInComment( $comment, $title = null, $local = false, $wikiId = null ) {
                return preg_replace_callback(
                        '/
                                \[\[
@@ -1418,7 +1403,7 @@ class Linker {
                                \]\]
                                ([^[]*) # 3. link trail (the text up until the next link)
                        /x',
-                       function ( $match ) use ( $title, $local ) {
+                       function ( $match ) use ( $title, $local, $wikiId ) {
                                global $wgContLang;
 
                                $medians = '(?:' . preg_quote( MWNamespace::getCanonicalName( NS_MEDIA ), '/' ) . '|';
@@ -1474,11 +1459,22 @@ class Linker {
                                                        $newTarget = clone ( $title );
                                                        $newTarget->setFragment( '#' . $target->getFragment() );
                                                        $target = $newTarget;
+
                                                }
-                                               $thelink = Linker::link(
-                                                       $target,
-                                                       $linkText . $inside
-                                               ) . $trail;
+
+                                               if ( $wikiId !== null ) {
+                                                       $thelink = Linker::makeExternalLink(
+                                                               WikiMap::getForeignURL( $wikiId, $target->getPrefixedURL() ),
+                                                               $linkText . $inside,
+                                                               true
+                                                       ) . $trail;
+                                               } else {
+                                                       $thelink = Linker::link(
+                                                               $target,
+                                                               $linkText . $inside
+                                                       ) . $trail;
+                                               }
+
                                        }
                                }
                                if ( $thelink ) {
@@ -1515,7 +1511,6 @@ class Linker {
                # ../Foobar/ -- convert to CurrentPage/Foobar, use 'Foobar' as text
                #              (from CurrentPage/CurrentSubPage)
 
-               wfProfileIn( __METHOD__ );
                $ret = $target; # default return value is no change
 
                # Some namespaces don't allow subpages,
@@ -1574,7 +1569,6 @@ class Linker {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -1997,7 +1991,6 @@ class Linker {
                $section = false, $more = null
        ) {
                global $wgLang;
-               wfProfileIn( __METHOD__ );
 
                $outText = '';
                if ( count( $templates ) > 0 ) {
@@ -2077,7 +2070,6 @@ class Linker {
 
                        $outText .= '</ul>';
                }
-               wfProfileOut( __METHOD__ );
                return $outText;
        }
 
@@ -2089,7 +2081,6 @@ class Linker {
         * @return string HTML output
         */
        public static function formatHiddenCategories( $hiddencats ) {
-               wfProfileIn( __METHOD__ );
 
                $outText = '';
                if ( count( $hiddencats ) > 0 ) {
@@ -2106,7 +2097,6 @@ class Linker {
                        }
                        $outText .= '</ul>';
                }
-               wfProfileOut( __METHOD__ );
                return $outText;
        }
 
@@ -2135,7 +2125,6 @@ class Linker {
         *   escape), or false for no title attribute
         */
        public static function titleAttrib( $name, $options = null ) {
-               wfProfileIn( __METHOD__ );
 
                $message = wfMessage( "tooltip-$name" );
 
@@ -2164,7 +2153,6 @@ class Linker {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $tooltip;
        }
 
@@ -2184,7 +2172,6 @@ class Linker {
                if ( isset( self::$accesskeycache[$name] ) ) {
                        return self::$accesskeycache[$name];
                }
-               wfProfileIn( __METHOD__ );
 
                $message = wfMessage( "accesskey-$name" );
 
@@ -2200,7 +2187,6 @@ class Linker {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                self::$accesskeycache[$name] = $accesskey;
                return self::$accesskeycache[$name];
        }
@@ -2308,7 +2294,6 @@ class Linker {
        static function makeLinkObj( $nt, $text = '', $query = '', $trail = '', $prefix = '' ) {
                wfDeprecated( __METHOD__, '1.21' );
 
-               wfProfileIn( __METHOD__ );
                $query = wfCgiToArray( $query );
                list( $inside, $trail ) = self::splitTrail( $trail );
                if ( $text === '' ) {
@@ -2317,7 +2302,6 @@ class Linker {
 
                $ret = self::link( $nt, "$prefix$text$inside", array(), $query ) . $trail;
 
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -2342,8 +2326,6 @@ class Linker {
        ) {
                wfDeprecated( __METHOD__, '1.21' );
 
-               wfProfileIn( __METHOD__ );
-
                if ( $text == '' ) {
                        $text = self::linkText( $title );
                }
@@ -2357,7 +2339,6 @@ class Linker {
                $ret = self::link( $title, "$prefix$text$inside", $attribs, $query,
                        array( 'known', 'noclasses' ) ) . $trail;
 
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
index 4b24a00..186821d 100644 (file)
@@ -330,15 +330,12 @@ class MagicWord {
         */
        function load( $id ) {
                global $wgContLang;
-               wfProfileIn( __METHOD__ );
                $this->mId = $id;
                $wgContLang->getMagic( $this );
                if ( !$this->mSynonyms ) {
                        $this->mSynonyms = array( 'brionmademeputthishere' );
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( "Error: invalid magic word '$id'" );
                }
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -655,7 +652,7 @@ class MagicWord {
         * This method uses the php feature to do several replacements at the same time,
         * thereby gaining some efficiency. The result is placed in the out variable
         * $result. The return value is true if something was replaced.
-        * @todo Should this be static? It doesn't seem to be used at all
+        * @deprecated since 1.25, unused
         *
         * @param array $magicarr
         * @param string $subject
@@ -664,6 +661,7 @@ class MagicWord {
         * @return bool
         */
        function replaceMultiple( $magicarr, $subject, &$result ) {
+               wfDeprecated( __METHOD__, '1.25' );
                $search = array();
                $replace = array();
                foreach ( $magicarr as $id => $replacement ) {
index 53b4d20..d94443b 100644 (file)
@@ -157,8 +157,6 @@ class MediaWiki {
        private function performRequest() {
                global $wgTitle;
 
-               wfProfileIn( __METHOD__ );
-
                $request = $this->context->getRequest();
                $requestTitle = $title = $this->context->getTitle();
                $output = $this->context->getOutput();
@@ -176,7 +174,6 @@ class MediaWiki {
                        || $title->isSpecial( 'Badtitle' )
                ) {
                        $this->context->setTitle( SpecialPage::getTitleFor( 'Badtitle' ) );
-                       wfProfileOut( __METHOD__ );
                        throw new BadTitleError();
                }
 
@@ -201,7 +198,6 @@ class MediaWiki {
                        $this->context->setTitle( $badTitle );
                        $wgTitle = $badTitle;
 
-                       wfProfileOut( __METHOD__ );
                        throw new PermissionsError( 'read', $permErrors );
                }
 
@@ -225,7 +221,6 @@ class MediaWiki {
                                $output->redirect( $url, 301 );
                        } else {
                                $this->context->setTitle( SpecialPage::getTitleFor( 'Badtitle' ) );
-                               wfProfileOut( __METHOD__ );
                                throw new BadTitleError();
                        }
                // Redirect loops, no title in URL, $wgUsePathInfo URLs, and URLs with a variant
@@ -283,7 +278,6 @@ class MediaWiki {
                        } elseif ( is_string( $article ) ) {
                                $output->redirect( $article );
                        } else {
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( "Shouldn't happen: MediaWiki::initializeArticle()"
                                        . " returned neither an object nor a URL" );
                        }
@@ -294,7 +288,6 @@ class MediaWiki {
                        $user->addAutopromoteOnceGroups( 'onView' );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -304,7 +297,6 @@ class MediaWiki {
         * @return mixed An Article, or a string to redirect to another URL
         */
        private function initializeArticle() {
-               wfProfileIn( __METHOD__ );
 
                $title = $this->context->getTitle();
                if ( $this->context->canUseWikiPage() ) {
@@ -322,7 +314,6 @@ class MediaWiki {
                // NS_MEDIAWIKI has no redirects.
                // It is also used for CSS/JS, so performance matters here...
                if ( $title->getNamespace() == NS_MEDIAWIKI ) {
-                       wfProfileOut( __METHOD__ );
                        return $article;
                }
 
@@ -353,7 +344,6 @@ class MediaWiki {
                                if ( is_string( $target ) ) {
                                        if ( !$this->config->get( 'DisableHardRedirects' ) ) {
                                                // we'll need to redirect
-                                               wfProfileOut( __METHOD__ );
                                                return $target;
                                        }
                                }
@@ -374,7 +364,6 @@ class MediaWiki {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $article;
        }
 
@@ -385,7 +374,6 @@ class MediaWiki {
         * @param Title $requestTitle The original title, before any redirects were applied
         */
        private function performAction( Page $page, Title $requestTitle ) {
-               wfProfileIn( __METHOD__ );
 
                $request = $this->context->getRequest();
                $output = $this->context->getOutput();
@@ -395,7 +383,6 @@ class MediaWiki {
                if ( !Hooks::run( 'MediaWikiPerformAction',
                                array( $output, $page, $title, $user, $request, $this ) )
                ) {
-                       wfProfileOut( __METHOD__ );
                        return;
                }
 
@@ -412,7 +399,6 @@ class MediaWiki {
                        }
 
                        $action->show();
-                       wfProfileOut( __METHOD__ );
                        return;
                }
 
@@ -421,7 +407,6 @@ class MediaWiki {
                        $output->showErrorPage( 'nosuchaction', 'nosuchactiontext' );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -456,7 +441,6 @@ class MediaWiki {
         * @return bool
         */
        private function checkMaxLag() {
-               wfProfileIn( __METHOD__ );
                $maxLag = $this->context->getRequest()->getVal( 'maxlag' );
                if ( !is_null( $maxLag ) ) {
                        list( $host, $lag ) = wfGetLB()->getMaxLag();
@@ -472,20 +456,15 @@ class MediaWiki {
                                        echo "Waiting for a database server: $lag seconds lagged\n";
                                }
 
-                               wfProfileOut( __METHOD__ );
-
                                exit;
                        }
                }
-               wfProfileOut( __METHOD__ );
                return true;
        }
 
        private function main() {
                global $wgTitle;
 
-               wfProfileIn( __METHOD__ );
-
                $request = $this->context->getRequest();
 
                // Send Ajax requests to the Ajax dispatcher.
@@ -497,7 +476,6 @@ class MediaWiki {
 
                        $dispatcher = new AjaxDispatcher( $this->config );
                        $dispatcher->performAction( $this->context->getUser() );
-                       wfProfileOut( __METHOD__ );
                        return;
                }
 
@@ -550,13 +528,11 @@ class MediaWiki {
                                $output->addVaryHeader( 'X-Forwarded-Proto' );
                                $output->redirect( $redirUrl );
                                $output->output();
-                               wfProfileOut( __METHOD__ );
                                return;
                        }
                }
 
                if ( $this->config->get( 'UseFileCache' ) && $title->getNamespace() >= 0 ) {
-                       wfProfileIn( 'main-try-filecache' );
                        if ( HTMLFileCache::useFileCache( $this->context ) ) {
                                // Try low-level file cache hit
                                $cache = new HTMLFileCache( $title, $action );
@@ -571,12 +547,9 @@ class MediaWiki {
                                        $this->context->getWikiPage()->doViewUpdates( $this->context->getUser() );
                                        // Tell OutputPage that output is taken care of
                                        $this->context->getOutput()->disable();
-                                       wfProfileOut( 'main-try-filecache' );
-                                       wfProfileOut( __METHOD__ );
                                        return;
                                }
                        }
-                       wfProfileOut( 'main-try-filecache' );
                }
 
                // Actually do the work of the request and build up any output
@@ -592,7 +565,6 @@ class MediaWiki {
                // Output everything!
                $this->context->getOutput()->output();
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -626,8 +598,6 @@ class MediaWiki {
                        return; // recursion guard
                }
 
-               $section = new ProfileSection( __METHOD__ );
-
                if ( $jobRunRate < 1 ) {
                        $max = mt_getrandmax();
                        if ( mt_rand( 0, $max ) > $max * $jobRunRate ) {
index e3b4dbe..6f7e8e5 100644 (file)
@@ -56,9 +56,7 @@ class MessageBlobStore {
         * @return array An array mapping module names to message blobs
         */
        public function get( ResourceLoader $resourceLoader, $modules, $lang ) {
-               wfProfileIn( __METHOD__ );
                if ( !count( $modules ) ) {
-                       wfProfileOut( __METHOD__ );
                        return array();
                }
                // Try getting from the DB first
@@ -73,7 +71,6 @@ class MessageBlobStore {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $blobs;
        }
 
index f8d5ab7..4e14b7b 100644 (file)
@@ -1685,8 +1685,6 @@ class OutputPage extends ContextSource {
        ) {
                global $wgParser;
 
-               wfProfileIn( __METHOD__ );
-
                $popts = $this->parserOptions();
                $oldTidy = $popts->setTidy( $tidy );
                $popts->setInterfaceMessage( (bool)$interface );
@@ -1700,7 +1698,6 @@ class OutputPage extends ContextSource {
 
                $this->addParserOutput( $parserOutput );
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -2173,8 +2170,6 @@ class OutputPage extends ContextSource {
                        return;
                }
 
-               wfProfileIn( __METHOD__ );
-
                $response = $this->getRequest()->response();
                $config = $this->getConfig();
 
@@ -2209,7 +2204,6 @@ class OutputPage extends ContextSource {
                                }
                        }
 
-                       wfProfileOut( __METHOD__ );
                        return;
                } elseif ( $this->mStatusCode ) {
                        $message = HttpStatus::getMessage( $this->mStatusCode );
@@ -2264,9 +2258,7 @@ class OutputPage extends ContextSource {
                        // adding of CSS or Javascript by extensions.
                        Hooks::run( 'BeforePageDisplay', array( &$this, &$sk ) );
 
-                       wfProfileIn( 'Output-skin' );
                        $sk->outputPage();
-                       wfProfileOut( 'Output-skin' );
                }
 
                // This hook allows last minute changes to final overall output by modifying output buffer
@@ -2276,7 +2268,6 @@ class OutputPage extends ContextSource {
 
                ob_end_flush();
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -2626,8 +2617,6 @@ class OutputPage extends ContextSource {
        public function headElement( Skin $sk, $includeStyle = true ) {
                global $wgContLang;
 
-               $section = new ProfileSection( __METHOD__ );
-
                $userdir = $this->getLanguage()->getDir();
                $sitedir = $wgContLang->getDir();
 
index aca6dcb..9e0a255 100644 (file)
@@ -243,10 +243,9 @@ class Preferences {
                        'type' => 'info',
                        'label' => $context->msg( 'prefs-memberingroups' )->numParams(
                                count( $userGroups ) )->params( $userName )->parse(),
-                       'default' => $context->msg( 'prefs-memberingroups-type',
-                               $lang->commaList( $userGroups ),
-                               $lang->commaList( $userMembers )
-                       )->plain(),
+                       'default' => $context->msg( 'prefs-memberingroups-type' )
+                               ->rawParams( $lang->commaList( $userGroups ), $lang->commaList( $userMembers ) )
+                               ->escaped(),
                        'raw' => true,
                        'section' => 'personal/info',
                );
@@ -338,11 +337,11 @@ class Preferences {
                        'type' => 'radio',
                        'section' => 'personal/i18n',
                        'options' => array(
-                               $context->msg( 'parentheses',
-                                       $context->msg( 'gender-unknown' )->text()
-                               )->text() => 'unknown',
-                               $context->msg( 'gender-female' )->text() => 'female',
-                               $context->msg( 'gender-male' )->text() => 'male',
+                               $context->msg( 'parentheses' )
+                                       ->params( $context->msg( 'gender-unknown' )->plain() )
+                                       ->escaped() => 'unknown',
+                               $context->msg( 'gender-female' )->escaped() => 'female',
+                               $context->msg( 'gender-male' )->escaped() => 'male',
                        ),
                        'label-message' => 'yourgender',
                        'help-message' => 'prefs-help-gender',
@@ -450,8 +449,8 @@ class Preferences {
                                                array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ) );
 
                                        $emailAddress .= $emailAddress == '' ? $link : (
-                                               $context->msg( 'word-separator' )->plain()
-                                               . $context->msg( 'parentheses' )->rawParams( $link )->plain()
+                                               $context->msg( 'word-separator' )->escaped()
+                                               . $context->msg( 'parentheses' )->rawParams( $link )->escaped()
                                        );
                                }
 
@@ -869,7 +868,7 @@ class Preferences {
                        'min' => 1,
                        'max' => ceil( $rcMaxAge / ( 3600 * 24 ) ),
                        'help' => $context->msg( 'recentchangesdays-max' )->numParams(
-                               ceil( $rcMaxAge / ( 3600 * 24 ) ) )->text()
+                               ceil( $rcMaxAge / ( 3600 * 24 ) ) )->escaped()
                );
                $defaultPreferences['rclimit'] = array(
                        'type' => 'int',
@@ -926,7 +925,7 @@ class Preferences {
                        'max' => $watchlistdaysMax,
                        'section' => 'watchlist/displaywatchlist',
                        'help' => $context->msg( 'prefs-watchlist-days-max' )->numParams(
-                               $watchlistdaysMax )->text(),
+                               $watchlistdaysMax )->escaped(),
                        'label-message' => 'prefs-watchlist-days',
                );
                $defaultPreferences['wllimit'] = array(
@@ -1046,7 +1045,7 @@ class Preferences {
                $ret = array();
 
                $mptitle = Title::newMainPage();
-               $previewtext = $context->msg( 'skin-preview' )->text();
+               $previewtext = $context->msg( 'skin-preview' )->escaped();
 
                # Only show skins that aren't disabled in $wgSkipSkins
                $validSkinNames = Skin::getAllowedSkins();
@@ -1091,10 +1090,9 @@ class Preferences {
                                $linkTools[] = Linker::link( $jsPage, $context->msg( 'prefs-custom-js' )->escaped() );
                        }
 
-                       $display = $sn . ' ' . $context->msg(
-                               'parentheses',
-                               $context->getLanguage()->pipeList( $linkTools )
-                       )->text();
+                       $display = $sn . ' ' . $context->msg( 'parentheses' )
+                               ->rawParams( $context->getLanguage()->pipeList( $linkTools ) )
+                               ->escaped();
                        $ret[$display] = $skinkey;
                }
 
index caa3ef5..2885679 100644 (file)
@@ -95,7 +95,6 @@ abstract class PrefixSearch {
         * @return array
         */
        public function searchWithVariants( $search, $limit, array $namespaces, $offset = 0 ) {
-               wfProfileIn( __METHOD__ );
                $searches = $this->search( $search, $limit, $namespaces, $offset );
 
                // if the content language has variants, try to retrieve fallback results
@@ -116,7 +115,6 @@ abstract class PrefixSearch {
                                }
                        }
                }
-               wfProfileOut( __METHOD__ );
                return $searches;
        }
 
index 8ba79df..c8015e6 100644 (file)
@@ -515,7 +515,6 @@ class Revision implements IDBAccessObject {
                if ( !$revIds ) {
                        return $revLens; // empty
                }
-               wfProfileIn( __METHOD__ );
                $res = $db->select( 'revision',
                        array( 'rev_id', 'rev_len' ),
                        array( 'rev_id' => $revIds ),
@@ -523,7 +522,6 @@ class Revision implements IDBAccessObject {
                foreach ( $res as $row ) {
                        $revLens[$row->rev_id] = $row->rev_len;
                }
-               wfProfileOut( __METHOD__ );
                return $revLens;
        }
 
@@ -1213,7 +1211,6 @@ class Revision implements IDBAccessObject {
         * @return string Text the text requested or false on failure
         */
        public static function getRevisionText( $row, $prefix = 'old_', $wiki = false ) {
-               wfProfileIn( __METHOD__ );
 
                # Get data
                $textField = $prefix . 'text';
@@ -1228,7 +1225,6 @@ class Revision implements IDBAccessObject {
                if ( isset( $row->$textField ) ) {
                        $text = $row->$textField;
                } else {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -1237,7 +1233,6 @@ class Revision implements IDBAccessObject {
                        $url = $text;
                        $parts = explode( '://', $url, 2 );
                        if ( count( $parts ) == 1 || $parts[1] == '' ) {
-                               wfProfileOut( __METHOD__ );
                                return false;
                        }
                        $text = ExternalStore::fetchFromURL( $url, array( 'wiki' => $wiki ) );
@@ -1247,7 +1242,6 @@ class Revision implements IDBAccessObject {
                if ( $text !== false ) {
                        $text = self::decompressRevisionText( $text, $flags );
                }
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -1331,8 +1325,6 @@ class Revision implements IDBAccessObject {
        public function insertOn( $dbw ) {
                global $wgDefaultExternalStore, $wgContentHandlerUseDB;
 
-               wfProfileIn( __METHOD__ );
-
                $this->checkContentModel();
 
                $data = $this->mText;
@@ -1343,7 +1335,6 @@ class Revision implements IDBAccessObject {
                        // Store and get the URL
                        $data = ExternalStore::insertToDefault( $data );
                        if ( !$data ) {
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( "Unable to store text to external storage" );
                        }
                        if ( $flags ) {
@@ -1403,7 +1394,6 @@ class Revision implements IDBAccessObject {
                        $title = $this->getTitle();
 
                        if ( $title === null ) {
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( "Insufficient information to determine the title of the "
                                        . "revision's page!" );
                        }
@@ -1421,7 +1411,6 @@ class Revision implements IDBAccessObject {
 
                Hooks::run( 'RevisionInsertComplete', array( &$this, $data, $flags ) );
 
-               wfProfileOut( __METHOD__ );
                return $this->mId;
        }
 
@@ -1490,7 +1479,6 @@ class Revision implements IDBAccessObject {
         * @return string|bool The revision's text, or false on failure
         */
        protected function loadText() {
-               wfProfileIn( __METHOD__ );
 
                // Caching may be beneficial for massive use of external storage
                global $wgRevisionCacheExpiry, $wgMemc;
@@ -1500,7 +1488,6 @@ class Revision implements IDBAccessObject {
                        $text = $wgMemc->get( $key );
                        if ( is_string( $text ) ) {
                                wfDebug( __METHOD__ . ": got id $textId from cache\n" );
-                               wfProfileOut( __METHOD__ );
                                return $text;
                        }
                }
@@ -1548,8 +1535,6 @@ class Revision implements IDBAccessObject {
                        $wgMemc->set( $key, $text, $wgRevisionCacheExpiry );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $text;
        }
 
@@ -1571,8 +1556,6 @@ class Revision implements IDBAccessObject {
        public static function newNullRevision( $dbw, $pageId, $summary, $minor, $user = null ) {
                global $wgContentHandlerUseDB;
 
-               wfProfileIn( __METHOD__ );
-
                $fields = array( 'page_latest', 'page_namespace', 'page_title',
                                                'rev_text_id', 'rev_len', 'rev_sha1' );
 
@@ -1619,7 +1602,6 @@ class Revision implements IDBAccessObject {
                        $revision = null;
                }
 
-               wfProfileOut( __METHOD__ );
                return $revision;
        }
 
index d35bbec..6942ac0 100644 (file)
@@ -372,8 +372,6 @@ class Sanitizer {
                static $htmlpairsStatic, $htmlsingle, $htmlsingleonly, $htmlnest, $tabletags,
                        $htmllist, $listtags, $htmlsingleallowed, $htmlelementsStatic, $staticInitialised;
 
-               wfProfileIn( __METHOD__ );
-
                // Base our staticInitialised variable off of the global config state so that if the globals
                // are changed (like in the screwed up test system) we will re-initialise the settings.
                $globalContext = implode( '-', compact( 'wgAllowMicrodataAttributes', 'wgAllowImageTag' ) );
@@ -600,7 +598,6 @@ class Sanitizer {
                                $text .= '&lt;' . str_replace( '>', '&gt;', $x );
                        }
                }
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -615,7 +612,6 @@ class Sanitizer {
         * @return string
         */
        static function removeHTMLcomments( $text ) {
-               wfProfileIn( __METHOD__ );
                while ( ( $start = strpos( $text, '<!--' ) ) !== false ) {
                        $end = strpos( $text, '-->', $start + 4 );
                        if ( $end === false ) {
@@ -646,7 +642,6 @@ class Sanitizer {
                                $text = substr_replace( $text, '', $start, $end - $start );
                        }
                }
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
index 535b13d..c75429e 100644 (file)
@@ -33,8 +33,10 @@ if ( !defined( 'MEDIAWIKI' ) ) {
 }
 
 $fname = 'Setup.php';
-wfProfileIn( $fname );
-wfProfileIn( $fname . '-defaults' );
+$ps_setup = Profiler::instance()->scopedProfileIn( $fname );
+
+// If any extensions are still queued, force load them
+ExtensionRegistry::getInstance()->loadFromQueue();
 
 // Check to see if we are at the file scope
 if ( !isset( $wgVersion ) ) {
@@ -43,6 +45,7 @@ if ( !isset( $wgVersion ) ) {
 }
 
 // Set various default paths sensibly...
+$ps_default = Profiler::instance()->scopedProfileIn( $fname . '-defaults' );
 
 if ( $wgScript === false ) {
        $wgScript = "$wgScriptPath/index$wgScriptExtension";
@@ -458,32 +461,25 @@ if ( $wgProfileOnly ) {
        $wgDebugLogFile = '';
 }
 
-wfProfileOut( $fname . '-defaults' );
+Profiler::instance()->scopedProfileOut( $ps_default );
 
 // Disable MWDebug for command line mode, this prevents MWDebug from eating up
 // all the memory from logging SQL queries on maintenance scripts
 global $wgCommandLineMode;
 if ( $wgDebugToolbar && !$wgCommandLineMode ) {
-       wfProfileIn( $fname . '-debugtoolbar' );
        MWDebug::init();
-       wfProfileOut( $fname . '-debugtoolbar' );
 }
 
 if ( !class_exists( 'AutoLoader' ) ) {
        require_once "$IP/includes/AutoLoader.php";
 }
 
-wfProfileIn( $fname . '-exception' );
 MWExceptionHandler::installHandler();
-wfProfileOut( $fname . '-exception' );
 
-wfProfileIn( $fname . '-includes' );
 require_once "$IP/includes/normal/UtfNormalUtil.php";
-require_once "$IP/includes/GlobalFunctions.php";
 require_once "$IP/includes/normal/UtfNormalDefines.php";
-wfProfileOut( $fname . '-includes' );
 
-wfProfileIn( $fname . '-defaults2' );
+$ps_default2 = Profiler::instance()->scopedProfileIn( $fname . '-defaults2' );
 
 if ( $wgCanonicalServer === false ) {
        $wgCanonicalServer = wfExpandUrl( $wgServer, PROTO_HTTP );
@@ -514,20 +510,20 @@ if ( $wgSecureLogin && substr( $wgServer, 0, 2 ) !== '//' ) {
                . 'HTTP or HTTPS. Disabling secure login.' );
 }
 
-// Now that GlobalFunctions is loaded, set defaults that depend
-// on it.
+// Now that GlobalFunctions is loaded, set defaults that depend on it.
 if ( $wgTmpDirectory === false ) {
-       wfProfileIn( $fname . '-tempDir' );
+       $ps_tmpdir = Profiler::instance()->scopedProfileIn( $fname . '-tempDir' );
        $wgTmpDirectory = wfTempDir();
-       wfProfileOut( $fname . '-tempDir' );
+       Profiler::instance()->scopedProfileOut( $ps_tmpdir );
 }
 
 // We don't use counters anymore. Left here for extensions still
 // expecting this to exist. Should be removed sometime 1.26 or later.
 $wgDisableCounters = true;
 
-wfProfileOut( $fname . '-defaults2' );
-wfProfileIn( $fname . '-misc1' );
+Profiler::instance()->scopedProfileOut( $ps_default2 );
+
+$ps_misc = Profiler::instance()->scopedProfileIn( $fname . '-misc1' );
 
 // Raise the memory limit if it's too low
 wfMemoryLimit();
@@ -569,8 +565,8 @@ if ( $wgCommandLineMode ) {
        wfDebug( $debug );
 }
 
-wfProfileOut( $fname . '-misc1' );
-wfProfileIn( $fname . '-memcached' );
+Profiler::instance()->scopedProfileOut( $ps_misc );
+$ps_memcached = Profiler::instance()->scopedProfileIn( $fname . '-memcached' );
 
 $wgMemc = wfGetMainCache();
 $messageMemc = wfGetMessageCacheStorage();
@@ -581,12 +577,12 @@ wfDebugLog( 'caches', 'main: ' . get_class( $wgMemc ) .
        ', message: ' . get_class( $messageMemc ) .
        ', parser: ' . get_class( $parserMemc ) );
 
-wfProfileOut( $fname . '-memcached' );
+Profiler::instance()->scopedProfileOut( $ps_memcached );
 
 // Most of the config is out, some might want to run hooks here.
 Hooks::run( 'SetupAfterCache' );
 
-wfProfileIn( $fname . '-session' );
+$ps_session = Profiler::instance()->scopedProfileIn( $fname . '-session' );
 
 if ( !defined( 'MW_NO_SESSION' ) && !$wgCommandLineMode ) {
        // If session.auto_start is there, we can't touch session name
@@ -599,8 +595,8 @@ if ( !defined( 'MW_NO_SESSION' ) && !$wgCommandLineMode ) {
        }
 }
 
-wfProfileOut( $fname . '-session' );
-wfProfileIn( $fname . '-globals' );
+Profiler::instance()->scopedProfileOut( $ps_session );
+$ps_globals = Profiler::instance()->scopedProfileIn( $fname . '-globals' );
 
 /**
  * @var Language $wgContLang
@@ -648,8 +644,8 @@ $wgTitle = null;
  */
 $wgDeferredUpdateList = array();
 
-wfProfileOut( $fname . '-globals' );
-wfProfileIn( $fname . '-extensions' );
+Profiler::instance()->scopedProfileOut( $ps_globals );
+$ps_extensions = Profiler::instance()->scopedProfileIn( $fname . '-extensions' );
 
 // Extension setup functions for extensions other than skins
 // Entries should be added to this variable during the inclusion
@@ -669,13 +665,14 @@ foreach ( $wgExtensionFunctions as $func ) {
                $profName = $fname . '-extensions-' . strval( $func );
        }
 
-       wfProfileIn( $profName );
+       $ps_ext_func = Profiler::instance()->scopedProfileIn( $profName );
        call_user_func( $func );
-       wfProfileOut( $profName );
+       Profiler::instance()->scopedProfileOut( $ps_ext_func );
 }
 
 wfDebug( "Fully initialised\n" );
 $wgFullyInitialised = true;
 
-wfProfileOut( $fname . '-extensions' );
-wfProfileOut( $fname );
+Profiler::instance()->scopedProfileOut( $ps_extensions );
+Profiler::instance()->scopedProfileOut( $ps_setup );
+
index 32c6761..15c18f3 100644 (file)
@@ -221,7 +221,6 @@ class SiteStats {
         * @return int
         */
        static function pagesInNs( $ns ) {
-               wfProfileIn( __METHOD__ );
                if ( !isset( self::$pageCount[$ns] ) ) {
                        $dbr = wfGetDB( DB_SLAVE );
                        self::$pageCount[$ns] = (int)$dbr->selectField(
@@ -231,7 +230,6 @@ class SiteStats {
                                __METHOD__
                        );
                }
-               wfProfileOut( __METHOD__ );
                return self::$pageCount[$ns];
        }
 
index 2503150..a52b25b 100644 (file)
@@ -39,10 +39,8 @@ class StreamFile {
         * @return bool Success
         */
        public static function stream( $fname, $headers = array(), $sendErrors = true ) {
-               wfProfileIn( __METHOD__ );
 
                if ( FileBackend::isStoragePath( $fname ) ) { // sanity
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( __FUNCTION__ . " given storage path '$fname'." );
                }
 
@@ -54,14 +52,11 @@ class StreamFile {
                if ( $res == self::NOT_MODIFIED ) {
                        $ok = true; // use client cache
                } elseif ( $res == self::READY_STREAM ) {
-                       wfProfileIn( __METHOD__ . '-send' );
                        $ok = readfile( $fname );
-                       wfProfileOut( __METHOD__ . '-send' );
                } else {
                        $ok = false; // failed
                }
 
-               wfProfileOut( __METHOD__ );
                return $ok;
        }
 
index adca862..2dfcdc2 100644 (file)
@@ -150,10 +150,8 @@ class StubObject {
 
                if ( get_class( $GLOBALS[$this->global] ) != $this->class ) {
                        $fname = __METHOD__ . '-' . $this->global;
-                       wfProfileIn( $fname );
                        $caller = wfGetCaller( $level );
                        if ( ++$recursionLevel > 2 ) {
-                               wfProfileOut( $fname );
                                throw new MWException( "Unstub loop detected on call of "
                                        . "\${$this->global}->$name from $caller\n" );
                        }
@@ -161,7 +159,6 @@ class StubObject {
                                . "\${$this->global}::$name from $caller\n" );
                        $GLOBALS[$this->global] = $this->_newObject();
                        --$recursionLevel;
-                       wfProfileOut( $fname );
                        return $GLOBALS[$this->global];
                }
        }
index 24f4331..0cac64a 100644 (file)
@@ -1782,7 +1782,6 @@ class Title {
         * @return string The URL
         */
        public function getLinkURL( $query = '', $query2 = false, $proto = PROTO_RELATIVE ) {
-               wfProfileIn( __METHOD__ );
                if ( $this->isExternal() || $proto !== PROTO_RELATIVE ) {
                        $ret = $this->getFullURL( $query, $query2, $proto );
                } elseif ( $this->getPrefixedText() === '' && $this->hasFragment() ) {
@@ -1790,7 +1789,6 @@ class Title {
                } else {
                        $ret = $this->getLocalURL( $query, $query2 ) . $this->getFragmentForURL();
                }
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -2444,7 +2442,6 @@ class Title {
        protected function getUserPermissionsErrorsInternal( $action, $user,
                $doExpensiveQueries = true, $short = false
        ) {
-               wfProfileIn( __METHOD__ );
 
                # Read has special handling
                if ( $action == 'read' ) {
@@ -2485,7 +2482,6 @@ class Title {
                        $errors = $this->$method( $action, $user, $errors, $doExpensiveQueries, $short );
                }
 
-               wfProfileOut( __METHOD__ );
                return $errors;
        }
 
@@ -2721,8 +2717,6 @@ class Title {
                        return array( $this->mHasCascadingRestrictions, $pagerestrictions );
                }
 
-               wfProfileIn( __METHOD__ );
-
                $dbr = wfGetDB( DB_SLAVE );
 
                if ( $this->getNamespace() == NS_FILE ) {
@@ -2797,7 +2791,6 @@ class Title {
                        $this->mHasCascadingRestrictions = $sources;
                }
 
-               wfProfileOut( __METHOD__ );
                return array( $sources, $pagerestrictions );
        }
 
@@ -4623,16 +4616,13 @@ class Title {
         */
        public function getPageLanguage() {
                global $wgLang, $wgLanguageCode;
-               wfProfileIn( __METHOD__ );
                if ( $this->isSpecialPage() ) {
                        // special pages are in the user language
-                       wfProfileOut( __METHOD__ );
                        return $wgLang;
                }
 
                // Checking if DB language is set
                if ( $this->mDbPageLanguage ) {
-                       wfProfileOut( __METHOD__ );
                        return wfGetLangObj( $this->mDbPageLanguage );
                }
 
@@ -4650,7 +4640,6 @@ class Title {
                        $langObj = wfGetLangObj( $this->mPageLanguage[0] );
                }
 
-               wfProfileOut( __METHOD__ );
                return $langObj;
        }
 
index 88004dc..7ca7d80 100644 (file)
@@ -324,7 +324,6 @@ class User implements IDBAccessObject {
                if ( $this->mLoadedItems === true ) {
                        return;
                }
-               wfProfileIn( __METHOD__ );
 
                // Set it now to avoid infinite recursion in accessors
                $this->mLoadedItems = true;
@@ -353,10 +352,8 @@ class User implements IDBAccessObject {
                                Hooks::run( 'UserLoadAfterLoadFromSession', array( $this ) );
                                break;
                        default:
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( "Unrecognised value for User->mFrom: \"{$this->mFrom}\"" );
                }
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -1019,7 +1016,6 @@ class User implements IDBAccessObject {
         * @param string|bool $name
         */
        public function loadDefaults( $name = false ) {
-               wfProfileIn( __METHOD__ );
 
                $passwordFactory = self::getPasswordFactory();
 
@@ -1051,7 +1047,6 @@ class User implements IDBAccessObject {
 
                Hooks::run( 'UserLoadDefaults', array( $this, $name ) );
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -1489,7 +1484,6 @@ class User implements IDBAccessObject {
                        return;
                }
 
-               wfProfileIn( __METHOD__ );
                wfDebug( __METHOD__ . ": checking...\n" );
 
                // Initialize data...
@@ -1564,7 +1558,6 @@ class User implements IDBAccessObject {
                // Extensions
                Hooks::run( 'GetBlockedStatus', array( &$this ) );
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -1596,7 +1589,6 @@ class User implements IDBAccessObject {
         * @return bool True if blacklisted.
         */
        public function inDnsBlacklist( $ip, $bases ) {
-               wfProfileIn( __METHOD__ );
 
                $found = false;
                // @todo FIXME: IPv6 ???  (http://bugs.php.net/bug.php?id=33170)
@@ -1631,7 +1623,6 @@ class User implements IDBAccessObject {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $found;
        }
 
@@ -1648,7 +1639,6 @@ class User implements IDBAccessObject {
                if ( !$wgProxyList ) {
                        return false;
                }
-               wfProfileIn( __METHOD__ );
 
                if ( !is_array( $wgProxyList ) ) {
                        // Load from the specified file
@@ -1665,7 +1655,6 @@ class User implements IDBAccessObject {
                } else {
                        $ret = false;
                }
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -1717,8 +1706,6 @@ class User implements IDBAccessObject {
                }
 
                global $wgMemc;
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-' . $action );
 
                $limits = $wgRateLimits[$action];
                $keys = array();
@@ -1799,8 +1786,6 @@ class User implements IDBAccessObject {
                        }
                }
 
-               wfProfileOut( __METHOD__ . '-' . $action );
-               wfProfileOut( __METHOD__ );
                return $triggered;
        }
 
@@ -1835,7 +1820,6 @@ class User implements IDBAccessObject {
         */
        public function isBlockedFrom( $title, $bFromSlave = false ) {
                global $wgBlockAllowsUTEdit;
-               wfProfileIn( __METHOD__ );
 
                $blocked = $this->isBlocked( $bFromSlave );
                $allowUsertalk = ( $wgBlockAllowsUTEdit ? $this->mAllowUsertalk : false );
@@ -1848,7 +1832,6 @@ class User implements IDBAccessObject {
 
                Hooks::run( 'UserIsBlockedFrom', array( $this, $title, &$blocked, &$allowUsertalk ) );
 
-               wfProfileOut( __METHOD__ );
                return $blocked;
        }
 
@@ -2930,7 +2913,6 @@ class User implements IDBAccessObject {
         */
        public function getEffectiveGroups( $recache = false ) {
                if ( $recache || is_null( $this->mEffectiveGroups ) ) {
-                       wfProfileIn( __METHOD__ );
                        $this->mEffectiveGroups = array_unique( array_merge(
                                $this->getGroups(), // explicit groups
                                $this->getAutomaticGroups( $recache ) // implicit groups
@@ -2939,7 +2921,6 @@ class User implements IDBAccessObject {
                        Hooks::run( 'UserEffectiveGroups', array( &$this, &$this->mEffectiveGroups ) );
                        // Force reindexation of groups when a hook has unset one of them
                        $this->mEffectiveGroups = array_values( array_unique( $this->mEffectiveGroups ) );
-                       wfProfileOut( __METHOD__ );
                }
                return $this->mEffectiveGroups;
        }
@@ -2953,7 +2934,6 @@ class User implements IDBAccessObject {
         */
        public function getAutomaticGroups( $recache = false ) {
                if ( $recache || is_null( $this->mImplicitGroups ) ) {
-                       wfProfileIn( __METHOD__ );
                        $this->mImplicitGroups = array( '*' );
                        if ( $this->getId() ) {
                                $this->mImplicitGroups[] = 'user';
@@ -2968,7 +2948,6 @@ class User implements IDBAccessObject {
                                // as getEffectiveGroups() depends on this function
                                $this->mEffectiveGroups = null;
                        }
-                       wfProfileOut( __METHOD__ );
                }
                return $this->mImplicitGroups;
        }
@@ -3008,7 +2987,6 @@ class User implements IDBAccessObject {
 
                if ( $this->mEditCount === null ) {
                        /* Populate the count, if it has not been populated yet */
-                       wfProfileIn( __METHOD__ );
                        $dbr = wfGetDB( DB_SLAVE );
                        // check if the user_editcount field has been initialized
                        $count = $dbr->selectField(
@@ -3022,7 +3000,6 @@ class User implements IDBAccessObject {
                                $count = $this->initEditCount();
                        }
                        $this->mEditCount = $count;
-                       wfProfileOut( __METHOD__ );
                }
                return (int)$this->mEditCount;
        }
@@ -3815,8 +3792,6 @@ class User implements IDBAccessObject {
        public function checkPassword( $password ) {
                global $wgAuth, $wgLegacyEncoding;
 
-               $section = new ProfileSection( __METHOD__ );
-
                $this->loadPasswords();
 
                // Certain authentication plugins do NOT want to save
index fbd6119..4d22692 100644 (file)
@@ -275,7 +275,6 @@ class WatchedItem {
         * @return bool
         */
        public static function batchAddWatch( array $items ) {
-               $section = new ProfileSection( __METHOD__ );
 
                if ( wfReadOnly() ) {
                        return false;
@@ -331,11 +330,9 @@ class WatchedItem {
         * @return bool
         */
        public function removeWatch() {
-               wfProfileIn( __METHOD__ );
 
                // Only loggedin user can have a watchlist
                if ( wfReadOnly() || $this->mUser->isAnon() || !$this->isAllowed( 'editmywatchlist' ) ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -370,7 +367,6 @@ class WatchedItem {
 
                $this->watched = false;
 
-               wfProfileOut( __METHOD__ );
                return $success;
        }
 
index 217ba3f..125e544 100644 (file)
@@ -74,11 +74,13 @@ if ( file_exists( "$IP/StartProfiler.php" ) ) {
        require "$IP/StartProfiler.php";
 }
 
-wfProfileIn( 'WebStart.php-conf' );
 
 # Load default settings
 require_once "$IP/includes/DefaultSettings.php";
 
+# Load global functions
+require_once "$IP/includes/GlobalFunctions.php";
+
 # Load composer's autoloader if present
 if ( is_readable( "$IP/vendor/autoload.php" ) ) {
        require_once "$IP/vendor/autoload.php";
@@ -104,9 +106,7 @@ if ( defined( 'MW_CONFIG_CALLBACK' ) ) {
        require_once MW_CONFIG_FILE;
 }
 
-wfProfileOut( 'WebStart.php-conf' );
 
-wfProfileIn( 'WebStart.php-ob_start' );
 # Initialise output buffering
 # Check that there is no previous output or previously set up buffers, because
 # that would cause us to potentially mix gzip and non-gzip output, creating a
@@ -115,7 +115,6 @@ if ( ob_get_level() == 0 ) {
        require_once "$IP/includes/OutputHandler.php";
        ob_start( 'wfOutputHandler' );
 }
-wfProfileOut( 'WebStart.php-ob_start' );
 
 if ( !defined( 'MW_NO_SETUP' ) ) {
        require_once "$IP/includes/Setup.php";
index c07ac73..78b8715 100644 (file)
@@ -94,9 +94,7 @@ class Xml {
                        $attribs = array_map( array( 'UtfNormal', 'cleanUp' ), $attribs );
                }
                if ( $contents ) {
-                       wfProfileIn( __METHOD__ . '-norm' );
                        $contents = $wgContLang->normalize( $contents );
-                       wfProfileOut( __METHOD__ . '-norm' );
                }
                return self::element( $element, $attribs, $contents );
        }
index e064aab..c19e8fa 100644 (file)
@@ -42,7 +42,6 @@ class CreditsAction extends FormlessAction {
         * @return string HTML
         */
        public function onView() {
-               wfProfileIn( __METHOD__ );
 
                if ( $this->page->getID() == 0 ) {
                        $s = $this->msg( 'nocredits' )->parse();
@@ -50,8 +49,6 @@ class CreditsAction extends FormlessAction {
                        $s = $this->getCredits( -1 );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return Html::rawElement( 'div', array( 'id' => 'mw-credits' ), $s );
        }
 
@@ -63,7 +60,6 @@ class CreditsAction extends FormlessAction {
         * @return string Html
         */
        public function getCredits( $cnt, $showIfMax = true ) {
-               wfProfileIn( __METHOD__ );
                $s = '';
 
                if ( $cnt != 0 ) {
@@ -73,8 +69,6 @@ class CreditsAction extends FormlessAction {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $s;
        }
 
index 6ee5d2c..1e2f889 100644 (file)
@@ -102,8 +102,6 @@ class HistoryAction extends FormlessAction {
                        return; // Client cache fresh and headers sent, nothing more to do.
                }
 
-               wfProfileIn( __METHOD__ );
-
                $this->preCacheMessages();
                $config = $this->context->getConfig();
 
@@ -131,7 +129,6 @@ class HistoryAction extends FormlessAction {
                $feedType = $request->getVal( 'feed' );
                if ( $feedType ) {
                        $this->feed( $feedType );
-                       wfProfileOut( __METHOD__ );
 
                        return;
                }
@@ -151,7 +148,6 @@ class HistoryAction extends FormlessAction {
                                        'msgKey' => array( 'moveddeleted-notice' )
                                )
                        );
-                       wfProfileOut( __METHOD__ );
 
                        return;
                }
@@ -215,7 +211,6 @@ class HistoryAction extends FormlessAction {
                );
                $out->preventClickjacking( $pager->getPreventClickjacking() );
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
index 686f63d..9e4a150 100644 (file)
@@ -634,7 +634,6 @@ class InfoAction extends FormlessAction {
         * @return array
         */
        protected function pageCounts( Title $title ) {
-               wfProfileIn( __METHOD__ );
                $id = $title->getArticleID();
                $config = $this->context->getConfig();
 
@@ -747,8 +746,6 @@ class InfoAction extends FormlessAction {
                        __METHOD__
                );
 
-               wfProfileOut( __METHOD__ );
-
                return $result;
        }
 
index e2e5a1d..0a8628d 100644 (file)
@@ -36,9 +36,7 @@ class UnwatchAction extends WatchAction {
        }
 
        public function onSubmit( $data ) {
-               wfProfileIn( __METHOD__ );
                self::doUnwatch( $this->getTitle(), $this->getUser() );
-               wfProfileOut( __METHOD__ );
 
                return true;
        }
index f333efb..9647340 100644 (file)
@@ -48,9 +48,7 @@ class WatchAction extends FormAction {
        }
 
        public function onSubmit( $data ) {
-               wfProfileIn( __METHOD__ );
                self::doWatch( $this->getTitle(), $this->getUser() );
-               wfProfileOut( __METHOD__ );
 
                return true;
        }
index 87c88fb..3a31b2a 100644 (file)
@@ -2181,6 +2181,10 @@ abstract class ApiBase extends ContextSource {
         * Profiling: total module execution time
         */
        private $mTimeIn = 0, $mModuleTime = 0;
+       /** @var ScopedCallback */
+       private $profile;
+       /** @var ScopedCallback */
+       private $dbProfile;
 
        /**
         * Get the name of the module as shown in the profiler log
@@ -2205,7 +2209,7 @@ abstract class ApiBase extends ContextSource {
                        ApiBase::dieDebug( __METHOD__, 'Called twice without calling profileOut()' );
                }
                $this->mTimeIn = microtime( true );
-               wfProfileIn( $this->getModuleProfileName() );
+               $this->profile = Profiler::instance()->scopedProfileIn( $this->getModuleProfileName() );
        }
 
        /**
@@ -2224,7 +2228,7 @@ abstract class ApiBase extends ContextSource {
 
                $this->mModuleTime += microtime( true ) - $this->mTimeIn;
                $this->mTimeIn = 0;
-               wfProfileOut( $this->getModuleProfileName() );
+               Profiler::instance()->scopedProfileOut( $this->profile );
        }
 
        /**
@@ -2271,7 +2275,8 @@ abstract class ApiBase extends ContextSource {
                        ApiBase::dieDebug( __METHOD__, 'Called twice without calling profileDBOut()' );
                }
                $this->mDBTimeIn = microtime( true );
-               wfProfileIn( $this->getModuleProfileName( true ) );
+
+               $this->dbProfile = Profiler::instance()->scopedProfileIn( $this->getModuleProfileName( true ) );
        }
 
        /**
@@ -2291,7 +2296,7 @@ abstract class ApiBase extends ContextSource {
 
                $this->mDBTime += $time;
                $this->getMain()->mDBTime += $time;
-               wfProfileOut( $this->getModuleProfileName( true ) );
+               Profiler::instance()->scopedProfileOut( $this->dbProfile );
        }
 
        /**
index a134074..c7dcce8 100644 (file)
@@ -79,7 +79,7 @@ class ApiImport extends ApiBase {
 
                try {
                        $importer->doImport();
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        $this->dieUsageMsg( array( 'import-unknownerror', $e->getMessage() ) );
                }
 
index 1610679..82ed295 100644 (file)
@@ -190,19 +190,20 @@ class ApiMain extends ApiBase {
 
                $uselang = $this->getParameter( 'uselang' );
                if ( $uselang === 'user' ) {
-                       $uselang = $this->getUser()->getOption( 'language' );
-                       $uselang = RequestContext::sanitizeLangCode( $uselang );
-                       Hooks::run( 'UserGetLanguageObject', array( $this->getUser(), &$uselang, $this ) );
-               } elseif ( $uselang === 'content' ) {
-                       global $wgContLang;
-                       $uselang = $wgContLang->getCode();
-               }
-               $code = RequestContext::sanitizeLangCode( $uselang );
-               $this->getContext()->setLanguage( $code );
-               if ( !$this->mInternalMode ) {
-                       global $wgLang;
-                       $wgLang = $this->getContext()->getLanguage();
-                       RequestContext::getMain()->setLanguage( $wgLang );
+                       // Assume the parent context is going to return the user language
+                       // for uselang=user (see T85635).
+               } else {
+                       if ( $uselang === 'content' ) {
+                               global $wgContLang;
+                               $uselang = $wgContLang->getCode();
+                       }
+                       $code = RequestContext::sanitizeLangCode( $uselang );
+                       $this->getContext()->setLanguage( $code );
+                       if ( !$this->mInternalMode ) {
+                               global $wgLang;
+                               $wgLang = $this->getContext()->getLanguage();
+                               RequestContext::getMain()->setLanguage( $wgLang );
+                       }
                }
 
                $config = $this->getConfig();
index 1417ef7..981c119 100644 (file)
@@ -450,6 +450,9 @@ class ApiPageSet extends ApiBase {
                        if ( $titleTo->hasFragment() ) {
                                $r['tofragment'] = $titleTo->getFragment();
                        }
+                       if ( $titleTo->isExternal() ) {
+                               $r['tointerwiki'] = $titleTo->getInterwiki();
+                       }
                        $values[] = $r;
                }
                if ( !empty( $values ) && $result ) {
@@ -1049,7 +1052,9 @@ class ApiPageSet extends ApiBase {
                                $row->rd_interwiki
                        );
                        unset( $this->mPendingRedirectIDs[$rdfrom] );
-                       if ( !$to->isExternal() && !isset( $this->mAllPages[$row->rd_namespace][$row->rd_title] ) ) {
+                       if ( $to->isExternal() ) {
+                               $this->mInterwikiTitles[$to->getPrefixedText()] = $to->getInterwiki();
+                       } elseif ( !isset( $this->mAllPages[$row->rd_namespace][$row->rd_title] ) ) {
                                $lb->add( $row->rd_namespace, $row->rd_title );
                        }
                        $this->mRedirectTitles[$from] = $to;
@@ -1326,7 +1331,13 @@ class ApiPageSet extends ApiBase {
                                ApiBase::PARAM_DFLT => false,
                                ApiBase::PARAM_HELP_MSG => array(
                                        'api-pageset-param-converttitles',
-                                       $this->getLanguage()->commaList( LanguageConverter::$languagesWithVariants ),
+                                       new DeferredStringifier(
+                                               function ( IContextSource $context ) {
+                                                       return $context->getLanguage()
+                                                               ->commaList( LanguageConverter::$languagesWithVariants );
+                                               },
+                                               $this
+                                       )
                                ),
                        ),
                );
index ff91b92..83d2cbc 100644 (file)
@@ -419,7 +419,6 @@ class ApiParse extends ApiBase {
         * @return ParserOptions
         */
        protected function makeParserOptions( WikiPage $pageObj, array $params ) {
-               wfProfileIn( __METHOD__ );
 
                $popts = $pageObj->makeParserOptions( $this->getContext() );
                $popts->enableLimitReport( !$params['disablepp'] );
@@ -427,8 +426,6 @@ class ApiParse extends ApiBase {
                $popts->setIsSectionPreview( $params['sectionpreview'] );
                $popts->setEditSection( !$params['disableeditsection'] );
 
-               wfProfileOut( __METHOD__ );
-
                return $popts;
        }
 
index e6667b4..05a1a15 100644 (file)
@@ -42,7 +42,7 @@ class ApiQueryInfo extends ApiQueryBase {
        private $pageRestrictions, $pageIsRedir, $pageIsNew, $pageTouched,
                $pageLatest, $pageLength;
 
-       private $protections, $watched, $watchers, $notificationtimestamps,
+       private $protections, $restrictionTypes, $watched, $watchers, $notificationtimestamps,
                $talkids, $subjectids, $displaytitles;
        private $showZeroWatchers = false;
 
@@ -419,6 +419,13 @@ class ApiQueryInfo extends ApiQueryBase {
                                        $this->protections[$ns][$dbkey];
                        }
                        $this->getResult()->setIndexedTagName( $pageInfo['protection'], 'pr' );
+
+                       $pageInfo['restrictiontypes'] = array();
+                       if ( isset( $this->restrictionTypes[$ns][$dbkey] ) ) {
+                               $pageInfo['restrictiontypes'] =
+                                       $this->restrictionTypes[$ns][$dbkey];
+                       }
+                       $this->getResult()->setIndexedTagName( $pageInfo['restrictiontypes'], 'rt' );
                }
 
                if ( $this->fld_watched && isset( $this->watched[$ns][$dbkey] ) ) {
@@ -568,7 +575,8 @@ class ApiQueryInfo extends ApiQueryBase {
                        }
                }
 
-               // Cascading protections
+               // Separate good and missing titles into files and other pages
+               // and populate $this->restrictionTypes
                $images = $others = array();
                foreach ( $this->everything as $title ) {
                        if ( $title->getNamespace() == NS_FILE ) {
@@ -576,6 +584,9 @@ class ApiQueryInfo extends ApiQueryBase {
                        } else {
                                $others[] = $title;
                        }
+                       // Applicable protection types
+                       $this->restrictionTypes[$title->getNamespace()][$title->getDBkey()] =
+                               array_values( $title->getRestrictionTypes() );
                }
 
                if ( count( $others ) ) {
index cdc61cd..b6ef604 100644 (file)
@@ -178,7 +178,7 @@ class ApiQueryRecentChanges extends ApiQueryGeneratorBase {
                if ( !is_null( $params['type'] ) ) {
                        try {
                                $this->addWhereFld( 'rc_type', RecentChange::parseToRCType( $params['type'] ) );
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                ApiBase::dieDebug( __METHOD__, $e->getMessage() );
                        }
                }
index 51f799a..16a491e 100644 (file)
@@ -332,7 +332,7 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                );
 
                $alternatives = SearchEngine::getSearchTypes();
-               if ( count( $alternatives ) > 0 ) {
+               if ( count( $alternatives ) > 1 ) {
                        if ( $alternatives[0] === null ) {
                                $alternatives[0] = self::BACKEND_NULL_PARAM;
                        }
index e8d7258..2e107ac 100644 (file)
@@ -55,7 +55,6 @@ class ApiQueryTokens extends ApiQueryBase {
        public static function getTokenTypeSalts() {
                static $salts = null;
                if ( !$salts ) {
-                       wfProfileIn( __METHOD__ );
                        $salts = array(
                                'csrf' => '',
                                'watch' => 'watch',
@@ -65,7 +64,6 @@ class ApiQueryTokens extends ApiQueryBase {
                        );
                        Hooks::run( 'ApiQueryTokensRegisterTypes', array( &$salts ) );
                        ksort( $salts );
-                       wfProfileOut( __METHOD__ );
                }
 
                return $salts;
index 4059ff8..6e60fe4 100644 (file)
@@ -199,7 +199,7 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
                if ( !is_null( $params['type'] ) ) {
                        try {
                                $this->addWhereFld( 'rc_type', RecentChange::parseToRCType( $params['type'] ) );
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                ApiBase::dieDebug( __METHOD__, $e->getMessage() );
                        }
                }
index 938f6c0..09489e4 100644 (file)
@@ -333,7 +333,12 @@ class ApiStashEdit extends ApiBase {
                // If an item is renewed, mind the cache TTL determined by config and parser functions
                $since = time() - wfTimestamp( TS_UNIX, $parserOutput->getTimestamp() );
                $ttl = min( $parserOutput->getCacheExpiry() - $since, 5 * 60 );
-               if ( $ttl > 0 && !$parserOutput->getFlag( 'vary-revision' ) ) {
+
+               // Note: ParserOutput with that contains secondary data update callbacks can not be
+               // stashed, since the callbacks are not serializable (see ParserOutput::__sleep).
+               $hasCustomDataUpdates = $parserOutput->hasCustomDataUpdates();
+
+               if ( $ttl > 0 && !$parserOutput->getFlag( 'vary-revision' ) && !$hasCustomDataUpdates ) {
                        // Only store what is actually needed
                        $stashInfo = (object)array(
                                'pstContent' => $pstContent,
index f7290af..073495c 100644 (file)
@@ -63,7 +63,6 @@ class ApiTokens extends ApiBase {
                if ( $types ) {
                        return $types;
                }
-               wfProfileIn( __METHOD__ );
                $types = array( 'patrol' => array( 'ApiQueryRecentChanges', 'getPatrolToken' ) );
                $names = array( 'edit', 'delete', 'protect', 'move', 'block', 'unblock',
                        'email', 'import', 'watch', 'options' );
@@ -72,7 +71,6 @@ class ApiTokens extends ApiBase {
                }
                Hooks::run( 'ApiTokensGetTokenTypes', array( &$types ) );
                ksort( $types );
-               wfProfileOut( __METHOD__ );
 
                return $types;
        }
index 43e4c61..d6ad7f3 100644 (file)
@@ -161,7 +161,7 @@ class ApiUpload extends ApiBase {
                        }
                } catch ( UploadStashException $e ) {
                        $this->handleStashException( $e );
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        $this->dieUsage( $e->getMessage(), 'stashfailed' );
                }
 
@@ -182,7 +182,7 @@ class ApiUpload extends ApiBase {
                try {
                        $result['filekey'] = $this->performStash();
                        $result['sessionkey'] = $result['filekey']; // backwards compatibility
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        $result['warnings']['stashfailed'] = $e->getMessage();
                }
 
@@ -209,7 +209,7 @@ class ApiUpload extends ApiBase {
                                $filekey = $this->performStash();
                        } catch ( UploadStashException $e ) {
                                $this->handleStashException( $e );
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                // FIXME: Error handling here is wrong/different from rest of this
                                $this->dieUsage( $e->getMessage(), 'stashfailed' );
                        }
@@ -283,7 +283,7 @@ class ApiUpload extends ApiBase {
                                throw new MWException( 'Invalid stashed file' );
                        }
                        $fileKey = $stashFile->getFileKey();
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        $message = 'Stashing temporary file failed: ' . get_class( $e ) . ' ' . $e->getMessage();
                        wfDebug( __METHOD__ . ' ' . $message . "\n" );
                        $className = get_class( $e );
@@ -306,7 +306,7 @@ class ApiUpload extends ApiBase {
                try {
                        $data['filekey'] = $this->performStash();
                        $data['sessionkey'] = $data['filekey'];
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        $data['stashfailed'] = $e->getMessage();
                }
                $data['invalidparameter'] = $parameter;
index 3e69ea9..838b052 100644 (file)
@@ -40,5 +40,9 @@
        "apihelp-compare-param-toid": "ID другой старонкі для параўнаньня.",
        "apihelp-compare-param-torev": "Другая вэрсія для параўнаньня.",
        "apihelp-compare-example-1": "Паказвае розьніцу паміж вэрсіямі 1 і 2",
-       "apihelp-createaccount-description": "Стварэньне новага рахунку ўдзельніка."
+       "apihelp-createaccount-description": "Стварэньне новага рахунку ўдзельніка.",
+       "apihelp-createaccount-param-name": "Імя ўдзельніка.",
+       "apihelp-createaccount-param-password": "Пароль (ігнаруецца, калі выстаўлена $1mailpassword).",
+       "apihelp-createaccount-param-domain": "Дамэн для вонкавай аўтэнтыфікацыі (неабавязкова).",
+       "apihelp-createaccount-param-token": "Маркер стварэньня рахунку, атрыманы пры першым запыце."
 }
index c7254c2..a4fb770 100644 (file)
@@ -5,8 +5,11 @@
                ]
        },
        "apihelp-main-param-format": "El format de la sortida.",
+       "apihelp-block-description": "Bloca un usuari.",
        "apihelp-block-param-nocreate": "Evita la creació de comptes.",
        "apihelp-createaccount-param-name": "Nom d'usuari.",
        "apihelp-createaccount-param-password": "Contrasenya (ignorada si es defineix $1mailpassword)",
-       "apihelp-delete-description": "Suprimeix una pàgina."
+       "apihelp-delete-description": "Suprimeix una pàgina.",
+       "apihelp-edit-description": "Crea i edita pàgines.",
+       "apihelp-edit-param-text": "Contingut de la pàgina."
 }
index 0eed4cd..cba687b 100644 (file)
@@ -83,7 +83,7 @@
        "apihelp-edit-param-bot": "Mark this edit as bot.",
        "apihelp-edit-param-basetimestamp": "Timestamp of the base revision, used to detect edit conflicts. May be obtained through [[Special:ApiHelp/query+revisions|action=query&prop=revisions&rvprop=timestamp]].",
        "apihelp-edit-param-starttimestamp": "Timestamp when you began the editing process, used to detect edit conflicts. An appropriate value may be obtained using [[Special:ApiHelp/main|curtimestamp]] when beginning the edit process (e.g. when loading the page content to edit).",
-       "apihelp-edit-param-recreate": "Override any errors about the article having been deleted in the meantime.",
+       "apihelp-edit-param-recreate": "Override any errors about the page having been deleted in the meantime.",
        "apihelp-edit-param-createonly": "Don't edit the page if it exists already.",
        "apihelp-edit-param-nocreate": "Throw an error if the page doesn't exist.",
        "apihelp-edit-param-watch": "Add the page to your watchlist.",
index 91b4907..c8a49ba 100644 (file)
        "apihelp-protect-example-unprotect": "خارج ساختن صفحه از حفاظت با تغییر سطح حفاظتی به \"همگان\"",
        "apihelp-protect-example-unprotect2": "خارج ساختن صفحه از حفاظت با قراردادن هیچ‌گونه محدودیت‌حفاظتی",
        "apihelp-purge-param-forcelinkupdate": "به‌روزرسانی جداول پیوندها.",
+       "apihelp-purge-param-forcerecursivelinkupdate": "جدول پیوندها را به‌روز رسانی کنید، و جدول‌های پیوندهای هر صفحه‌ای را که از این صفحه به عنوان الگو استفاده می‌کند به‌روز رسانی کنید.",
+       "apihelp-query-param-list": "کدام فهرست‌ها دریافت شود.",
+       "apihelp-query-param-meta": "کدام فراداده‌ها دریافت شود.",
+       "apihelp-query+allcategories-param-prefix": "عنوان همهٔ رده‌ها را که با این مقدار آغاز می‌شود جستجو کنید.",
+       "apihelp-query+allcategories-param-limit": "میزان رده‌ها برای بازگرداندن.",
+       "apihelp-query+alldeletedrevisions-paraminfo-nonuseronly": "نمی‌تواند همراه $3user به کار رود.",
        "apihelp-query+allfileusages-param-limit": "تعداد آیتم‌ها برای بازگرداندن.",
        "apihelp-query+allfileusages-param-dir": "جهتی که باید فهرست شود.",
        "apihelp-query+allfileusages-example-unique": "فهرست پرونده‌های با عنوان یکتا",
        "apihelp-query+alllinks-param-dir": "جهتی که باید فهرست شود.",
        "apihelp-query+allpages-param-filterredir": "صفحه‌هایی که باید فهرست شوند.",
        "apihelp-query+allpages-param-minsize": "محدودکردن به صفحه‌هایی که همراه دست کم این تعداد بایت است.",
+       "apihelp-query+allpages-param-limit": "میزان کل صفحه‌ها برای بازگرداندن.",
        "apihelp-query+allredirects-param-limit": "تعداد آیتم‌ها برای بازگرداندن.",
+       "apihelp-query+backlinks-example-simple": "نمایش پیوندها به [[صفحهٔ اصلی]]",
        "apihelp-query+blocks-example-simple": "فهرست بسته‌شده‌ها",
+       "apihelp-query+categories-param-show": "کدام نوع رده‌ها نمایش داده‌شود.",
+       "apihelp-query+categories-param-limit": "چه میزان رده بازگردانده شود.",
+       "apihelp-query+categories-param-categories": "فقط این رده‌ها فهرست شود. کاربردی برای بررسی وجود یک صفحهٔ مشخص در یک ردهٔ مشخص.",
        "apihelp-query+categorymembers-description": "فهرست‌کردن همهٔ صفحه‌ها در یک ردهٔ مشخص‌شده.",
        "apihelp-query+categorymembers-param-sort": "خصوصیت برای مرتب‌سازی",
        "apihelp-query+categorymembers-param-dir": "جهت مرتب شدن",
index b86eb57..b1a7e8c 100644 (file)
@@ -1,8 +1,10 @@
 {
        "@metadata": {
                "authors": [
-                       "Nike"
+                       "Nike",
+                       "MrTapsa"
                ]
        },
+       "apihelp-query+linkshere-param-show": "Näytä vain kohteet, jotka täyttävät nämä kriteerit:\n;redirect:Näytä vain uudelleenohjaukset.\n;!redirect:Näytä vain ei-uudelleenohjaukset",
        "apihelp-upload-param-stash": "Mikäli valittu, palvelin säilöö tiedoston väliaikaisesti tallentamisen sijaan."
 }
index c587d5b..4578a06 100644 (file)
@@ -4,7 +4,8 @@
                        "Chrumps",
                        "Py64",
                        "Pan Cube",
-                       "Alan ffm"
+                       "Alan ffm",
+                       "Devwebtel"
                ]
        },
        "apihelp-main-param-action": "Wybierz akcję do wykonania.",
        "apihelp-block-description": "Zablokuj użytkownika.",
        "apihelp-block-param-reason": "Powód blokady.",
        "apihelp-block-param-nocreate": "Zapobiegnij utworzeniu konta.",
+       "apihelp-block-param-watchuser": "Obserwuj stronę użytkownika i jego IP oraz jego stronę dyskusji.",
+       "apihelp-block-example-ip-simple": "Zablokuj IP 192.0.2.5 na 3 dni za \"Pierwszy atak\"",
        "apihelp-createaccount-param-name": "Nazwa użytkownika",
        "apihelp-delete-description": "Usuń stronę.",
+       "apihelp-delete-param-watch": "Dodaj stronę do twojej listy obserwowanych.",
+       "apihelp-delete-param-unwatch": "Usuń stronę z twojej listy obserwowanych.",
        "apihelp-delete-example-simple": "Usuń stronę główną",
+       "apihelp-disabled-description": "Ten moduł został wyłączony.",
+       "apihelp-edit-description": "Utwórz i edytuj strony.;",
        "apihelp-edit-param-text": "Zawartość strony.",
        "apihelp-edit-param-minor": "Drobna zmiana.",
+       "apihelp-edit-param-notminor": "Nie drobna zmiana.",
+       "apihelp-edit-param-bot": "Oznacz tą edycję jako edycję bota.",
        "apihelp-edit-example-edit": "Edytuj stronę",
        "apihelp-emailuser-description": "Wyślij e‐mail do użytkownika.",
        "apihelp-help-description": "Wyświetl pomoc dla określonych modułów.",
diff --git a/includes/api/i18n/roa-tara.json b/includes/api/i18n/roa-tara.json
new file mode 100644 (file)
index 0000000..0706412
--- /dev/null
@@ -0,0 +1,11 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Joetaras"
+               ]
+       },
+       "apihelp-block-param-reason": "Mutive pu blocche.",
+       "apihelp-createaccount-param-name": "Nome de l'utende.",
+       "apihelp-edit-param-text": "Vôsce.",
+       "apihelp-edit-example-edit": "Cange 'na pàgene"
+}
index 30b25c4..ca690bf 100644 (file)
        "apihelp-query+allmessages-example-ipb": "Visa meddelanden som börjar med \"ipb-\"",
        "apihelp-query+allmessages-example-de": "Visa meddelandena \"august\" och \"mainpage\" på tyska",
        "apihelp-query+allpages-param-filterredir": "Vilka sidor att lista.",
+       "apihelp-query+allusers-param-dir": "Riktning att sortera i.",
+       "apihelp-query+allusers-example-Y": "Lista användare som börjar på Y",
        "apihelp-query+revisions-example-first5-not-localhost": "Hämta första 5 revideringarna av \"huvudsidan\" och som inte gjorts av anonym användare \"127.0.0.1\"",
        "apihelp-query+stashimageinfo-description": "Returnerar filinformation för temporära filer.",
        "apihelp-query+stashimageinfo-param-filekey": "Nyckel som identifierar en tidigare uppladdning som lagrats temporärt.",
index 01d78dc..a60fa56 100644 (file)
@@ -6,7 +6,8 @@
                        "Liuxinyu970226",
                        "Papapasan",
                        "LNDDYL",
-                       "Shizhao"
+                       "Shizhao",
+                       "Yfdyh000"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [https://www.mediawiki.org/wiki/API:Main_page/zh 文档]\n* [https://www.mediawiki.org/wiki/API:FAQ/zh 常见问题]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api 邮件列表]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce API公告]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R 程序错误与功能请求]\n</div>\n<strong>状态信息:</strong> 本页所展示的所有特性都应正常工作,但是API仍在开发当中,将会随时变化。请订阅[https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ mediawiki-api-announce 邮件列表]以便获得更新通知。\n\n<strong>错误请求:</strong> 当API收到错误请求时,HTTP header将会返回一个包含\"MediaWiki-API-Error\"的值,随后header的值与error code将会送回并设置为相同的值。详细信息请参阅 https://www.mediawiki.org/wiki/API:Errors_and_warnings 。",
        "apihelp-expandtemplates-example-simple": "展开wiki文本“<nowiki>{{Project:Sandbox}}</nowiki>”",
        "apihelp-feedcontributions-description": "返回用户贡献纲要。",
        "apihelp-feedcontributions-param-feedformat": "纲要的格式。",
+       "apihelp-feedcontributions-param-user": "获取哪些用户的贡献。",
+       "apihelp-feedcontributions-param-namespace": "过滤哪些命名空间的贡献。",
        "apihelp-feedcontributions-param-year": "起始年份(及更早)。",
        "apihelp-feedcontributions-param-month": "起始月份(及更早)。",
+       "apihelp-feedcontributions-param-tagfilter": "过滤有这些标签的贡献者。",
        "apihelp-feedcontributions-param-deletedonly": "仅显示已删除的贡献。",
        "apihelp-feedcontributions-param-toponly": "仅仅显示那些作为最新修订的编辑。",
        "apihelp-feedcontributions-param-newonly": "仅仅显示那些作为页面创建的编辑。",
        "apihelp-feedrecentchanges-param-feedformat": "纲要的格式。",
        "apihelp-feedrecentchanges-param-namespace": "用于限制结果的命名空间。",
        "apihelp-feedrecentchanges-param-invert": "除所选定者外的所有命名空间。",
+       "apihelp-feedrecentchanges-param-associated": "包括相关的命名空间(讨论页或主要)。",
        "apihelp-feedrecentchanges-param-days": "用于限制结果的天数。",
        "apihelp-feedrecentchanges-param-limit": "所要返回结果的最大数目。",
        "apihelp-feedrecentchanges-param-from": "显示自那时以来的更改。",
        "apihelp-filerevert-param-filename": "目标文件名,不包含前缀“File:”。",
        "apihelp-filerevert-param-comment": "上传评论。",
        "apihelp-filerevert-example-revert": "回退Wiki.png至2011-03-05T15:27:40Z的版本",
+       "apihelp-help-description": "显示指定模块的帮助。",
+       "apihelp-help-param-submodules": "包括给定名称模块的子模块的帮助。",
+       "apihelp-help-param-recursivesubmodules": "包括递归子模块的帮助。",
        "apihelp-help-param-helpformat": "帮助的输出格式。",
+       "apihelp-help-param-wrap": "在一个标准API响应结构中包裹输出。",
+       "apihelp-help-param-toc": "在HTML输出中包括目录。",
        "apihelp-help-example-main": "主模块帮助",
        "apihelp-help-example-recursive": "一个页面中的所有帮助",
        "apihelp-help-example-help": "帮助模块本身的帮助",
        "apihelp-import-param-namespace": "用于跨wiki导入:导入到此名字空间。",
        "apihelp-import-param-rootpage": "导入作为此页面的子页面。",
        "apihelp-import-example-import": "将页面[[meta:Help:Parserfunctions]]连带完整历史导入至100名字空间。",
+       "apihelp-login-description": "登录并获得身份验证Cookie。\n\n在成功登录的情况下,所需的Cookie将包含在HTTP响应头中。在登录失败的情况下,进一步的尝试可能会被自动密码猜解攻击的限制所遏制。",
        "apihelp-login-param-name": "用户名。",
        "apihelp-login-param-password": "密码。",
        "apihelp-login-param-domain": "域名(可选)。",
+       "apihelp-login-param-token": "在首个请求中获得的登录令牌。",
        "apihelp-login-example-gettoken": "检索登录令牌",
        "apihelp-login-example-login": "登录",
        "apihelp-logout-description": "退出并清除会话数据。",
        "apihelp-move-param-movesubpages": "移动子页面,如果可以。",
        "apihelp-move-param-noredirect": "不要创建重定向。",
        "apihelp-move-param-watch": "将页面和重定向加入至您的监视列表中。",
+       "apihelp-move-param-unwatch": "从您的监视列表中移除页面及重定向。",
+       "apihelp-move-param-watchlist": "无条件地将页面加入至您的监视列表或将其移除,使用设置或不更改监视。",
        "apihelp-move-param-ignorewarnings": "忽略任何警告。",
+       "apihelp-move-example-move": "移动“坏标题”到“好标题”并且不留下重定向",
+       "apihelp-opensearch-description": "使用OpenSearch协议搜索本wiki。",
        "apihelp-opensearch-param-search": "搜索字符串。",
        "apihelp-opensearch-param-limit": "要返回的结果最大数。",
        "apihelp-opensearch-param-namespace": "搜索的名字空间。",
        "apihelp-opensearch-param-suggest": "如果[https://www.mediawiki.org/wiki/Manual:$wgEnableOpenSearchSuggest $wgEnableOpenSearchSuggest]设置为false则不做任何事情。",
+       "apihelp-opensearch-param-redirects": "如何处理重定向:\n;return:返回重定向本身。\n;resolve:返回目标页面。可能返回少于$1limit个结果。\n由于历史原因,$1format=json默认为\"return\",其他格式默认为\"resolve\"",
        "apihelp-opensearch-param-format": "输出格式。",
        "apihelp-opensearch-example-te": "查找以“Te”开头的页面",
+       "apihelp-options-description": "更改当前用户的偏好设置。\n\n只有注册在核心或者已安装扩展中的选项,或者具有\"userjs-\"键值前缀(旨在被用户脚本使用)的选项可被设置。",
+       "apihelp-options-param-reset": "重置偏好设置到网站默认设置。",
        "apihelp-options-example-reset": "重置所有用户设置",
        "apihelp-options-example-change": "更改“皮肤”和“hideminot”设置",
        "apihelp-options-example-complex": "重置所有设置,之后设置“皮肤”和“昵称”",
        "apihelp-parse-param-pageid": "解析此页的内容。覆盖 $1 页。",
        "apihelp-parse-param-redirects": "如果 $1page 或 $1 pageid 参数被设置为一个重定向,则解析它。",
        "apihelp-parse-param-oldid": "解析该修订版本的内容。覆盖 $1page 和 $1 pageid。",
+       "apihelp-parse-param-generatexml": "生成XML解析树(需要内容模型\"$1\")。",
        "apihelp-parse-param-preview": "在预览模式下解析。",
        "apihelp-parse-param-sectionpreview": "在小节预览模式下解析 (同时要启用预览模式)。",
        "apihelp-parse-param-disabletoc": "在输出中禁用目录。",
        "apihelp-query+fileusage-example-simple": "获取使用[[:File:Example.jpg]]的页面列表",
        "apihelp-query+fileusage-example-generator": "获取有关使用[[:File:Example.jpg]]的页面的信息",
        "apihelp-query+imageinfo-description": "返回文件信息和上传历史。",
+       "apihelp-query+imageinfo-param-prop": "要获取的文件信息:",
        "apihelp-query+imageinfo-paramvalue-prop-timestamp": "添加时间戳至上传的版本。",
        "apihelp-query+imageinfo-paramvalue-prop-comment": "此版本的摘要。",
        "apihelp-query+imageinfo-paramvalue-prop-dimensions": "大小别名。",
index 753263c..c6d9a18 100644 (file)
@@ -176,7 +176,6 @@ class BacklinkCache {
         * @return ResultWrapper
         */
        protected function queryLinks( $table, $startId, $endId, $max, $select = 'all' ) {
-               wfProfileIn( __METHOD__ );
 
                $fromField = $this->getPrefix( $table ) . '_from';
 
@@ -231,8 +230,6 @@ class BacklinkCache {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $res;
        }
 
index 48c063f..77e4d49 100644 (file)
@@ -128,11 +128,9 @@ class LinkBatch {
         * @return array Remaining IDs
         */
        protected function executeInto( &$cache ) {
-               wfProfileIn( __METHOD__ );
                $res = $this->doQuery();
                $this->doGenderQuery();
                $ids = $this->addResultToCache( $cache, $res );
-               wfProfileOut( __METHOD__ );
 
                return $ids;
        }
@@ -185,7 +183,6 @@ class LinkBatch {
                if ( $this->isEmpty() ) {
                        return false;
                }
-               wfProfileIn( __METHOD__ );
 
                // This is similar to LinkHolderArray::replaceInternal
                $dbr = wfGetDB( DB_SLAVE );
@@ -205,7 +202,6 @@ class LinkBatch {
                        $caller .= " (for {$this->caller})";
                }
                $res = $dbr->select( $table, $fields, $conds, $caller );
-               wfProfileOut( __METHOD__ );
 
                return $res;
        }
index 82fb12d..eace1ee 100644 (file)
@@ -218,23 +218,18 @@ class LinkCache {
        public function addLinkObj( $nt ) {
                global $wgContentHandlerUseDB;
 
-               wfProfileIn( __METHOD__ );
-
                $key = $nt->getPrefixedDBkey();
                if ( $this->isBadLink( $key ) || $nt->isExternal() ) {
-                       wfProfileOut( __METHOD__ );
 
                        return 0;
                }
                $id = $this->getGoodLinkID( $key );
                if ( $id != 0 ) {
-                       wfProfileOut( __METHOD__ );
 
                        return $id;
                }
 
                if ( $key === '' ) {
-                       wfProfileOut( __METHOD__ );
 
                        return 0;
                }
@@ -263,8 +258,6 @@ class LinkCache {
                        $id = 0;
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $id;
        }
 
index 472195c..e270f5f 100644 (file)
@@ -257,9 +257,7 @@ class LocalisationCache {
         */
        public function getItem( $code, $key ) {
                if ( !isset( $this->loadedItems[$code][$key] ) ) {
-                       wfProfileIn( __METHOD__ . '-load' );
                        $this->loadItem( $code, $key );
-                       wfProfileOut( __METHOD__ . '-load' );
                }
 
                if ( $key === 'fallback' && isset( $this->shallowFallbacks[$code] ) ) {
@@ -280,9 +278,7 @@ class LocalisationCache {
                if ( !isset( $this->loadedSubitems[$code][$key][$subkey] ) &&
                        !isset( $this->loadedItems[$code][$key] )
                ) {
-                       wfProfileIn( __METHOD__ . '-load' );
                        $this->loadSubitem( $code, $key, $subkey );
-                       wfProfileOut( __METHOD__ . '-load' );
                }
 
                if ( isset( $this->data[$code][$key][$subkey] ) ) {
@@ -509,7 +505,6 @@ class LocalisationCache {
         * @return array
         */
        protected function readPHPFile( $_fileName, $_fileType ) {
-               wfProfileIn( __METHOD__ );
                // Disable APC caching
                wfSuppressWarnings();
                $_apcEnabled = ini_set( 'apc.cache_by_default', '0' );
@@ -526,10 +521,8 @@ class LocalisationCache {
                } elseif ( $_fileType == 'aliases' ) {
                        $data = compact( 'aliases' );
                } else {
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( __METHOD__ . ": Invalid file type: $_fileType" );
                }
-               wfProfileOut( __METHOD__ );
 
                return $data;
        }
@@ -541,24 +534,20 @@ class LocalisationCache {
         * @return array Array with a 'messages' key, or empty array if the file doesn't exist
         */
        public function readJSONFile( $fileName ) {
-               wfProfileIn( __METHOD__ );
 
                if ( !is_readable( $fileName ) ) {
-                       wfProfileOut( __METHOD__ );
 
                        return array();
                }
 
                $json = file_get_contents( $fileName );
                if ( $json === false ) {
-                       wfProfileOut( __METHOD__ );
 
                        return array();
                }
 
                $data = FormatJson::decode( $json, true );
                if ( $data === null ) {
-                       wfProfileOut( __METHOD__ );
 
                        throw new MWException( __METHOD__ . ": Invalid JSON file: $fileName" );
                }
@@ -570,8 +559,6 @@ class LocalisationCache {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-
                // The JSON format only supports messages, none of the other variables, so wrap the data
                return array( 'messages' => $data );
        }
@@ -697,7 +684,6 @@ class LocalisationCache {
         */
        protected function readSourceFilesAndRegisterDeps( $code, &$deps ) {
                global $IP;
-               wfProfileIn( __METHOD__ );
 
                // This reads in the PHP i18n file with non-messages l10n data
                $fileName = Language::getMessagesFileName( $code );
@@ -718,8 +704,6 @@ class LocalisationCache {
                $deps['plurals'] = new FileDependency( "$IP/languages/data/plurals.xml" );
                $deps['plurals-mw'] = new FileDependency( "$IP/languages/data/plurals-mediawiki.xml" );
 
-               wfProfileOut( __METHOD__ );
-
                return $data;
        }
 
@@ -823,10 +807,8 @@ class LocalisationCache {
         */
        public function recache( $code ) {
                global $wgExtensionMessagesFiles;
-               wfProfileIn( __METHOD__ );
 
                if ( !$code ) {
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( "Invalid language code requested" );
                }
                $this->recachedLangs[$code] = true;
@@ -871,8 +853,6 @@ class LocalisationCache {
                $codeSequence = array_merge( array( $code ), $coreData['fallbackSequence'] );
                $messageDirs = $this->getMessagesDirs();
 
-               wfProfileIn( __METHOD__ . '-fallbacks' );
-
                # Load non-JSON localisation data for extensions
                $extensionData = array_combine(
                        $codeSequence,
@@ -969,8 +949,6 @@ class LocalisationCache {
                        }
                }
 
-               wfProfileOut( __METHOD__ . '-fallbacks' );
-
                # Add cache dependencies for any referenced globals
                $deps['wgExtensionMessagesFiles'] = new GlobalDependency( 'wgExtensionMessagesFiles' );
                // $wgMessagesDirs is used in LocalisationCache::getMessagesDirs()
@@ -1012,7 +990,6 @@ class LocalisationCache {
                Hooks::run( 'LocalisationCacheRecache', array( $this, $code, &$allData, &$purgeBlobs ) );
 
                if ( is_null( $allData['namespaceNames'] ) ) {
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( __METHOD__ . ': Localisation data failed sanity check! ' .
                                'Check that your languages/messages/MessagesEn.php file is intact.' );
                }
@@ -1027,7 +1004,6 @@ class LocalisationCache {
                }
 
                # Save to the persistent cache
-               wfProfileIn( __METHOD__ . '-write' );
                $this->store->startWrite( $code );
                foreach ( $allData as $key => $value ) {
                        if ( in_array( $key, self::$splitKeys ) ) {
@@ -1039,7 +1015,6 @@ class LocalisationCache {
                        }
                }
                $this->store->finishWrite();
-               wfProfileOut( __METHOD__ . '-write' );
 
                # Clear out the MessageBlobStore
                # HACK: If using a null (i.e. disabled) storage backend, we
@@ -1048,7 +1023,6 @@ class LocalisationCache {
                        MessageBlobStore::getInstance()->clear();
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
index 2f6a1b1..04f5887 100644 (file)
@@ -266,7 +266,6 @@ class MessageCache {
                }
 
                # Loading code starts
-               wfProfileIn( __METHOD__ );
                $success = false; # Keep track of success
                $staleCache = false; # a cache array with expired data, or false if none has been loaded
                $where = array(); # Debug info, delayed to avoid spamming debug log too much
@@ -276,7 +275,6 @@ class MessageCache {
                # Hash of the contents is stored in memcache, to detect if local cache goes
                # out of date (e.g. due to replace() on some other server)
                if ( $wgUseLocalMessageCache ) {
-                       wfProfileIn( __METHOD__ . '-fromlocal' );
 
                        $hash = $this->mMemc->get( wfMemcKey( 'messages', $code, 'hash' ) );
                        if ( $hash ) {
@@ -292,7 +290,6 @@ class MessageCache {
                                        $this->mCache[$code] = $cache;
                                }
                        }
-                       wfProfileOut( __METHOD__ . '-fromlocal' );
                }
 
                if ( !$success ) {
@@ -300,7 +297,6 @@ class MessageCache {
                        # the lock can't be acquired, wait for the other thread to finish
                        # and then try the global cache a second time.
                        for ( $failedAttempts = 0; $failedAttempts < 2; $failedAttempts++ ) {
-                               wfProfileIn( __METHOD__ . '-fromcache' );
                                $cache = $this->mMemc->get( $cacheKey );
                                if ( !$cache ) {
                                        $where[] = 'global cache is empty';
@@ -314,8 +310,6 @@ class MessageCache {
                                        $success = true;
                                }
 
-                               wfProfileOut( __METHOD__ . '-fromcache' );
-
                                if ( $success ) {
                                        # Done, no need to retry
                                        break;
@@ -423,7 +417,6 @@ class MessageCache {
                }
                $info = implode( ', ', $where );
                wfDebugLog( 'MessageCache', __METHOD__ . ": Loading $code... $info\n" );
-               wfProfileOut( __METHOD__ );
 
                return $success;
        }
@@ -437,7 +430,6 @@ class MessageCache {
         * @return array Loaded messages for storing in caches.
         */
        function loadFromDB( $code ) {
-               wfProfileIn( __METHOD__ );
                global $wgMaxMsgCacheEntrySize, $wgLanguageCode, $wgAdaptiveMessageCache;
                $dbr = wfGetDB( DB_SLAVE );
                $cache = array();
@@ -511,7 +503,6 @@ class MessageCache {
 
                $cache['VERSION'] = MSG_CACHE_VERSION;
                $cache['EXPIRY'] = wfTimestamp( TS_MW, time() + $this->mExpiry );
-               wfProfileOut( __METHOD__ );
 
                return $cache;
        }
@@ -524,10 +515,8 @@ class MessageCache {
         */
        public function replace( $title, $text ) {
                global $wgMaxMsgCacheEntrySize;
-               wfProfileIn( __METHOD__ );
 
                if ( $this->mDisable ) {
-                       wfProfileOut( __METHOD__ );
 
                        return;
                }
@@ -577,7 +566,6 @@ class MessageCache {
 
                Hooks::run( 'MessageCacheReplace', array( $title, $text ) );
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -610,7 +598,6 @@ class MessageCache {
         * @return bool
         */
        protected function saveToCaches( $cache, $dest, $code = false ) {
-               wfProfileIn( __METHOD__ );
                global $wgUseLocalMessageCache;
 
                $cacheKey = wfMemcKey( 'messages', $code );
@@ -629,8 +616,6 @@ class MessageCache {
                        $this->saveToLocal( $serialized, $hash, $code );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $success;
        }
 
@@ -708,8 +693,6 @@ class MessageCache {
        function get( $key, $useDB = true, $langcode = true, $isFullKey = false ) {
                global $wgContLang;
 
-               $section = new ProfileSection( __METHOD__ );
-
                if ( is_int( $key ) ) {
                        // Fix numerical strings that somehow become ints
                        // on their way here
@@ -1056,7 +1039,6 @@ class MessageCache {
                $popts->setInterfaceMessage( $interface );
                $popts->setTargetLanguage( $language );
 
-               wfProfileIn( __METHOD__ );
                if ( !$title || !$title instanceof Title ) {
                        global $wgTitle;
                        wfDebugLog( 'GlobalTitleFail', __METHOD__ . ' called by ' . wfGetAllCallers( 5 ) . ' with no title set.' );
@@ -1073,8 +1055,6 @@ class MessageCache {
                $res = $parser->parse( $text, $title, $popts, $linestart );
                $this->mInParser = false;
 
-               wfProfileOut( __METHOD__ );
-
                return $res;
        }
 
index 7f36f5a..8a42489 100644 (file)
@@ -80,7 +80,6 @@ class UserCache {
         * @param string $caller The calling method
         */
        public function doQuery( array $userIds, $options = array(), $caller = '' ) {
-               wfProfileIn( __METHOD__ );
 
                $usersToCheck = array();
                $usersToQuery = array();
@@ -134,7 +133,6 @@ class UserCache {
                }
                $lb->execute();
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
index ef15bb1..6ecaacb 100644 (file)
@@ -94,7 +94,7 @@ abstract class BloomCache {
         * @return bool True if set, false if not (also returns true on error)
         */
        final public function check( $domain, $type, $member ) {
-               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+               $ps = Profiler::instance()->scopedProfileIn( get_class( $this ) . '::' . __FUNCTION__ );
 
                if ( method_exists( "BloomFilter{$type}", 'mergeAndCheck' ) ) {
                        try {
@@ -114,7 +114,7 @@ abstract class BloomCache {
                                if ( $useFilter ) {
                                        return ( $this->isHit( 'shared', "$virtualKey:$member" ) !== false );
                                }
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                MWExceptionHandler::logException( $e );
                                return true;
                        }
@@ -132,7 +132,7 @@ abstract class BloomCache {
         * @return bool Success
         */
        final public function insert( $domain, $type, $members ) {
-               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+               $ps = Profiler::instance()->scopedProfileIn( get_class( $this ) . '::' . __FUNCTION__ );
 
                if ( method_exists( "BloomFilter{$type}", 'mergeAndCheck' ) ) {
                        try {
@@ -143,7 +143,7 @@ abstract class BloomCache {
                                }
 
                                return $this->add( 'shared', $prefixedMembers );
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                MWExceptionHandler::logException( $e );
                                return false;
                        }
@@ -161,7 +161,7 @@ abstract class BloomCache {
         * @return bool Success
         */
        final public function init( $key, $size = 1000000, $precision = .001 ) {
-               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+               $ps = Profiler::instance()->scopedProfileIn( get_class( $this ) . '::' . __FUNCTION__ );
 
                return $this->doInit( "{$this->cacheID}:$key", $size, min( .1, $precision ) );
        }
@@ -174,7 +174,7 @@ abstract class BloomCache {
         * @return bool Success
         */
        final public function add( $key, $members ) {
-               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+               $ps = Profiler::instance()->scopedProfileIn( get_class( $this ) . '::' . __FUNCTION__ );
 
                return $this->doAdd( "{$this->cacheID}:$key", (array)$members );
        }
@@ -193,7 +193,7 @@ abstract class BloomCache {
         * @return bool|null True if set, false if not, null on error
         */
        final public function isHit( $key, $member ) {
-               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+               $ps = Profiler::instance()->scopedProfileIn( get_class( $this ) . '::' . __FUNCTION__ );
 
                return $this->doIsHit( "{$this->cacheID}:$key", $member );
        }
@@ -205,7 +205,7 @@ abstract class BloomCache {
         * @return bool Success
         */
        final public function delete( $key ) {
-               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+               $ps = Profiler::instance()->scopedProfileIn( get_class( $this ) . '::' . __FUNCTION__ );
 
                return $this->doDelete( "{$this->cacheID}:$key" );
        }
@@ -218,7 +218,7 @@ abstract class BloomCache {
         * @return bool Success
         */
        final public function setStatus( $virtualKey, array $values ) {
-               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+               $ps = Profiler::instance()->scopedProfileIn( get_class( $this ) . '::' . __FUNCTION__ );
 
                return $this->doSetStatus( "{$this->cacheID}:$virtualKey", $values );
        }
@@ -236,7 +236,7 @@ abstract class BloomCache {
         * @return array|bool False on failure
         */
        final public function getStatus( $virtualKey ) {
-               $section = new ProfileSection( get_class( $this ) . '::' . __FUNCTION__ );
+               $ps = Profiler::instance()->scopedProfileIn( get_class( $this ) . '::' . __FUNCTION__ );
 
                return $this->doGetStatus( "{$this->cacheID}:$virtualKey" );
        }
index 2d3b919..28c2f7e 100644 (file)
@@ -167,14 +167,12 @@ class ChangesFeed {
         * @param Feed $feed
         */
        public static function generateFeed( $rows, &$feed ) {
-               wfProfileIn( __METHOD__ );
                $items = self::buildItems( $rows );
                $feed->outHeader();
                foreach ( $items as $item ) {
                        $feed->outItem( $item );
                }
                $feed->outFooter();
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -183,7 +181,6 @@ class ChangesFeed {
         * @return array
         */
        public static function buildItems( $rows ) {
-               wfProfileIn( __METHOD__ );
                $items = array();
 
                # Merge adjacent edits by one user
@@ -234,7 +231,6 @@ class ChangesFeed {
                        );
                }
 
-               wfProfileOut( __METHOD__ );
                return $items;
        }
 }
index 09fcfd9..2cee726 100644 (file)
@@ -89,7 +89,6 @@ class EnhancedChangesList extends ChangesList {
         * @return string
         */
        public function recentChangesLine( &$baseRC, $watched = false ) {
-               wfProfileIn( __METHOD__ );
 
                $date = $this->getLanguage()->userDate(
                        $baseRC->mAttribs['rc_timestamp'],
@@ -110,8 +109,6 @@ class EnhancedChangesList extends ChangesList {
                $cacheEntry = $this->cacheEntryFactory->newFromRecentChange( $baseRC, $watched );
                $this->addCacheEntry( $cacheEntry );
 
-               wfProfileOut( __METHOD__ );
-
                return $ret;
        }
 
@@ -161,7 +158,6 @@ class EnhancedChangesList extends ChangesList {
         * @return string
         */
        protected function recentChangesBlockGroup( $block ) {
-               wfProfileIn( __METHOD__ );
 
                # Add the namespace and title of the block as part of the class
                $classes = array( 'mw-collapsible', 'mw-collapsed', 'mw-enhanced-rc' );
@@ -469,8 +465,6 @@ class EnhancedChangesList extends ChangesList {
 
                $this->rcCacheIndex++;
 
-               wfProfileOut( __METHOD__ );
-
                return $r;
        }
 
@@ -481,7 +475,6 @@ class EnhancedChangesList extends ChangesList {
         * @return string A HTML formatted line (generated using $r)
         */
        protected function recentChangesBlockLine( $rcObj ) {
-               wfProfileIn( __METHOD__ );
                $query['curid'] = $rcObj->mAttribs['rc_cur_id'];
 
                $type = $rcObj->mAttribs['rc_type'];
@@ -553,8 +546,6 @@ class EnhancedChangesList extends ChangesList {
 
                $r .= "</td></tr></table>\n";
 
-               wfProfileOut( __METHOD__ );
-
                return $r;
        }
 
@@ -569,8 +560,6 @@ class EnhancedChangesList extends ChangesList {
                        return '';
                }
 
-               wfProfileIn( __METHOD__ );
-
                $blockOut = '';
                foreach ( $this->rc_cache as $block ) {
                        if ( count( $block ) < 2 ) {
@@ -580,8 +569,6 @@ class EnhancedChangesList extends ChangesList {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-
                return '<div>' . $blockOut . '</div>';
        }
 
index 5067886..4ce564d 100644 (file)
@@ -32,7 +32,6 @@ class OldChangesList extends ChangesList {
         * @return string|bool
         */
        public function recentChangesLine( &$rc, $watched = false, $linenumber = null ) {
-               wfProfileIn( __METHOD__ );
 
                $classes = array();
                // use mw-line-even/mw-line-odd class only if linenumber is given (feature from bug 14468)
@@ -57,13 +56,9 @@ class OldChangesList extends ChangesList {
                }
 
                if ( !Hooks::run( 'OldChangesListRecentChangesLine', array( &$this, &$html, $rc, &$classes ) ) ) {
-                       wfProfileOut( __METHOD__ );
-
                        return false;
                }
 
-               wfProfileOut( __METHOD__ );
-
                $dateheader = ''; // $html now contains only <li>...</li>, for hooks' convenience.
                $this->insertDateHeader( $dateheader, $rc->mAttribs['rc_timestamp'] );
 
index ff3b25b..df90f22 100644 (file)
@@ -25,8 +25,8 @@ class JsonContent extends TextContent {
        /**
         * @param string $text JSON
         */
-       public function __construct( $text ) {
-               parent::__construct( $text, CONTENT_MODEL_JSON );
+       public function __construct( $text, $modelId = CONTENT_MODEL_JSON ) {
+               parent::__construct( $text, $modelId );
        }
 
        /**
index 7593d7c..dbe09f9 100644 (file)
@@ -68,13 +68,11 @@ class WikitextContent extends TextContent {
         * @see Content::replaceSection()
         */
        public function replaceSection( $sectionId, Content $with, $sectionTitle = '' ) {
-               wfProfileIn( __METHOD__ );
 
                $myModelId = $this->getModel();
                $sectionModelId = $with->getModel();
 
                if ( $sectionModelId != $myModelId ) {
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( "Incompatible content model for section: " .
                                "document uses $myModelId but " .
                                "section uses $sectionModelId." );
@@ -84,7 +82,6 @@ class WikitextContent extends TextContent {
                $text = $with->getNativeData();
 
                if ( strval( $sectionId ) === '' ) {
-                       wfProfileOut( __METHOD__ );
 
                        return $with; # XXX: copy first?
                }
@@ -107,8 +104,6 @@ class WikitextContent extends TextContent {
 
                $newContent = new static( $text );
 
-               wfProfileOut( __METHOD__ );
-
                return $newContent;
        }
 
index 7cd2290..89ccd0b 100644 (file)
@@ -318,7 +318,10 @@ class RequestContext implements IContextSource {
                                $request = $this->getRequest();
                                $user = $this->getUser();
 
-                               $code = $request->getVal( 'uselang', $user->getOption( 'language' ) );
+                               $code = $request->getVal( 'uselang', 'user' );
+                               if ( $code === 'user' ) {
+                                       $code = $user->getOption( 'language' );
+                               }
                                $code = self::sanitizeLangCode( $code );
 
                                Hooks::run( 'UserGetLanguageObject', array( $user, &$code, $this ) );
@@ -358,7 +361,6 @@ class RequestContext implements IContextSource {
         */
        public function getSkin() {
                if ( $this->skin === null ) {
-                       wfProfileIn( __METHOD__ . '-createskin' );
 
                        $skin = null;
                        Hooks::run( 'RequestContextCreateSkin', array( $this, &$skin ) );
@@ -396,7 +398,6 @@ class RequestContext implements IContextSource {
 
                        // After all that set a context on whatever skin got created
                        $this->skin->setContext( $this );
-                       wfProfileOut( __METHOD__ . '-createskin' );
                }
 
                return $this->skin;
index 0b022d1..054f27a 100644 (file)
@@ -3962,7 +3962,7 @@ abstract class DatabaseBase implements IDatabase {
 
                try {
                        $error = $this->sourceStream( $fp, $lineCallback, $resultCallback, $fname, $inputCallback );
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        fclose( $fp );
                        throw $e;
                }
index 2393bbb..86950a8 100644 (file)
@@ -229,7 +229,7 @@ class DBConnectionError extends DBExpectedError {
 
                                        return;
                                }
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                // Do nothing, just use the default page
                        }
                }
index 430b20c..f02aa93 100644 (file)
@@ -58,7 +58,6 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
         */
        function open( $server, $user, $password, $dbName ) {
                global $wgAllDBsAreLocalhost, $wgSQLMode;
-               wfProfileIn( __METHOD__ );
 
                # Debugging hack -- fake cluster
                if ( $wgAllDBsAreLocalhost ) {
@@ -72,8 +71,6 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                $this->mPassword = $password;
                $this->mDBname = $dbName;
 
-               wfProfileIn( "dbconnect-$server" );
-
                # The kernel's default SYN retransmission period is far too slow for us,
                # so we use a short timeout plus a manual retry. Retrying means that a small
                # but finite rate of SYN packet loss won't cause user-visible errors.
@@ -82,15 +79,11 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                try {
                        $this->mConn = $this->mysqlConnect( $realServer );
                } catch ( Exception $ex ) {
-                       wfProfileOut( "dbconnect-$server" );
-                       wfProfileOut( __METHOD__ );
                        $this->restoreErrorHandler();
                        throw $ex;
                }
                $error = $this->restoreErrorHandler();
 
-               wfProfileOut( "dbconnect-$server" );
-
                # Always log connection errors
                if ( !$this->mConn ) {
                        if ( !$error ) {
@@ -107,8 +100,6 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                                "Server: $server, User: $user, Password: " .
                                substr( $password, 0, 3 ) . "..., error: " . $error . "\n" );
 
-                       wfProfileOut( __METHOD__ );
-
                        $this->reportConnectionError( $error );
                }
 
@@ -126,8 +117,6 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                                wfDebug( "Error selecting database $dbName on server {$this->mServer} " .
                                        "from client host " . wfHostname() . "\n" );
 
-                               wfProfileOut( __METHOD__ );
-
                                $this->reportConnectionError( "Error selecting database $dbName" );
                        }
                }
@@ -149,13 +138,11 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                                                'method' => __METHOD__,
                                        ) )
                                );
-                               wfProfileOut( __METHOD__ );
                                $this->reportConnectionError( "Error setting sql_mode to $mode" );
                        }
                }
 
                $this->mOpened = true;
-               wfProfileOut( __METHOD__ );
 
                return true;
        }
@@ -671,7 +658,6 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                        return '0'; // http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html
                }
 
-               wfProfileIn( __METHOD__ );
                # Commit any open transactions
                $this->commit( __METHOD__, 'flush' );
 
@@ -680,18 +666,15 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
 
                        if ( $wait > $timeout * 1e6 ) {
                                wfDebug( "Fake slave timed out waiting for $pos ($wait us)\n" );
-                               wfProfileOut( __METHOD__ );
 
                                return -1;
                        } elseif ( $wait > 0 ) {
                                wfDebug( "Fake slave waiting $wait us\n" );
                                usleep( $wait );
-                               wfProfileOut( __METHOD__ );
 
                                return 1;
                        } else {
                                wfDebug( "Fake slave up to date ($wait us)\n" );
-                               wfProfileOut( __METHOD__ );
 
                                return 0;
                        }
@@ -711,8 +694,6 @@ abstract class DatabaseMysqlBase extends DatabaseBase {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $status;
        }
 
index f1b3238..4c9fd32 100644 (file)
@@ -58,9 +58,14 @@ class LoadBalancer {
        private $mLaggedSlaveMode;
        /** @var string The last DB selection or connection error */
        private $mLastError = 'Unknown error';
+       /** @var integer Total connections opened */
+       private $connsOpened = 0;
        /** @var ProcessCacheLRU */
        private $mProcCache;
 
+       /** @var integer Warn when this many connection are held */
+       const CONN_HELD_WARN_THRESHOLD = 10;
+
        /**
         * @param array $params Array with keys:
         *   servers           Required. Array of server info structures.
@@ -224,8 +229,6 @@ class LoadBalancer {
                        return $this->mReadIndex;
                }
 
-               new ProfileSection( __METHOD__ );
-
                # Find the relevant load array
                if ( $group !== false ) {
                        if ( isset( $this->mGroupLoads[$group] ) ) {
@@ -340,7 +343,6 @@ class LoadBalancer {
         * @param DBMasterPos $pos
         */
        public function waitFor( $pos ) {
-               wfProfileIn( __METHOD__ );
                $this->mWaitForPos = $pos;
                $i = $this->mReadIndex;
 
@@ -350,7 +352,6 @@ class LoadBalancer {
                                $this->mLaggedSlaveMode = true;
                        }
                }
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -360,7 +361,6 @@ class LoadBalancer {
         * @return bool Success (able to connect and no timeouts reached)
         */
        public function waitForAll( $pos, $timeout = null ) {
-               wfProfileIn( __METHOD__ );
                $this->mWaitForPos = $pos;
                $serverCount = count( $this->mServers );
 
@@ -370,7 +370,6 @@ class LoadBalancer {
                                $ok = $this->doWait( $i, true, $timeout ) && $ok;
                        }
                }
-               wfProfileOut( __METHOD__ );
 
                return $ok;
        }
@@ -457,10 +456,7 @@ class LoadBalancer {
         * @return DatabaseBase
         */
        public function getConnection( $i, $groups = array(), $wiki = false ) {
-               wfProfileIn( __METHOD__ );
-
                if ( $i === null || $i === false ) {
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( 'Attempt to call ' . __METHOD__ .
                                ' with invalid server index' );
                }
@@ -498,7 +494,6 @@ class LoadBalancer {
                        # Couldn't find a working server in getReaderIndex()?
                        if ( $i === false ) {
                                $this->mLastError = 'No working slave server: ' . $this->mLastError;
-                               wfProfileOut( __METHOD__ );
 
                                return $this->reportConnectionError();
                        }
@@ -507,13 +502,10 @@ class LoadBalancer {
                # Now we have an explicit index into the servers array
                $conn = $this->openConnection( $i, $wiki );
                if ( !$conn ) {
-                       wfProfileOut( __METHOD__ );
 
                        return $this->reportConnectionError();
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $conn;
        }
 
@@ -613,10 +605,8 @@ class LoadBalancer {
         * @access private
         */
        public function openConnection( $i, $wiki = false ) {
-               wfProfileIn( __METHOD__ );
                if ( $wiki !== false ) {
                        $conn = $this->openForeignConnection( $i, $wiki );
-                       wfProfileOut( __METHOD__ );
 
                        return $conn;
                }
@@ -635,7 +625,6 @@ class LoadBalancer {
                                $conn = false;
                        }
                }
-               wfProfileOut( __METHOD__ );
 
                return $conn;
        }
@@ -659,7 +648,6 @@ class LoadBalancer {
         * @return DatabaseBase
         */
        private function openForeignConnection( $i, $wiki ) {
-               wfProfileIn( __METHOD__ );
                list( $dbName, $prefix ) = wfSplitWikiID( $wiki );
                if ( isset( $this->mConns['foreignUsed'][$i][$wiki] ) ) {
                        // Reuse an already-used connection
@@ -712,7 +700,6 @@ class LoadBalancer {
                        $refCount = $conn->getLBInfo( 'foreignPoolRefCount' );
                        $conn->setLBInfo( 'foreignPoolRefCount', $refCount + 1 );
                }
-               wfProfileOut( __METHOD__ );
 
                return $conn;
        }
@@ -752,6 +739,14 @@ class LoadBalancer {
                        $server['dbname'] = $dbNameOverride;
                }
 
+               // Log when many connection are made on requests
+               if ( ++$this->connsOpened >= self::CONN_HELD_WARN_THRESHOLD ) {
+                       $masterAddr = $this->getServerName( 0 );
+                       wfDebugLog( 'DBPerformance', __METHOD__ . ": " .
+                               "{$this->connsOpened}+ connections made (master=$masterAddr)\n" .
+                               wfBacktrace( true ) );
+               }
+
                # Create object
                try {
                        $db = DatabaseBase::factory( $server['type'], $server );
@@ -923,6 +918,7 @@ class LoadBalancer {
                        'foreignFree' => array(),
                        'foreignUsed' => array(),
                );
+               $this->connsOpened = 0;
        }
 
        /**
@@ -939,6 +935,7 @@ class LoadBalancer {
                                        if ( $conn === $candidateConn ) {
                                                $conn->close();
                                                unset( $this->mConns[$i1][$i2][$i3] );
+                                               --$this->connsOpened;
                                                $done = true;
                                                break;
                                        }
index b694a6f..91840dd 100644 (file)
@@ -93,8 +93,6 @@ class LoadMonitorMySQL implements LoadMonitor {
                        return array( 0 => 0 );
                }
 
-               $section = new ProfileSection( __METHOD__ );
-
                $expiry = 5;
                $requestRate = 10;
 
index b0c1899..42816dd 100644 (file)
@@ -82,13 +82,10 @@ class DeferredUpdates {
        public static function doUpdates( $commit = '' ) {
                global $wgDeferredUpdateList;
 
-               wfProfileIn( __METHOD__ );
-
                $updates = array_merge( $wgDeferredUpdateList, self::$updates );
 
                // No need to get master connections in case of empty updates array
                if ( !count( $updates ) ) {
-                       wfProfileOut( __METHOD__ );
 
                        return;
                }
@@ -110,7 +107,7 @@ class DeferredUpdates {
                                        if ( $doCommit && $dbw->trxLevel() ) {
                                                $dbw->commit( __METHOD__, 'flush' );
                                        }
-                               } catch ( MWException $e ) {
+                               } catch ( Exception $e ) {
                                        // We don't want exceptions thrown during deferred updates to
                                        // be reported to the user since the output is already sent.
                                        // Instead we just log them.
@@ -122,7 +119,6 @@ class DeferredUpdates {
                        $updates = array_merge( $wgDeferredUpdateList, self::$updates );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
index 54fa594..e02cfbc 100644 (file)
@@ -43,7 +43,6 @@ class HTMLCacheUpdate implements DeferrableUpdate {
        }
 
        public function doUpdate() {
-               wfProfileIn( __METHOD__ );
 
                $job = new HTMLCacheUpdateJob(
                        $this->mTitle,
@@ -65,6 +64,5 @@ class HTMLCacheUpdate implements DeferrableUpdate {
                        } );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 }
index 4e5af0b..822c964 100644 (file)
@@ -153,7 +153,6 @@ class LinksUpdate extends SqlDataUpdate {
        }
 
        protected function doIncrementalUpdate() {
-               wfProfileIn( __METHOD__ );
 
                # Page links
                $existing = $this->getExistingLinks();
@@ -227,7 +226,6 @@ class LinksUpdate extends SqlDataUpdate {
                        $this->queueRecursiveJobs();
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -251,7 +249,6 @@ class LinksUpdate extends SqlDataUpdate {
         * @param string $table Table to use (e.g. 'templatelinks')
         */
        public static function queueRecursiveJobsForTable( Title $title, $table ) {
-               wfProfileIn( __METHOD__ );
                if ( $title->getBacklinkCache()->hasLinks( $table ) ) {
                        $job = new RefreshLinksJob(
                                $title,
@@ -265,7 +262,6 @@ class LinksUpdate extends SqlDataUpdate {
                        JobQueueGroup::singleton()->push( $job );
                        JobQueueGroup::singleton()->deduplicateRootJob( $job );
                }
-               wfProfileOut( __METHOD__ );
        }
 
        /**
index 8808c20..ba14f09 100644 (file)
@@ -78,8 +78,6 @@ class SearchUpdate implements DeferrableUpdate {
                        return;
                }
 
-               wfProfileIn( __METHOD__ );
-
                $page = WikiPage::newFromID( $this->id, WikiPage::READ_LATEST );
 
                foreach ( SearchEngine::getSearchTypes() as $type ) {
@@ -108,7 +106,6 @@ class SearchUpdate implements DeferrableUpdate {
                        $search->update( $this->id, $normalTitle, $search->normalizeText( $text ) );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -125,7 +122,6 @@ class SearchUpdate implements DeferrableUpdate {
                $text = $wgContLang->normalizeForSearch( $text );
                $lc = SearchEngine::legalSearchChars() . '&#;';
 
-               wfProfileIn( __METHOD__ . '-regexps' );
                $text = preg_replace( "/<\\/?\\s*[A-Za-z][^>]*?>/",
                        ' ', $wgContLang->lc( " " . $text . " " ) ); # Strip HTML markup
                $text = preg_replace( "/(^|\\n)==\\s*([^\\n]+)\\s*==(\\s)/sD",
@@ -172,7 +168,6 @@ class SearchUpdate implements DeferrableUpdate {
 
                # Strip wiki '' and '''
                $text = preg_replace( "/''[']*/", " ", $text );
-               wfProfileOut( __METHOD__ . '-regexps' );
 
                return $text;
        }
index d4fc7a0..950a264 100644 (file)
@@ -110,8 +110,6 @@ class SquidUpdate {
                        self::HTCPPurge( $urlArr );
                }
 
-               wfProfileIn( __METHOD__ );
-
                // Remove duplicate URLs
                $urlArr = array_unique( $urlArr );
                // Maximum number of parallel connections per squid
@@ -137,7 +135,6 @@ class SquidUpdate {
                }
                $pool->run();
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -148,7 +145,6 @@ class SquidUpdate {
         */
        public static function HTCPPurge( $urlArr ) {
                global $wgHTCPRouting, $wgHTCPMulticastTTL;
-               wfProfileIn( __METHOD__ );
 
                // HTCP CLR operation
                $htcpOpCLR = 4;
@@ -166,7 +162,6 @@ class SquidUpdate {
                        $errstr = socket_strerror( socket_last_error() );
                        wfDebugLog( 'squid', __METHOD__ .
                                ": Error opening UDP socket: $errstr" );
-                       wfProfileOut( __METHOD__ );
 
                        return;
                }
@@ -188,7 +183,6 @@ class SquidUpdate {
 
                foreach ( $urlArr as $url ) {
                        if ( !is_string( $url ) ) {
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( 'Bad purge URL' );
                        }
                        $url = self::expand( $url );
@@ -205,7 +199,6 @@ class SquidUpdate {
                        }
                        foreach ( $conf as $subconf ) {
                                if ( !isset( $subconf['host'] ) || !isset( $subconf['port'] ) ) {
-                                       wfProfileOut( __METHOD__ );
                                        throw new MWException( "Invalid HTCP rule for URL $url\n" );
                                }
                        }
@@ -237,7 +230,6 @@ class SquidUpdate {
                                        $subconf['host'], $subconf['port'] );
                        }
                }
-               wfProfileOut( __METHOD__ );
        }
 
        /**
index 30534f0..d327433 100644 (file)
@@ -222,7 +222,6 @@ class DiffEngine {
         * @return DiffOp[]
         */
        public function diff( $from_lines, $to_lines ) {
-               wfProfileIn( __METHOD__ );
 
                // Diff and store locally
                $this->diffLocal( $from_lines, $to_lines );
@@ -272,7 +271,6 @@ class DiffEngine {
                                $edits[] = new DiffOpAdd( $add );
                        }
                }
-               wfProfileOut( __METHOD__ );
 
                return $edits;
        }
@@ -283,7 +281,6 @@ class DiffEngine {
         */
        private function diffLocal( $from_lines, $to_lines ) {
                global $wgExternalDiffEngine;
-               wfProfileIn( __METHOD__ );
 
                if ( $wgExternalDiffEngine == 'wikidiff3' ) {
                        // wikidiff3
@@ -346,7 +343,6 @@ class DiffEngine {
                        // Find the LCS.
                        $this->compareSeq( 0, count( $this->xv ), 0, count( $this->yv ) );
                }
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -582,7 +578,6 @@ class DiffEngine {
         * This is extracted verbatim from analyze.c (GNU diffutils-2.7).
         */
        private function shiftBoundaries( $lines, &$changed, $other_changed ) {
-               wfProfileIn( __METHOD__ );
                $i = 0;
                $j = 0;
 
@@ -697,7 +692,6 @@ class DiffEngine {
                                assert( '$j >= 0 && !$other_changed[$j]' );
                        }
                }
-               wfProfileOut( __METHOD__ );
        }
 }
 
@@ -858,7 +852,6 @@ class MappedDiff extends Diff {
         */
        public function __construct( $from_lines, $to_lines,
                $mapped_from_lines, $mapped_to_lines ) {
-               wfProfileIn( __METHOD__ );
 
                assert( 'count( $from_lines ) == count( $mapped_from_lines )' );
                assert( 'count( $to_lines ) == count( $mapped_to_lines )' );
@@ -880,7 +873,6 @@ class MappedDiff extends Diff {
                                $yi += count( $closing );
                        }
                }
-               wfProfileOut( __METHOD__ );
        }
 }
 
@@ -981,14 +973,12 @@ class WordLevelDiff extends MappedDiff {
         * @param string[] $closing_lines
         */
        public function __construct( $orig_lines, $closing_lines ) {
-               wfProfileIn( __METHOD__ );
 
                list( $orig_words, $orig_stripped ) = $this->split( $orig_lines );
                list( $closing_words, $closing_stripped ) = $this->split( $closing_lines );
 
                parent::__construct( $orig_words, $closing_words,
                        $orig_stripped, $closing_stripped );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -997,7 +987,6 @@ class WordLevelDiff extends MappedDiff {
         * @return array[]
         */
        private function split( $lines ) {
-               wfProfileIn( __METHOD__ );
 
                $words = array();
                $stripped = array();
@@ -1028,7 +1017,6 @@ class WordLevelDiff extends MappedDiff {
                                }
                        }
                }
-               wfProfileOut( __METHOD__ );
 
                return array( $words, $stripped );
        }
@@ -1037,7 +1025,6 @@ class WordLevelDiff extends MappedDiff {
         * @return string[]
         */
        public function orig() {
-               wfProfileIn( __METHOD__ );
                $orig = new HWLDFWordAccumulator;
 
                foreach ( $this->edits as $edit ) {
@@ -1048,7 +1035,6 @@ class WordLevelDiff extends MappedDiff {
                        }
                }
                $lines = $orig->getLines();
-               wfProfileOut( __METHOD__ );
 
                return $lines;
        }
@@ -1057,7 +1043,6 @@ class WordLevelDiff extends MappedDiff {
         * @return string[]
         */
        public function closing() {
-               wfProfileIn( __METHOD__ );
                $closing = new HWLDFWordAccumulator;
 
                foreach ( $this->edits as $edit ) {
@@ -1068,7 +1053,6 @@ class WordLevelDiff extends MappedDiff {
                        }
                }
                $lines = $closing->getLines();
-               wfProfileOut( __METHOD__ );
 
                return $lines;
        }
index 40df0d7..33ca931 100644 (file)
@@ -57,7 +57,6 @@ abstract class DiffFormatter {
         * @return string The formatted output.
         */
        public function format( $diff ) {
-               wfProfileIn( __METHOD__ );
 
                $xi = $yi = 1;
                $block = false;
@@ -115,7 +114,6 @@ abstract class DiffFormatter {
                }
 
                $end = $this->endDiff();
-               wfProfileOut( __METHOD__ );
 
                return $end;
        }
@@ -130,7 +128,6 @@ abstract class DiffFormatter {
         * @throws MWException If the edit type is not known.
         */
        protected function block( $xbeg, $xlen, $ybeg, $ylen, &$edits ) {
-               wfProfileIn( __METHOD__ );
                $this->startBlock( $this->blockHeader( $xbeg, $xlen, $ybeg, $ylen ) );
                foreach ( $edits as $edit ) {
                        if ( $edit->type == 'copy' ) {
@@ -146,7 +143,6 @@ abstract class DiffFormatter {
                        }
                }
                $this->endBlock();
-               wfProfileOut( __METHOD__ );
        }
 
        protected function startDiff() {
index a458831..90a2785 100644 (file)
@@ -232,7 +232,6 @@ class DifferenceEngine extends ContextSource {
        }
 
        public function showDiffPage( $diffOnly = false ) {
-               wfProfileIn( __METHOD__ );
 
                # Allow frames except in certain special cases
                $out = $this->getOutput();
@@ -241,7 +240,6 @@ class DifferenceEngine extends ContextSource {
 
                if ( !$this->loadRevisionData() ) {
                        $this->showMissingRevision();
-                       wfProfileOut( __METHOD__ );
 
                        return;
                }
@@ -253,7 +251,6 @@ class DifferenceEngine extends ContextSource {
                                $this->mOldPage->getUserPermissionsErrors( 'read', $user ) );
                }
                if ( count( $permErrors ) ) {
-                       wfProfileOut( __METHOD__ );
                        throw new PermissionsError( 'read', $permErrors );
                }
 
@@ -454,7 +451,6 @@ class DifferenceEngine extends ContextSource {
                                $this->renderNewRevision();
                        }
                }
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -547,7 +543,6 @@ class DifferenceEngine extends ContextSource {
         * Show the new revision of the page.
         */
        public function renderNewRevision() {
-               wfProfileIn( __METHOD__ );
                $out = $this->getOutput();
                $revHeader = $this->getRevisionHeader( $this->mNewRev );
                # Add "current version as of X" title
@@ -605,7 +600,6 @@ class DifferenceEngine extends ContextSource {
                # Add redundant patrol link on bottom...
                $out->addHTML( $this->markPatrolledLink() );
 
-               wfProfileOut( __METHOD__ );
        }
 
        protected function getParserOutput( WikiPage $page, Revision $rev ) {
@@ -684,23 +678,19 @@ class DifferenceEngine extends ContextSource {
         */
        public function getDiffBody() {
                global $wgMemc;
-               wfProfileIn( __METHOD__ );
                $this->mCacheHit = true;
                // Check if the diff should be hidden from this user
                if ( !$this->loadRevisionData() ) {
-                       wfProfileOut( __METHOD__ );
 
                        return false;
                } elseif ( $this->mOldRev &&
                        !$this->mOldRev->userCan( Revision::DELETED_TEXT, $this->getUser() )
                ) {
-                       wfProfileOut( __METHOD__ );
 
                        return false;
                } elseif ( $this->mNewRev &&
                        !$this->mNewRev->userCan( Revision::DELETED_TEXT, $this->getUser() )
                ) {
-                       wfProfileOut( __METHOD__ );
 
                        return false;
                }
@@ -708,7 +698,6 @@ class DifferenceEngine extends ContextSource {
                if ( $this->mOldRev === false || ( $this->mOldRev && $this->mNewRev
                        && $this->mOldRev->getID() == $this->mNewRev->getID() )
                ) {
-                       wfProfileOut( __METHOD__ );
 
                        return '';
                }
@@ -724,7 +713,6 @@ class DifferenceEngine extends ContextSource {
                                        wfIncrStats( 'diff_cache_hit' );
                                        $difftext = $this->localiseLineNumbers( $difftext );
                                        $difftext .= "\n<!-- diff cache key $key -->\n";
-                                       wfProfileOut( __METHOD__ );
 
                                        return $difftext;
                                }
@@ -734,7 +722,6 @@ class DifferenceEngine extends ContextSource {
 
                // Loadtext is permission safe, this just clears out the diff
                if ( !$this->loadText() ) {
-                       wfProfileOut( __METHOD__ );
 
                        return false;
                }
@@ -754,7 +741,6 @@ class DifferenceEngine extends ContextSource {
                if ( $difftext !== false ) {
                        $difftext = $this->localiseLineNumbers( $difftext );
                }
-               wfProfileOut( __METHOD__ );
 
                return $difftext;
        }
@@ -840,8 +826,6 @@ class DifferenceEngine extends ContextSource {
        public function generateTextDiffBody( $otext, $ntext ) {
                global $wgExternalDiffEngine, $wgContLang;
 
-               wfProfileIn( __METHOD__ );
-
                $otext = str_replace( "\r\n", "\n", $otext );
                $ntext = str_replace( "\r\n", "\n", $ntext );
 
@@ -850,7 +834,6 @@ class DifferenceEngine extends ContextSource {
                        # input text to be HTML-escaped already
                        $otext = htmlspecialchars( $wgContLang->segmentForDiff( $otext ) );
                        $ntext = htmlspecialchars( $wgContLang->segmentForDiff( $ntext ) );
-                       wfProfileOut( __METHOD__ );
 
                        return $wgContLang->unsegmentForDiff( wikidiff_do_diff( $otext, $ntext, 2 ) ) .
                        $this->debug( 'wikidiff1' );
@@ -859,11 +842,8 @@ class DifferenceEngine extends ContextSource {
                if ( $wgExternalDiffEngine == 'wikidiff2' && function_exists( 'wikidiff2_do_diff' ) ) {
                        # Better external diff engine, the 2 may some day be dropped
                        # This one does the escaping and segmenting itself
-                       wfProfileIn( 'wikidiff2_do_diff' );
                        $text = wikidiff2_do_diff( $otext, $ntext, 2 );
                        $text .= $this->debug( 'wikidiff2' );
-                       wfProfileOut( 'wikidiff2_do_diff' );
-                       wfProfileOut( __METHOD__ );
 
                        return $text;
                }
@@ -875,13 +855,11 @@ class DifferenceEngine extends ContextSource {
 
                        $tempFile1 = fopen( $tempName1, "w" );
                        if ( !$tempFile1 ) {
-                               wfProfileOut( __METHOD__ );
 
                                return false;
                        }
                        $tempFile2 = fopen( $tempName2, "w" );
                        if ( !$tempFile2 ) {
-                               wfProfileOut( __METHOD__ );
 
                                return false;
                        }
@@ -890,13 +868,10 @@ class DifferenceEngine extends ContextSource {
                        fclose( $tempFile1 );
                        fclose( $tempFile2 );
                        $cmd = wfEscapeShellArg( $wgExternalDiffEngine, $tempName1, $tempName2 );
-                       wfProfileIn( __METHOD__ . "-shellexec" );
                        $difftext = wfShellExec( $cmd );
                        $difftext .= $this->debug( "external $wgExternalDiffEngine" );
-                       wfProfileOut( __METHOD__ . "-shellexec" );
                        unlink( $tempName1 );
                        unlink( $tempName2 );
-                       wfProfileOut( __METHOD__ );
 
                        return $difftext;
                }
@@ -906,8 +881,7 @@ class DifferenceEngine extends ContextSource {
                $nta = explode( "\n", $wgContLang->segmentForDiff( $ntext ) );
                $diffs = new Diff( $ota, $nta );
                $formatter = new TableDiffFormatter();
-               $difftext = $wgContLang->unsegmentForDiff( $formatter->format( $diffs ) ) .
-                       wfProfileOut( __METHOD__ );
+               $difftext = $wgContLang->unsegmentForDiff( $formatter->format( $diffs ) );
 
                return $difftext;
        }
index db7318f..e5155bf 100644 (file)
@@ -190,7 +190,6 @@ class TableDiffFormatter extends DiffFormatter {
         * @param string[] $closing
         */
        protected function changed( $orig, $closing ) {
-               wfProfileIn( __METHOD__ );
 
                $diff = new WordLevelDiff( $orig, $closing );
                $del = $diff->orig();
@@ -208,7 +207,6 @@ class TableDiffFormatter extends DiffFormatter {
                        echo '<tr>' . $this->emptyLine() .
                                $this->addedLine( $line ) . "</tr>\n";
                }
-               wfProfileOut( __METHOD__ );
        }
 
 }
index 83801b6..5ea9359 100644 (file)
@@ -142,7 +142,7 @@ class MWExceptionHandler {
         *
         *   try {
         *       ...
-        *   } catch ( MWException $e ) {
+        *   } catch ( Exception $e ) {
         *       $e->report();
         *   } catch ( Exception $e ) {
         *       echo $e->__toString();
@@ -493,5 +493,10 @@ TXT;
                } else {
                        wfDebugLog( 'error', $log );
                }
+
+               $json = self::jsonSerializeException( $e, false, FormatJson::ALL_OK );
+               if ( $json !== false ) {
+                       wfDebugLog( 'error-json', $json, 'private' );
+               }
        }
 }
index 688130e..ea04cc8 100644 (file)
@@ -197,7 +197,7 @@ class ExternalStore {
                        }
                        try {
                                $url = $store->store( $path, $data ); // Try to save the object
-                       } catch ( MWException $error ) {
+                       } catch ( Exception $error ) {
                                $url = false;
                        }
                        if ( strlen( $url ) ) {
index 1659c62..6ee9b2e 100644 (file)
@@ -104,7 +104,6 @@ class FSFile {
         * @return array
         */
        public function getProps( $ext = true ) {
-               wfProfileIn( __METHOD__ );
                wfDebug( __METHOD__ . ": Getting file info for $this->path\n" );
 
                $info = self::placeholderProps();
@@ -146,8 +145,6 @@ class FSFile {
                        wfDebug( __METHOD__ . ": $this->path NOT FOUND!\n" );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $info;
        }
 
@@ -201,10 +198,8 @@ class FSFile {
         * @return bool|string False on failure
         */
        public function getSha1Base36( $recache = false ) {
-               wfProfileIn( __METHOD__ );
 
                if ( $this->sha1Base36 !== null && !$recache ) {
-                       wfProfileOut( __METHOD__ );
 
                        return $this->sha1Base36;
                }
@@ -217,8 +212,6 @@ class FSFile {
                        $this->sha1Base36 = wfBaseConvert( $this->sha1Base36, 16, 36, 31 );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $this->sha1Base36;
        }
 
index 06fb2c6..a3b0009 100644 (file)
@@ -118,7 +118,7 @@ abstract class FileBackendStore extends FileBackend {
         * @return Status
         */
        final public function createInternal( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                if ( strlen( $params['content'] ) > $this->maxFileSizeInternal() ) {
                        $status = Status::newFatal( 'backend-fail-maxsize',
                                $params['dst'], $this->maxFileSizeInternal() );
@@ -159,7 +159,7 @@ abstract class FileBackendStore extends FileBackend {
         * @return Status
         */
        final public function storeInternal( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                if ( filesize( $params['src'] ) > $this->maxFileSizeInternal() ) {
                        $status = Status::newFatal( 'backend-fail-maxsize',
                                $params['dst'], $this->maxFileSizeInternal() );
@@ -201,7 +201,7 @@ abstract class FileBackendStore extends FileBackend {
         * @return Status
         */
        final public function copyInternal( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $status = $this->doCopyInternal( $params );
                $this->clearCache( array( $params['dst'] ) );
                if ( !isset( $params['dstExists'] ) || $params['dstExists'] ) {
@@ -233,7 +233,7 @@ abstract class FileBackendStore extends FileBackend {
         * @return Status
         */
        final public function deleteInternal( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $status = $this->doDeleteInternal( $params );
                $this->clearCache( array( $params['src'] ) );
                $this->deleteFileCache( $params['src'] ); // persistent cache
@@ -267,7 +267,7 @@ abstract class FileBackendStore extends FileBackend {
         * @return Status
         */
        final public function moveInternal( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $status = $this->doMoveInternal( $params );
                $this->clearCache( array( $params['src'], $params['dst'] ) );
                $this->deleteFileCache( $params['src'] ); // persistent cache
@@ -313,7 +313,7 @@ abstract class FileBackendStore extends FileBackend {
         * @return Status
         */
        final public function describeInternal( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                if ( count( $params['headers'] ) ) {
                        $status = $this->doDescribeInternal( $params );
                        $this->clearCache( array( $params['src'] ) );
@@ -346,7 +346,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final public function concatenate( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $status = Status::newGood();
 
                // Try to lock the source files for the scope of this function
@@ -439,7 +439,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final protected function doPrepare( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $status = Status::newGood();
 
                list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( $params['dir'] );
@@ -474,7 +474,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final protected function doSecure( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $status = Status::newGood();
 
                list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( $params['dir'] );
@@ -509,7 +509,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final protected function doPublish( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $status = Status::newGood();
 
                list( $fullCont, $dir, $shard ) = $this->resolveStoragePath( $params['dir'] );
@@ -544,7 +544,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final protected function doClean( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $status = Status::newGood();
 
                // Recursive: first delete all empty subdirs recursively
@@ -600,21 +600,21 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final public function fileExists( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $stat = $this->getFileStat( $params );
 
                return ( $stat === null ) ? null : (bool)$stat; // null => failure
        }
 
        final public function getFileTimestamp( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $stat = $this->getFileStat( $params );
 
                return $stat ? $stat['mtime'] : false;
        }
 
        final public function getFileSize( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $stat = $this->getFileStat( $params );
 
                return $stat ? $stat['size'] : false;
@@ -625,7 +625,7 @@ abstract class FileBackendStore extends FileBackend {
                if ( $path === null ) {
                        return false; // invalid storage path
                }
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $latest = !empty( $params['latest'] ); // use latest data?
                if ( !$this->cheapCache->has( $path, 'stat', self::CACHE_TTL ) ) {
                        $this->primeFileCache( array( $path ) ); // check persistent cache
@@ -644,9 +644,7 @@ abstract class FileBackendStore extends FileBackend {
                                }
                        }
                }
-               wfProfileIn( __METHOD__ . '-miss-' . $this->name );
                $stat = $this->doGetFileStat( $params );
-               wfProfileOut( __METHOD__ . '-miss-' . $this->name );
                if ( is_array( $stat ) ) { // file exists
                        // Strongly consistent backends can automatically set "latest"
                        $stat['latest'] = isset( $stat['latest'] ) ? $stat['latest'] : $latest;
@@ -679,7 +677,7 @@ abstract class FileBackendStore extends FileBackend {
        abstract protected function doGetFileStat( array $params );
 
        public function getFileContentsMulti( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
 
                $params = $this->setConcurrencyFlags( $params );
                $contents = $this->doGetFileContentsMulti( $params );
@@ -708,7 +706,7 @@ abstract class FileBackendStore extends FileBackend {
                if ( $path === null ) {
                        return false; // invalid storage path
                }
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $latest = !empty( $params['latest'] ); // use latest data?
                if ( $this->cheapCache->has( $path, 'xattr', self::CACHE_TTL ) ) {
                        $stat = $this->cheapCache->get( $path, 'xattr' );
@@ -718,12 +716,8 @@ abstract class FileBackendStore extends FileBackend {
                                return $stat['map'];
                        }
                }
-               wfProfileIn( __METHOD__ . '-miss' );
-               wfProfileIn( __METHOD__ . '-miss-' . $this->name );
                $fields = $this->doGetFileXAttributes( $params );
                $fields = is_array( $fields ) ? self::normalizeXAttributes( $fields ) : false;
-               wfProfileOut( __METHOD__ . '-miss-' . $this->name );
-               wfProfileOut( __METHOD__ . '-miss' );
                $this->cheapCache->set( $path, 'xattr', array( 'map' => $fields, 'latest' => $latest ) );
 
                return $fields;
@@ -742,7 +736,7 @@ abstract class FileBackendStore extends FileBackend {
                if ( $path === null ) {
                        return false; // invalid storage path
                }
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $latest = !empty( $params['latest'] ); // use latest data?
                if ( $this->cheapCache->has( $path, 'sha1', self::CACHE_TTL ) ) {
                        $stat = $this->cheapCache->get( $path, 'sha1' );
@@ -752,9 +746,7 @@ abstract class FileBackendStore extends FileBackend {
                                return $stat['hash'];
                        }
                }
-               wfProfileIn( __METHOD__ . '-miss-' . $this->name );
                $hash = $this->doGetFileSha1Base36( $params );
-               wfProfileOut( __METHOD__ . '-miss-' . $this->name );
                $this->cheapCache->set( $path, 'sha1', array( 'hash' => $hash, 'latest' => $latest ) );
 
                return $hash;
@@ -775,7 +767,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final public function getFileProps( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $fsFile = $this->getLocalReference( $params );
                $props = $fsFile ? $fsFile->getProps() : FSFile::placeholderProps();
 
@@ -783,7 +775,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final public function getLocalReferenceMulti( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
 
                $params = $this->setConcurrencyFlags( $params );
 
@@ -826,7 +818,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final public function getLocalCopyMulti( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
 
                $params = $this->setConcurrencyFlags( $params );
                $tmpFiles = $this->doGetLocalCopyMulti( $params );
@@ -851,7 +843,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final public function streamFile( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $status = Status::newGood();
 
                $info = $this->getFileStat( $params );
@@ -865,9 +857,7 @@ abstract class FileBackendStore extends FileBackend {
                if ( $res == StreamFile::NOT_MODIFIED ) {
                        // do nothing; client cache is up to date
                } elseif ( $res == StreamFile::READY_STREAM ) {
-                       wfProfileIn( __METHOD__ . '-send-' . $this->name );
                        $status = $this->doStreamFile( $params );
-                       wfProfileOut( __METHOD__ . '-send-' . $this->name );
                        if ( !$status->isOK() ) {
                                // Per bug 41113, nasty things can happen if bad cache entries get
                                // stuck in cache. It's also possible that this error can come up
@@ -1071,7 +1061,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final protected function doOperationsInternal( array $ops, array $opts ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $status = Status::newGood();
 
                // Fix up custom header name/value pairs...
@@ -1137,7 +1127,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final protected function doQuickOperationsInternal( array $ops ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $status = Status::newGood();
 
                // Fix up custom header name/value pairs...
@@ -1204,7 +1194,7 @@ abstract class FileBackendStore extends FileBackend {
         * @return array Map of Status objects
         */
        final public function executeOpHandlesInternal( array $fileOpHandles ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
 
                foreach ( $fileOpHandles as $fileOpHandle ) {
                        if ( !( $fileOpHandle instanceof FileBackendStoreOpHandle ) ) {
@@ -1300,7 +1290,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        final public function preloadFileStat( array $params ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                $success = true; // no network errors
 
                $params['concurrency'] = ( $this->parallelize !== 'off' ) ? $this->concurrency : 1;
@@ -1623,7 +1613,7 @@ abstract class FileBackendStore extends FileBackend {
         * @param array $items
         */
        final protected function primeContainerCache( array $items ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
 
                $paths = array(); // list of storage paths
                $contNames = array(); // (cache key => resolved container name)
@@ -1733,7 +1723,7 @@ abstract class FileBackendStore extends FileBackend {
         * @param array $items List of storage paths
         */
        final protected function primeFileCache( array $items ) {
-               $section = new ProfileSection( __METHOD__ . "-{$this->name}" );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
 
                $paths = array(); // list of storage paths
                $pathNames = array(); // (cache key => storage path)
index b0d83e0..faa1314 100644 (file)
@@ -55,7 +55,6 @@ class FileOpBatch {
         * @return Status
         */
        public static function attempt( array $performOps, array $opts, FileJournal $journal ) {
-               $section = new ProfileSection( __METHOD__ );
                $status = Status::newGood();
 
                $n = count( $performOps );
index 7234474..2637b5a 100644 (file)
@@ -647,7 +647,7 @@ class SwiftFileBackend extends FileBackendStore {
                        $timestamp = new MWTimestamp( $ts );
 
                        return $timestamp->getTimestamp( $format );
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        throw new FileBackendError( $e->getMessage() );
                }
        }
@@ -664,7 +664,7 @@ class SwiftFileBackend extends FileBackendStore {
                        return $objHdrs; // nothing to do
                }
 
-               $section = new ProfileSection( __METHOD__ . '-' . $this->name );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
                trigger_error( "$path was not stored with SHA-1 metadata.", E_USER_WARNING );
 
                $auth = $this->getAuthentication();
@@ -798,7 +798,7 @@ class SwiftFileBackend extends FileBackendStore {
                        return $dirs; // nothing more
                }
 
-               $section = new ProfileSection( __METHOD__ . '-' . $this->name );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
 
                $prefix = ( $dir == '' ) ? null : "{$dir}/";
                // Non-recursive: only list dirs right under $dir
@@ -878,7 +878,7 @@ class SwiftFileBackend extends FileBackendStore {
                        return $files; // nothing more
                }
 
-               $section = new ProfileSection( __METHOD__ . '-' . $this->name );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
 
                $prefix = ( $dir == '' ) ? null : "{$dir}/";
                // $objects will contain a list of unfiltered names or CF_Object items
@@ -1272,7 +1272,7 @@ class SwiftFileBackend extends FileBackendStore {
         * @return array|bool|null False on 404, null on failure
         */
        protected function getContainerStat( $container, $bypassCache = false ) {
-               $section = new ProfileSection( __METHOD__ . '-' . $this->name );
+               $ps = Profiler::instance()->scopedProfileIn( __METHOD__ . "-{$this->name}" );
 
                if ( $bypassCache ) { // purge cache
                        $this->containerStatCache->clear( $container );
@@ -1285,13 +1285,11 @@ class SwiftFileBackend extends FileBackendStore {
                                return null;
                        }
 
-                       wfProfileIn( __METHOD__ . "-{$this->name}-miss" );
                        list( $rcode, $rdesc, $rhdrs, $rbody, $rerr ) = $this->http->run( array(
                                'method' => 'HEAD',
                                'url' => $this->storageUrl( $auth, $container ),
                                'headers' => $this->authTokenHeaders( $auth )
                        ) );
-                       wfProfileOut( __METHOD__ . "-{$this->name}-miss" );
 
                        if ( $rcode === 204 ) {
                                $stat = array(
index 1b68130..791be7f 100644 (file)
@@ -55,7 +55,6 @@ class TempFSFile extends FSFile {
         * @return TempFSFile|null
         */
        public static function factory( $prefix, $extension = '' ) {
-               wfProfileIn( __METHOD__ );
                $base = wfTempDir() . '/' . $prefix . wfRandomString( 12 );
                $ext = ( $extension != '' ) ? ".{$extension}" : "";
                for ( $attempt = 1; true; $attempt++ ) {
@@ -68,14 +67,12 @@ class TempFSFile extends FSFile {
                                break; // got it
                        }
                        if ( $attempt >= 5 ) {
-                               wfProfileOut( __METHOD__ );
 
                                return null; // give up
                        }
                }
                $tmpFile = new self( $path );
                $tmpFile->autocollect(); // safely instantiated
-               wfProfileOut( __METHOD__ );
 
                return $tmpFile;
        }
index affcf44..39a5563 100644 (file)
@@ -97,7 +97,7 @@ abstract class DBLockManager extends QuorumLockManager {
                                // connection timeouts. This is useless if each bucket has one peer.
                                try {
                                        $this->statusCache = ObjectCache::newAccelerator( array() );
-                               } catch ( MWException $e ) {
+                               } catch ( Exception $e ) {
                                        trigger_error( __CLASS__ .
                                                " using multiple DB peers without apc, xcache, or wincache." );
                                }
index 9253f2e..615ba77 100644 (file)
@@ -102,7 +102,6 @@ abstract class LockManager {
         * @since 1.22
         */
        final public function lockByType( array $pathsByType, $timeout = 0 ) {
-               wfProfileIn( __METHOD__ );
                $status = Status::newGood();
                $pathsByType = $this->normalizePathsByType( $pathsByType );
                $msleep = array( 0, 50, 100, 300, 500 ); // retry backoff times
@@ -116,7 +115,6 @@ abstract class LockManager {
                        usleep( 1e3 * ( next( $msleep ) ?: 1000 ) ); // use 1 sec after enough times
                        $elapsed = microtime( true ) - $start;
                } while ( $elapsed < $timeout && $elapsed >= 0 );
-               wfProfileOut( __METHOD__ );
 
                return $status;
        }
@@ -140,10 +138,8 @@ abstract class LockManager {
         * @since 1.22
         */
        final public function unlockByType( array $pathsByType ) {
-               wfProfileIn( __METHOD__ );
                $pathsByType = $this->normalizePathsByType( $pathsByType );
                $status = $this->doUnlockByType( $pathsByType );
-               wfProfileOut( __METHOD__ );
 
                return $status;
        }
index 600421f..df85f9c 100644 (file)
@@ -471,8 +471,6 @@ abstract class File {
        public function getThumbnailBucket( $desiredWidth, $page = 1 ) {
                global $wgThumbnailBuckets, $wgThumbnailMinimumBucketDistance;
 
-               wfDebugLog( 'thumbnail', 'thumbnail buckets ' . json_encode( $wgThumbnailBuckets ) );
-
                $imageWidth = $this->getWidth( $page );
 
                if ( $imageWidth === false ) {
@@ -998,7 +996,6 @@ abstract class File {
        function transform( $params, $flags = 0 ) {
                global $wgThumbnailEpoch;
 
-               wfProfileIn( __METHOD__ );
                do {
                        if ( !$this->canRender() ) {
                                $thumb = $this->iconThumb();
@@ -1071,8 +1068,6 @@ abstract class File {
                        }
                } while ( false );
 
-               wfProfileOut( __METHOD__ );
-
                return is_object( $thumb ) ? $thumb : false;
        }
 
@@ -1102,9 +1097,7 @@ abstract class File {
                }
 
                // Actually render the thumbnail...
-               wfProfileIn( __METHOD__ . '-doTransform' );
                $thumb = $handler->doTransform( $this, $tmpThumbPath, $thumbUrl, $transformParams );
-               wfProfileOut( __METHOD__ . '-doTransform' );
                $tmpFile->bind( $thumb ); // keep alive with $thumb
 
                if ( !$thumb ) { // bad params?
index eb0f654..b2e5b00 100644 (file)
@@ -247,13 +247,11 @@ class LocalFile extends File {
        function loadFromCache() {
                global $wgMemc;
 
-               wfProfileIn( __METHOD__ );
                $this->dataLoaded = false;
                $this->extraDataLoaded = false;
                $key = $this->getCacheKey();
 
                if ( !$key ) {
-                       wfProfileOut( __METHOD__ );
 
                        return false;
                }
@@ -280,8 +278,6 @@ class LocalFile extends File {
                        wfIncrStats( 'image_cache_miss' );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $this->dataLoaded;
        }
 
@@ -382,9 +378,7 @@ class LocalFile extends File {
         * @param int $flags
         */
        function loadFromDB( $flags = 0 ) {
-               # Polymorphic function name to distinguish foreign and local fetches
                $fname = get_class( $this ) . '::' . __FUNCTION__;
-               wfProfileIn( $fname );
 
                # Unconditionally set loaded=true, we don't want the accessors constantly rechecking
                $this->dataLoaded = true;
@@ -402,8 +396,6 @@ class LocalFile extends File {
                } else {
                        $this->fileExists = false;
                }
-
-               wfProfileOut( $fname );
        }
 
        /**
@@ -411,9 +403,7 @@ class LocalFile extends File {
         * This covers fields that are sometimes not cached.
         */
        protected function loadExtraFromDB() {
-               # Polymorphic function name to distinguish foreign and local fetches
                $fname = get_class( $this ) . '::' . __FUNCTION__;
-               wfProfileIn( $fname );
 
                # Unconditionally set loaded=true, we don't want the accessors constantly rechecking
                $this->extraDataLoaded = true;
@@ -428,11 +418,8 @@ class LocalFile extends File {
                                $this->$name = $value;
                        }
                } else {
-                       wfProfileOut( $fname );
                        throw new MWException( "Could not find data for image '{$this->getName()}'." );
                }
-
-               wfProfileOut( $fname );
        }
 
        /**
@@ -587,7 +574,6 @@ class LocalFile extends File {
         * Fix assorted version-related problems with the image row by reloading it from the file
         */
        function upgradeRow() {
-               wfProfileIn( __METHOD__ );
 
                $this->lock(); // begin
 
@@ -597,7 +583,6 @@ class LocalFile extends File {
                if ( !$this->fileExists ) {
                        $this->unlock();
                        wfDebug( __METHOD__ . ": file does not exist, aborting\n" );
-                       wfProfileOut( __METHOD__ );
 
                        return;
                }
@@ -607,7 +592,6 @@ class LocalFile extends File {
 
                if ( wfReadOnly() ) {
                        $this->unlock();
-                       wfProfileOut( __METHOD__ );
 
                        return;
                }
@@ -633,7 +617,6 @@ class LocalFile extends File {
 
                $this->unlock(); // done
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -889,7 +872,6 @@ class LocalFile extends File {
         * @note This used to purge old thumbnails by default as well, but doesn't anymore.
         */
        function purgeCache( $options = array() ) {
-               wfProfileIn( __METHOD__ );
                // Refresh metadata cache
                $this->purgeMetadataCache();
 
@@ -898,7 +880,6 @@ class LocalFile extends File {
 
                // Purge squid cache for this file
                SquidUpdate::purge( array( $this->getURL() ) );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -907,7 +888,6 @@ class LocalFile extends File {
         */
        function purgeOldThumbnails( $archiveName ) {
                global $wgUseSquid;
-               wfProfileIn( __METHOD__ );
 
                // Get a list of old thumbnails and URLs
                $files = $this->getThumbnails( $archiveName );
@@ -927,7 +907,6 @@ class LocalFile extends File {
                        SquidUpdate::purge( $urls );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -936,7 +915,6 @@ class LocalFile extends File {
         */
        function purgeThumbnails( $options = array() ) {
                global $wgUseSquid;
-               wfProfileIn( __METHOD__ );
 
                // Delete thumbnails
                $files = $this->getThumbnails();
@@ -968,7 +946,6 @@ class LocalFile extends File {
                        SquidUpdate::purge( $urls );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -1146,7 +1123,6 @@ class LocalFile extends File {
                }
 
                if ( !$props ) {
-                       wfProfileIn( __METHOD__ . '-getProps' );
                        if ( $this->repo->isVirtualUrl( $srcPath )
                                || FileBackend::isStoragePath( $srcPath )
                        ) {
@@ -1154,7 +1130,6 @@ class LocalFile extends File {
                        } else {
                                $props = FSFile::getPropsFromPath( $srcPath );
                        }
-                       wfProfileOut( __METHOD__ . '-getProps' );
                }
 
                $options = array();
@@ -1236,7 +1211,6 @@ class LocalFile extends File {
        function recordUpload2( $oldver, $comment, $pageText, $props = false, $timestamp = false,
                $user = null
        ) {
-               wfProfileIn( __METHOD__ );
 
                if ( is_null( $user ) ) {
                        global $wgUser;
@@ -1247,9 +1221,7 @@ class LocalFile extends File {
                $dbw->begin( __METHOD__ );
 
                if ( !$props ) {
-                       wfProfileIn( __METHOD__ . '-getProps' );
                        $props = $this->repo->getFileProps( $this->getVirtualUrl() );
-                       wfProfileOut( __METHOD__ . '-getProps' );
                }
 
                # Imports or such might force a certain timestamp; otherwise we generate
@@ -1271,7 +1243,6 @@ class LocalFile extends File {
                if ( !$this->fileExists ) {
                        wfDebug( __METHOD__ . ": File " . $this->getRel() . " went missing!\n" );
                        $dbw->rollback( __METHOD__ );
-                       wfProfileOut( __METHOD__ );
 
                        return false;
                }
@@ -1406,12 +1377,14 @@ class LocalFile extends File {
                        // Page exists, do RC entry now (otherwise we wait for later).
                        $logEntry->publish( $logId );
                }
-               wfProfileIn( __METHOD__ . '-edit' );
 
                if ( $exists ) {
                        # Create a null revision
                        $latest = $descTitle->getLatestRevID();
-                       $editSummary = LogFormatter::newFromEntry( $logEntry )->getPlainActionText();
+                       // Use own context to get the action text in content language
+                       $formatter = LogFormatter::newFromEntry( $logEntry );
+                       $formatter->setContext( RequestContext::newExtraneousContext( $descTitle ) );
+                       $editSummary = $formatter->getPlainActionText();
 
                        $nullRevision = Revision::newNullRevision(
                                $dbw,
@@ -1470,22 +1443,16 @@ class LocalFile extends File {
                        $dbw->commit( __METHOD__ ); // commit before anything bad can happen
                }
 
-               wfProfileOut( __METHOD__ . '-edit' );
-
                if ( $reupload ) {
                        # Delete old thumbnails
-                       wfProfileIn( __METHOD__ . '-purge' );
                        $this->purgeThumbnails();
-                       wfProfileOut( __METHOD__ . '-purge' );
 
                        # Remove the old file from the squid cache
                        SquidUpdate::purge( array( $this->getURL() ) );
                }
 
                # Hooks, hooks, the magic of hooks...
-               wfProfileIn( __METHOD__ . '-hooks' );
                Hooks::run( 'FileUpload', array( $this, $reupload, $descTitle->exists() ) );
-               wfProfileOut( __METHOD__ . '-hooks' );
 
                # Invalidate cache for all pages using this file
                $update = new HTMLCacheUpdate( $this->getTitle(), 'imagelinks' );
@@ -1494,8 +1461,6 @@ class LocalFile extends File {
                        LinksUpdate::queueRecursiveJobsForTable( $this->getTitle(), 'imagelinks' );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return true;
        }
 
@@ -2240,7 +2205,6 @@ class LocalFileDeleteBatch {
         * @return FileRepoStatus
         */
        function execute() {
-               wfProfileIn( __METHOD__ );
 
                $this->file->lock();
 
@@ -2289,7 +2253,6 @@ class LocalFileDeleteBatch {
                        // Roll back inserts, release lock and abort
                        // TODO: delete the defunct filearchive rows if we are using a non-transactional DB
                        $this->file->unlockAndRollback();
-                       wfProfileOut( __METHOD__ );
 
                        return $this->status;
                }
@@ -2299,7 +2262,6 @@ class LocalFileDeleteBatch {
 
                // Commit and return
                $this->file->unlock();
-               wfProfileOut( __METHOD__ );
 
                return $this->status;
        }
index 710058f..73c614a 100644 (file)
@@ -175,7 +175,6 @@ class OldLocalFile extends LocalFile {
        }
 
        function loadFromDB( $flags = 0 ) {
-               wfProfileIn( __METHOD__ );
 
                $this->dataLoaded = true;
 
@@ -194,14 +193,12 @@ class OldLocalFile extends LocalFile {
                        $this->fileExists = false;
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
         * Load lazy file metadata from the DB
         */
        protected function loadExtraFromDB() {
-               wfProfileIn( __METHOD__ );
 
                $this->extraDataLoaded = true;
                $dbr = $this->repo->getSlaveDB();
@@ -226,11 +223,9 @@ class OldLocalFile extends LocalFile {
                                $this->$name = $value;
                        }
                } else {
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( "Could not find data for image '{$this->archive_name}'." );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -260,13 +255,11 @@ class OldLocalFile extends LocalFile {
        }
 
        function upgradeRow() {
-               wfProfileIn( __METHOD__ );
                $this->loadFromFile();
 
                # Don't destroy file info of missing files
                if ( !$this->fileExists ) {
                        wfDebug( __METHOD__ . ": file does not exist, aborting\n" );
-                       wfProfileOut( __METHOD__ );
 
                        return;
                }
@@ -291,7 +284,6 @@ class OldLocalFile extends LocalFile {
                                'oi_archive_name' => $this->archive_name ),
                        __METHOD__
                );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
index 11b88b4..a91f331 100644 (file)
@@ -218,7 +218,7 @@ abstract class HTMLFormField {
                                default:
                                        throw new MWException( "Unknown operation" );
                        }
-               } catch ( MWException $ex ) {
+               } catch ( Exception $ex ) {
                        throw new MWException(
                                "Invalid hide-if specification for $this->mName: " .
                                $ex->getMessage() . " in " . var_export( $origParams, true ),
index 31b93c8..f36bac1 100644 (file)
@@ -305,7 +305,7 @@ abstract class DatabaseInstaller {
                $up = DatabaseUpdater::newForDB( $this->db );
                try {
                        $up->doUpdates();
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        echo "\nAn error occurred:\n";
                        echo $e->getText();
                        $ret = false;
index 760254d..4159c1d 100644 (file)
@@ -674,7 +674,6 @@ abstract class Installer {
                        'site_stats',
                        array(
                                'ss_row_id' => 1,
-                               'ss_total_views' => 0,
                                'ss_total_edits' => 0,
                                'ss_good_articles' => 0,
                                'ss_total_pages' => 0,
@@ -1378,7 +1377,7 @@ abstract class Installer {
 
                                try {
                                        $text = Http::get( $url . $file, array( 'timeout' => 3 ) );
-                               } catch ( MWException $e ) {
+                               } catch ( Exception $e ) {
                                        // Http::get throws with allow_url_fopen = false and no curl extension.
                                        $text = null;
                                }
@@ -1754,7 +1753,7 @@ abstract class Installer {
                                false,
                                User::newFromName( 'MediaWiki default' )
                        );
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        //using raw, because $wgShowExceptionDetails can not be set yet
                        $status->fatal( 'config-install-mainpage-failed', $e->getMessage() );
                }
index ed11f8b..5eef335 100644 (file)
@@ -42,6 +42,11 @@ class MssqlUpdater extends DatabaseUpdater {
 
                        // 1.24
                        array( 'addField', 'page', 'page_lang', 'patch-page-page_lang.sql'),
+
+                       // 1.25
+                       array( 'dropTable', 'hitcounter' ),
+                       array( 'dropField', 'site_stats', 'ss_total_views', 'patch-drop-ss_total_views.sql' ),
+                       array( 'dropField', 'page', 'page_counter', 'patch-drop-page_counter.sql' ),
                        // Constraint updates
                        array( 'updateConstraints', 'category_types', 'categorylinks', 'cl_type' ),
                        array( 'updateConstraints', 'major_mime', 'filearchive', 'fa_major_mime' ),
index c3dedbc..7a36f01 100644 (file)
@@ -266,6 +266,11 @@ class MysqlUpdater extends DatabaseUpdater {
                                'patch-oi_major_mime-chemical.sql' ),
                        array( 'modifyField', 'filearchive', 'fa_major_mime',
                                'patch-fa_major_mime-chemical.sql' ),
+
+                       // 1.25
+                       array( 'dropTable', 'hitcounter' ),
+                       array( 'dropField', 'site_stats', 'ss_total_views', 'patch-drop-ss_total_views.sql' ),
+                       array( 'dropField', 'page', 'page_counter', 'patch-drop-page_counter.sql' ),
                );
        }
 
@@ -516,7 +521,6 @@ class MysqlUpdater extends DatabaseUpdater {
                        page_namespace int NOT NULL,
                        page_title varchar(255) binary NOT NULL,
                        page_restrictions tinyblob NOT NULL,
-                       page_counter bigint(20) unsigned NOT NULL default '0',
                        page_is_redirect tinyint(1) unsigned NOT NULL default '0',
                        page_is_new tinyint(1) unsigned NOT NULL default '0',
                        page_random real unsigned NOT NULL,
@@ -598,9 +602,9 @@ class MysqlUpdater extends DatabaseUpdater {
                $this->output( "......Setting up page table.\n" );
                $this->db->query(
                        "INSERT INTO $page (page_id, page_namespace, page_title,
-                               page_restrictions, page_counter, page_is_redirect, page_is_new, page_random,
+                               page_restrictions, page_is_redirect, page_is_new, page_random,
                                page_touched, page_latest, page_len)
-                       SELECT cur_id, cur_namespace, cur_title, cur_restrictions, cur_counter,
+                       SELECT cur_id, cur_namespace, cur_title, cur_restrictions,
                                cur_is_redirect, cur_is_new, cur_random, cur_touched, rev_id, LENGTH(cur_text)
                        FROM $cur,$revision
                        WHERE cur_id=rev_page AND rev_timestamp=cur_timestamp AND rev_id > {$maxold}",
index 1846854..03dbd1c 100644 (file)
@@ -103,6 +103,11 @@ class OracleUpdater extends DatabaseUpdater {
                        // 1.24
                        array( 'addField', 'page', 'page_lang', 'patch-page-page_lang.sql' ),
 
+                       // 1.25
+                       array( 'dropTable', 'hitcounter' ),
+                       array( 'dropField', 'site_stats', 'ss_total_views', 'patch-drop-ss_total_views.sql' ),
+                       array( 'dropField', 'page', 'page_counter', 'patch-drop-page_counter.sql' ),
+
                        // KEEP THIS AT THE BOTTOM!!
                        array( 'doRebuildDuplicateFunction' ),
 
@@ -172,7 +177,6 @@ class OracleUpdater extends DatabaseUpdater {
                        'page_id' => 0,
                        'page_namespace' => 0,
                        'page_title' => ' ',
-                       'page_counter' => 0,
                        'page_is_redirect' => 0,
                        'page_is_new' => 0,
                        'page_random' => 0,
index 9e8ee94..bc25455 100644 (file)
@@ -418,6 +418,11 @@ class PostgresUpdater extends DatabaseUpdater {
                        array( 'addPgField', 'pagelinks', 'pl_from_namespace', 'INTEGER NOT NULL DEFAULT 0' ),
                        array( 'addPgField', 'templatelinks', 'tl_from_namespace', 'INTEGER NOT NULL DEFAULT 0' ),
                        array( 'addPgField', 'imagelinks', 'il_from_namespace', 'INTEGER NOT NULL DEFAULT 0' ),
+
+                       // 1.25
+                       array( 'dropTable', 'hitcounter' ),
+                       array( 'dropField', 'site_stats', 'ss_total_views', 'patch-drop-ss_total_views.sql' ),
+                       array( 'dropField', 'page', 'page_counter', 'patch-drop-page_counter.sql' ),
                );
        }
 
index 91cbb04..81304c4 100644 (file)
@@ -137,6 +137,11 @@ class SqliteUpdater extends DatabaseUpdater {
                        array( 'addField', 'pagelinks', 'pl_from_namespace', 'patch-pl_from_namespace.sql' ),
                        array( 'addField', 'templatelinks', 'tl_from_namespace', 'patch-tl_from_namespace.sql' ),
                        array( 'addField', 'imagelinks', 'il_from_namespace', 'patch-il_from_namespace.sql' ),
+
+                       // 1.25
+                       array( 'dropTable', 'hitcounter' ),
+                       array( 'dropField', 'site_stats', 'ss_total_views', 'patch-drop-ss_total_views.sql' ),
+                       array( 'dropField', 'page', 'page_counter', 'patch-drop-page_counter.sql' ),
                );
        }
 
index 8688fe4..8fda8d4 100644 (file)
@@ -23,7 +23,7 @@
        "config-mysql-myisam": "MyISAM",
        "config-mysql-utf8": "UTF-8",
        "config-ns-generic": "Layihə",
-       "config-admin-name": "Sizin adınız:",
+       "config-admin-name": "Sizin istifadəçi adınız:",
        "config-admin-password": "Parol:",
        "config-admin-email": "E-poçt ünvanı",
        "config-license-pd": "İctimai istifadə",
index 6876409..51fe74f 100644 (file)
@@ -3,7 +3,8 @@
                "authors": [
                        "DCLXVI",
                        "아라",
-                       "StanProg"
+                       "StanProg",
+                       "Vodnokon4e"
                ]
        },
        "config-desc": "Инсталатор на МедияУики",
@@ -53,7 +54,7 @@
        "config-unicode-using-intl": "Използване на разширението [http://pecl.php.net/intl intl PECL] за нормализация на Уникод.",
        "config-unicode-pure-php-warning": "'''Предупреждение''': [http://pecl.php.net/intl Разширението intl PECL] не е налично за справяне с нормализацията на Уникод, превключване към по-бавното изпълнение на чист PHP.\nАко сайтът е с голям трафик, препоръчително е запознаването с [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations нормализацията на Уникод].",
        "config-unicode-update-warning": "'''Предупреждение''': Инсталираната версия на Обвивката за нормализация на Unicode използва по-старата версия на библиотеката на [http://site.icu-project.org/ проекта ICU].\nНеобходимо е да [//www.mediawiki.org/wiki/Special:MyLanguage/Unicode_normalization_considerations инсталирате по-нова верия], в случай че сте загрижени за използването на Unicode.",
-       "config-no-db": "Не може да бъде открит подходящ драйвер за база данни! Необходимо е да се инсталира драйвер за база данни за PHP.\nПоддържат се следните типове базни данни: $1.\n\nАко сами сте компилирали PHP, преконфигурирайте го с включен клиент за база данни, например чрез използване на <code>./configure --with-mysql</code>.\nАко сте инсталирали PHP от пакет за Debian или Ubuntu, необходимо е, също така, да инсталирате и модула <code>php5-mysql</code>.",
+       "config-no-db": "Не може да бъде открит подходящ драйвер за база данни! Необходимо е да инсталирате драйвер за база данни за PHP.\nПоддържат се следните типове базни данни: $1.\n\nАко сами сте компилирали PHP, преконфигурирайте го с включен клиент за база данни, например чрез използване на <code>./configure --with-mysql</code>.\nАко сте инсталирали PHP от пакет за Debian или Ubuntu, необходимо е също така да инсталирате и модула <code>php5-mysql</code>.",
        "config-outdated-sqlite": "<strong>Предупреждение:</strong> имате инсталиран SQLite  $1, а минималната допустима версия е $2. SQLite ще бъде недостъпна за ползване.",
        "config-no-fts3": "'''Предупреждение''': SQLite е компилирана без [//sqlite.org/fts3.html модула FTS3], затова възможностите за търсене няма да са достъпни.",
        "config-magic-quotes-runtime": "'''Фатално: [http://www.php.net/manual/en/ref.info.php#ini.magic-quotes-runtime magic_quotes_runtime] е активирана!'''\nТова може да повреди непредвидимо въвеждането на данните.\nИнсталацията на МедияУики е невъзможна докато тази настройка не бъде изключена.",
        "config-license-gfdl": "Лиценз за свободна документация на GNU 1.3 или по-нов",
        "config-license-pd": "Обществено достояние",
        "config-license-cc-choose": "Избиране на друг лиценз от Криейтив Комънс",
-       "config-license-help": "Много публични уикита поставят всички приноси под [http://freedomdefined.org/Definition/Bg свободен лиценз].\nТова помага създаване на усещане за общност и насърчава дългосрочните приноси.\nТова не е необходимо за частни или корпоративни уикита.\n\nАко е необходимо да се използват текстове от Уикипедия, както и Уикипедия да може да използва текстове от уикито, необходимо е да се избере лиценз <strong>{{int:config-license-cc-by-sa}}</strong>..\n\nЛицензът за свободна документация на GNU е старият лиценз на съдържанието на Уикипедия.\nТой все още е валиден лиценз, но някои негови условия са трудни за разбиране и правят по-сложни повторното използване и интерпретацията.",
+       "config-license-help": "Много публични уикита поставят всички приноси под [http://freedomdefined.org/Definition/Bg свободен лиценз].\nТова помага за създаването на усещане за общност и насърчава дългосрочните приноси. \nТова не е необходимо като цяло за частно или корпоративно уики.\n\nАко искате да използвате текстове от Уикипедия, и искате Уикипедия да може да приема текстове, копирани от вашето уики, трябва да изберете лиценз <strong>{{int:config-license-cc-by-sa}}</strong>.\n\nЛицензът за свободна документация на GNU е старият лиценз на съдържанието на Уикипедия.\nТой все още е валиден лиценз, но някои негови условия са трудни за разбиране и правят по-сложни повторното използване и интерпретацията.",
        "config-email-settings": "Настройки за е-поща",
        "config-enable-email": "Разрешаване на изходящи е-писма",
        "config-enable-email-help": "За да работят възможностите за използване на е-поща, необходимо е [http://www.php.net/manual/en/mail.configuration.php настройките за поща на PHP] да бъдат конфигурирани правилно.\nАко няма да се използват услугите за е-поща в уикито, те могат да бъдат изключени тук.",
        "config-extensions": "Разширения",
        "config-extensions-help": "Разширенията от списъка по-горе бяха открити в директорията <code>./extensions</code>.\n\nВъзможно е те да изискват допълнително конфигуриране, но сега могат да бъдат включени.",
        "config-skins": "Облици",
-       "config-skins-help": "По-горе са посочени облици, които са открити в папката <code>./skins</code> на уикито. Необходимо е да изберете поне един, който да се използва по подразбиране.",
+       "config-skins-help": "По-горе са посочени облиците, които са открити във вашата директория <code>./skins</code>. Необходимо е да изберете поне един, който да се използва по подразбиране.",
        "config-skins-use-as-default": "Използване на този облик по подразбиране",
        "config-install-alreadydone": "'''Предупреждение:''' Изглежда вече сте инсталирали МедияУики и се опитвате да го инсталирате отново.\nПродължете към следващата страница.",
        "config-install-begin": "Инсталацията на МедияУики ще започне след натискане на бутона „{{int:config-continue}}“.\nВ случай, че е необходимо да се направят промени, използва се бутона „{{int:config-back}}“.",
index 5ead1dc..ff7afaa 100644 (file)
@@ -7,6 +7,9 @@
                ]
        },
        "config-desc": "Y gosodwr ar gyfer MediaWiki",
+       "config-title": "Gosod MediaWiki $1",
+       "config-information": "Gwybodaeth",
+       "config-localsettings-upgrade": "Rydym wedi canfod ffeil <code>LocalSettings.php</code>.\nI uwchraddio'r gosodiad yma, rhowch fanylion y<code>$wgUpgradeKey</code> yn y blwch isod.\nFe'i cewch yn <code>LocalSettings.php</code>.",
        "mainpagetext": "'''Wedi llwyddo gosod meddalwedd MediaWiki yma'''",
        "mainpagedocfooter": "Ceir cymorth (yn Saesneg) ar ddefnyddio meddalwedd wici yn y [//meta.wikimedia.org/wiki/Help:Contents Canllaw Defnyddwyr] ar wefan Wikimedia.\n\n==Cychwyn arni==\n\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Rhestr osodiadau wrth gyflunio]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Cwestiynau poblogaidd ar MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Rhestr postio datganiadau MediaWiki]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Cyfieithu MediaWici i'ch iaith chi]"
 }
index f0aaa22..9c68ce9 100644 (file)
@@ -41,7 +41,7 @@
        "config-help-restart": "Vulite scancellà tutt' 'e date astipate c'avite nzertato e riabbià 'o prucesso d'installazione?",
        "config-restart": "Sì, riabbìa",
        "config-welcome": "=== Cuntrollo 'e ll'ambiente ===\nSarranno eseguite 'e cuntrolle bbase pe' putè vedè si st'ambiente è adatto pe' ne ffà l'installazione 'e MediaWiki.\nArricurdateve d'includere sti nfurmaziune si spiate assistenza ncopp' 'a maniera 'e cumpletà l'installazione.",
-       "config-copyright": "=== Copyright e termine ===\n\n$1\n\nChistu programma è nu software libbero; vuje 'o putite redestribbuì e/o cagnà sott' 'e termine d' 'a licienza GNU GPL ('a Licienza Pubbreca Generale) comme pubbrecata d' 'a Free Software Foundation; o pure 'a verziona 2 d' 'a Licienza, o pure (comme vulite vuje) 'a n'ata verziona cchiù nnova.\n\nChistu programma è destribbuito c' 'a speranza d'essere utile, ma SENZA NISCIUNA GARANZIA; senza manco 'a garanzia p' 'a CUMMERCIABBELETÀ O IDONIETÀ PE' NU SCOPO PARTICOLARE.\nIate a vedé 'a GNU GPL pe' n'avé cchiù nfurmaziune.\n\nCu stu programma avísseve 'a ricevere <doclink href=Copying>na copia d' 'a Licienza GNU GPL</doclink> cu stu prugramma; si nò, scrivete â Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA o [http://www.gnu.org/copyleft/gpl.html liggite sta paggena ncopp' 'a l'Internet].",
+       "config-copyright": "=== Copyright e termine ===\n\n$1\n\nChistu programma è nu software libbero; vuje 'o putite redestribbuì e/o cagnà sott' 'e termine d' 'a licienza GNU GPL ('a Licienza Pubbreca Generale) comme pubbrecata d' 'a Free Software Foundation; o pure 'a verziona 2 d' 'a Licienza, o pure (comme vulite vuje) 'a n'ata verziona cchiù nnova.\n\nChistu programma è destribbuito c' 'a speranza d'essere utile, ma SENZA NISCIUNA GARANZIA; senza manco 'a garanzia p' 'a CUMMERCIABBELETÀ O IDONIETÀ PE' NU SCOPO PARTICULARE.\nIate a vedé 'a GNU GPL pe' n'avé cchiù nfurmaziune.\n\nCu stu programma avísseve 'a ricevere <doclink href=Copying>na copia d' 'a Licienza GNU GPL</doclink> cu stu prugramma; si nò, scrivete â Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA o [http://www.gnu.org/copyleft/gpl.html liggite sta paggena ncopp' 'a l'Internet].",
        "config-sidebar": "* [//www.mediawiki.org Paggina prencepale MediaWiki]\n* [//www.mediawiki.org/wiki/Aiuto:Guida a 'e cuntenute pe' l'utente]\n* [//www.mediawiki.org/wiki/Manuale:Guida a 'e cuntenute pe l'ammenistrature]\n* [//www.mediawiki.org/wiki/Manuale:FAQ FAQ]\n----\n* <doclink href=Readme>Lieggeme</doclink>\n* <doclink href=ReleaseNotes>Note 'e verziona</doclink>\n* <doclink href=Copying>Copie</doclink>\n* <doclink href=UpgradeDoc>Agghiurnamento</doclink>",
        "config-env-good": "L'ambiente è stato cuntrullato.\nÈ pussibbele installare MediaWiki.",
        "config-env-bad": "L'ambiente è stato cuntrullato.\nNun se può installà MediaWiki.",
index 8220337..8b82db0 100644 (file)
        "config-page-copying": "Stoche a copie",
        "config-page-upgradedoc": "Aggiornamende",
        "config-page-existingwiki": "Uicchi esistende",
+       "config-restart": "Sìne, falle repartì",
+       "config-env-php": "PHP $1 ha state installate.",
+       "config-env-hhvm": "HHVM $1 ha state installate.",
        "config-db-type": "Tipe de database:",
+       "config-db-host-oracle": "Database TNS:",
+       "config-db-name-oracle": "Scheme d'u database:",
        "config-db-charset": "'Nzieme de carattere d'u database",
        "config-charset-mysql5-binary": "MySQL 4.1/5.0 binary",
        "config-charset-mysql5": "MySQL 4.1/5.0 UTF-8",
        "config-charset-mysql4": "MySQL 4.0 backwards-compatible UTF-8",
        "config-db-port": "Porte d'u database:",
        "config-db-schema": "Scheme pe MediaUicchi:",
-       "config-type-mysql": "MySQL",
+       "config-type-mysql": "MySQL (o combatibbile)",
        "config-type-postgres": "PostgreSQL",
        "config-type-sqlite": "SQLite",
        "config-type-oracle": "Oracle",
+       "config-type-mssql": "Microsoft SQL Server",
+       "config-header-mysql": "'Mbostaziune de MySQL",
+       "config-header-postgres": "'Mbostaziune de PostgreSQL",
+       "config-header-sqlite": "'Mbostaziune de SQLite",
+       "config-header-oracle": "'Mbostaziune de Oracle",
+       "config-header-mssql": "'Mbostaziune de Microsoft SQL Server",
+       "config-invalid-db-type": "Tipe de database invalide.",
        "config-mysql-innodb": "InnoDB",
        "config-mysql-myisam": "MyISAM",
        "config-admin-email": "Indirizze e-mail:",
@@ -51,6 +63,7 @@
        "config-install-schema": "Stoche a creje 'u scheme",
        "config-install-pg-schema-not-exist": "'U scheme PostgreSQL non g'esiste.",
        "config-help": "ajute",
+       "config-help-tooltip": "cazze pe spannere",
        "mainpagetext": "'''MediaUicchi ha state 'nstallete.'''",
        "mainpagedocfooter": "Vè vide [//meta.wikimedia.org/wiki/Help:Contents User's Guide] pe l'mbormaziune sus a cumme s'ause 'u softuer wiki.\n\n== Pe accumenzà ==\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Liste pe le configuraziune]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ FAQ de MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Elenghe d'a poste de MediaUicchi]\n* [//www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Localizzazzione de MediaUicchi pa lènga toje]"
 }
index 8b4136e..e9b05cf 100644 (file)
@@ -7,7 +7,8 @@
                        "SiLveRLeaD",
                        "Trncmvsr",
                        "Sayginer",
-                       "Trockya"
+                       "Trockya",
+                       "Aşilleus"
                ]
        },
        "config-desc": "MediaWiki yükleyicisi",
        "config-git": "Sürüm kontrol yazılımı Git bulundu: <code>$1</code>.",
        "config-git-bad": "Sürüm kontrol yazılımı Git bulunamadı.",
        "config-imagemagick": "ImageMagick bulundu: <code>$1</code>.\nEğer yüklemeleri etkinleştirirseniz, küçük resimler etkinleştirilecektir.",
+       "config-db-type": "Veritabanı tipi:",
        "config-db-host": "Veritabanı sunucusu:",
        "config-db-host-help": "Veritabanı sunucunuz farklı bir sunucu üzerinde ise, ana bilgisayar adını veya IP adresini buraya girin.\n\nPaylaşılan ağ barındırma hizmeti kullanıyorsanız, barındırma sağlayıcınız size doğru bir ana bilgisayar adını kendi belgelerinde vermiştir.\n\nEğer MySQL kullanan bir Windows sunucusuna yükleme yapıyorsanız, sunucu adı olarak \"localhost\" kullanırsanız çalışmayabilir. Çalışmazsa, yerel IP adresi için \"127.0.0.1\" deneyin.\n\nPostgreSQL kullanıyorsanız, bu alanı bir Unix soketi ile bağlanmak için boş bırakın.",
+       "config-db-host-oracle": "Veritabanı TNS:",
        "config-db-wiki-settings": "Bu wikiyi tanımla",
        "config-db-name": "Veritabanı adı:",
        "config-db-name-oracle": "Veritabanı şeması:",
index c00d22e..53fcaee 100644 (file)
@@ -187,9 +187,7 @@ abstract class JobQueue {
         * @throws JobQueueError
         */
        final public function isEmpty() {
-               wfProfileIn( __METHOD__ );
                $res = $this->doIsEmpty();
-               wfProfileOut( __METHOD__ );
 
                return $res;
        }
@@ -210,9 +208,7 @@ abstract class JobQueue {
         * @throws JobQueueError
         */
        final public function getSize() {
-               wfProfileIn( __METHOD__ );
                $res = $this->doGetSize();
-               wfProfileOut( __METHOD__ );
 
                return $res;
        }
@@ -233,9 +229,7 @@ abstract class JobQueue {
         * @throws JobQueueError
         */
        final public function getAcquiredCount() {
-               wfProfileIn( __METHOD__ );
                $res = $this->doGetAcquiredCount();
-               wfProfileOut( __METHOD__ );
 
                return $res;
        }
@@ -257,9 +251,7 @@ abstract class JobQueue {
         * @since 1.22
         */
        final public function getDelayedCount() {
-               wfProfileIn( __METHOD__ );
                $res = $this->doGetDelayedCount();
-               wfProfileOut( __METHOD__ );
 
                return $res;
        }
@@ -282,9 +274,7 @@ abstract class JobQueue {
         * @throws JobQueueError
         */
        final public function getAbandonedCount() {
-               wfProfileIn( __METHOD__ );
                $res = $this->doGetAbandonedCount();
-               wfProfileOut( __METHOD__ );
 
                return $res;
        }
@@ -336,9 +326,7 @@ abstract class JobQueue {
                        }
                }
 
-               wfProfileIn( __METHOD__ );
                $this->doBatchPush( $jobs, $flags );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -366,9 +354,7 @@ abstract class JobQueue {
                        throw new MWException( "Unrecognized job type '{$this->type}'." );
                }
 
-               wfProfileIn( __METHOD__ );
                $job = $this->doPop();
-               wfProfileOut( __METHOD__ );
 
                // Flag this job as an old duplicate based on its "root" job...
                try {
@@ -376,7 +362,7 @@ abstract class JobQueue {
                                JobQueue::incrStats( 'job-pop-duplicate', $this->type, 1, $this->wiki );
                                $job = DuplicateJob::newFromJob( $job ); // convert to a no-op
                        }
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        // don't lose jobs over this
                }
 
@@ -403,9 +389,7 @@ abstract class JobQueue {
                if ( $job->getType() !== $this->type ) {
                        throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
                }
-               wfProfileIn( __METHOD__ );
                $this->doAck( $job );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -449,9 +433,7 @@ abstract class JobQueue {
                if ( $job->getType() !== $this->type ) {
                        throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
                }
-               wfProfileIn( __METHOD__ );
                $ok = $this->doDeduplicateRootJob( $job );
-               wfProfileOut( __METHOD__ );
 
                return $ok;
        }
@@ -494,9 +476,7 @@ abstract class JobQueue {
                if ( $job->getType() !== $this->type ) {
                        throw new MWException( "Got '{$job->getType()}' job; expected '{$this->type}'." );
                }
-               wfProfileIn( __METHOD__ );
                $isDuplicate = $this->doIsRootJobOldDuplicate( $job );
-               wfProfileOut( __METHOD__ );
 
                return $isDuplicate;
        }
@@ -538,9 +518,7 @@ abstract class JobQueue {
         * @return void
         */
        final public function delete() {
-               wfProfileIn( __METHOD__ );
                $this->doDelete();
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -560,9 +538,7 @@ abstract class JobQueue {
         * @throws JobQueueError
         */
        final public function waitForBackups() {
-               wfProfileIn( __METHOD__ );
                $this->doWaitForBackups();
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -607,9 +583,7 @@ abstract class JobQueue {
         * @return void
         */
        final public function flushCaches() {
-               wfProfileIn( __METHOD__ );
                $this->doFlushCaches();
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -661,7 +635,6 @@ abstract class JobQueue {
         * @since 1.22
         */
        final public function getSiblingQueuesWithJobs( array $types ) {
-               $section = new ProfileSection( __METHOD__ );
 
                return $this->doGetSiblingQueuesWithJobs( $types );
        }
@@ -686,7 +659,6 @@ abstract class JobQueue {
         * @since 1.22
         */
        final public function getSiblingQueueSizes( array $types ) {
-               $section = new ProfileSection( __METHOD__ );
 
                return $this->doGetSiblingQueueSizes( $types );
        }
index b0b35e9..dbb85d7 100644 (file)
@@ -220,12 +220,10 @@ class JobQueueGroup {
        public function waitForBackups() {
                global $wgJobTypeConf;
 
-               wfProfileIn( __METHOD__ );
                // Try to avoid doing this more than once per queue storage medium
                foreach ( $wgJobTypeConf as $type => $conf ) {
                        $this->get( $type )->waitForBackups();
                }
-               wfProfileOut( __METHOD__ );
        }
 
        /**
index 6b19340..d99bfab 100644 (file)
@@ -129,21 +129,19 @@ class JobRunner {
                                $this->runJobsLog( $job->toString() . " STARTING" );
 
                                // Run the job...
-                               wfProfileIn( __METHOD__ . '-' . get_class( $job ) );
                                $jobStartTime = microtime( true );
                                try {
                                        ++$jobsRun;
                                        $status = $job->run();
                                        $error = $job->getLastError();
                                        wfGetLBFactory()->commitMasterChanges();
-                               } catch ( MWException $e ) {
+                               } catch ( Exception $e ) {
                                        MWExceptionHandler::rollbackMasterChangesAndLog( $e );
                                        $status = false;
                                        $error = get_class( $e ) . ': ' . $e->getMessage();
                                        MWExceptionHandler::logException( $e );
                                }
                                $timeMs = intval( ( microtime( true ) - $jobStartTime ) * 1000 );
-                               wfProfileOut( __METHOD__ . '-' . get_class( $job ) );
                                $timeMsTotal += $timeMs;
 
                                // Mark the job as done on success or when the job cannot be retried
@@ -253,7 +251,6 @@ class JobRunner {
         * @return array Map of (job type => backoff expiry timestamp)
         */
        private function loadBackoffs( array $backoffs, $mode = 'wait' ) {
-               $section = new ProfileSection( __METHOD__ );
 
                $file = wfTempDir() . '/mw-runJobs-backoffs.json';
                if ( is_file( $file ) ) {
@@ -292,7 +289,6 @@ class JobRunner {
         * @return array The new backoffs account for $backoffs and the latest file data
         */
        private function syncBackoffDeltas( array $backoffs, array &$deltas, $mode = 'wait' ) {
-               $section = new ProfileSection( __METHOD__ );
 
                if ( !$deltas ) {
                        return $this->loadBackoffs( $backoffs, $mode );
index 8600eed..bd5c40d 100644 (file)
@@ -73,9 +73,7 @@ abstract class JobQueueAggregator {
         * @return bool Success
         */
        final public function notifyQueueEmpty( $wiki, $type ) {
-               wfProfileIn( __METHOD__ );
                $ok = $this->doNotifyQueueEmpty( $wiki, $type );
-               wfProfileOut( __METHOD__ );
 
                return $ok;
        }
@@ -93,9 +91,7 @@ abstract class JobQueueAggregator {
         * @return bool Success
         */
        final public function notifyQueueNonEmpty( $wiki, $type ) {
-               wfProfileIn( __METHOD__ );
                $ok = $this->doNotifyQueueNonEmpty( $wiki, $type );
-               wfProfileOut( __METHOD__ );
 
                return $ok;
        }
@@ -111,9 +107,7 @@ abstract class JobQueueAggregator {
         * @return array (job type => (list of wiki IDs))
         */
        final public function getAllReadyWikiQueues() {
-               wfProfileIn( __METHOD__ );
                $res = $this->doGetAllReadyWikiQueues();
-               wfProfileOut( __METHOD__ );
 
                return $res;
        }
@@ -129,9 +123,7 @@ abstract class JobQueueAggregator {
         * @return bool Success
         */
        final public function purge() {
-               wfProfileIn( __METHOD__ );
                $res = $this->doPurge();
-               wfProfileOut( __METHOD__ );
 
                return $res;
        }
index cc28a01..b7f09e7 100644 (file)
@@ -94,7 +94,7 @@ class AssembleUploadChunksJob extends Job {
                                        'status' => Status::newGood()
                                )
                        );
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        UploadBase::setSessionStatus(
                                $user,
                                $this->params['filekey'],
index 55215b3..3d4cfae 100644 (file)
@@ -108,7 +108,7 @@ class PublishStashedFileJob extends Job {
                                        'status' => Status::newGood()
                                )
                        );
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        UploadBase::setSessionStatus(
                                $user,
                                $this->params['filekey'],
index 56dc6ea..0fe9444 100644 (file)
@@ -48,7 +48,7 @@ class Cookie {
         *        expires A date string
         *        path    The path this cookie is used on
         *        domain  Domain this cookie is used on
-        * @throws MWException
+        * @throws InvalidArgumentException
         */
        public function set( $value, $attr ) {
                $this->value = $value;
index 2a7ee2a..0b6db32 100644 (file)
@@ -94,6 +94,14 @@ class MapCacheLRU {
                }
        }
 
+       /**
+        * @return array
+        * @since 1.25
+        */
+       public function getAllKeys() {
+               return array_keys( $this->cache );
+       }
+
        /**
         * Clear one or several cache entries, or all cache entries
         *
index eeda8d4..fb2daa6 100644 (file)
@@ -34,6 +34,7 @@
  *                array bodies are encoded as multipart/form-data and strings
  *                use application/x-www-form-urlencoded (headers sent automatically)
  *   - stream   : resource to stream the HTTP response body to
+ *   - proxy    : HTTP proxy to use
  * Request maps can use integer index 0 instead of 'method' and 1 instead of 'url'.
  *
  * @author Aaron Schulz
@@ -52,11 +53,14 @@ class MultiHttpClient {
        protected $usePipelining = false;
        /** @var integer */
        protected $maxConnsPerHost = 50;
+       /** @var string|null proxy */
+       protected $proxy;
 
        /**
         * @param array $options
         *   - connTimeout     : default connection timeout
         *   - reqTimeout      : default request timeout
+        *   - proxy           : HTTP proxy to use
         *   - usePipelining   : whether to use HTTP pipelining if possible (for all hosts)
         *   - maxConnsPerHost : maximum number of concurrent connections (per host)
         * @throws Exception
@@ -68,7 +72,7 @@ class MultiHttpClient {
                                throw new Exception( "Cannot find CA bundle: " . $this->caBundlePath );
                        }
                }
-               static $opts = array( 'connTimeout', 'reqTimeout', 'usePipelining', 'maxConnsPerHost' );
+               static $opts = array( 'connTimeout', 'reqTimeout', 'usePipelining', 'maxConnsPerHost', 'proxy' );
                foreach ( $opts as $key ) {
                        if ( isset( $options[$key] ) ) {
                                $this->$key = $options[$key];
@@ -253,6 +257,7 @@ class MultiHttpClient {
 
                curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT,
                        isset( $opts['connTimeout'] ) ? $opts['connTimeout'] : $this->connTimeout );
+               curl_setopt( $ch, CURLOPT_PROXY, isset( $req['proxy'] ) ? $req['proxy'] : $this->proxy );
                curl_setopt( $ch, CURLOPT_TIMEOUT,
                        isset( $opts['reqTimeout'] ) ? $opts['reqTimeout'] : $this->reqTimeout );
                curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, 1 );
index 98ff675..5ed67c7 100644 (file)
@@ -321,7 +321,7 @@ class Xhprof {
                                $this->complete[$func]['subcalls'] = array();
                        }
 
-                       foreach( $this->hieraData as $key => $stats ) {
+                       foreach ( $this->hieraData as $key => $stats ) {
                                list( $parent, $child ) = self::splitKey( $key );
                                if ( $parent !== null ) {
                                        // Track call tree information
index 4786165..49c9f23 100644 (file)
@@ -51,4 +51,4 @@ class ComposerJson {
                return $version;
        }
 
-}
\ No newline at end of file
+}
diff --git a/includes/libs/virtualrest/ParsoidVirtualRESTService.php b/includes/libs/virtualrest/ParsoidVirtualRESTService.php
new file mode 100644 (file)
index 0000000..34e43f9
--- /dev/null
@@ -0,0 +1,121 @@
+<?php
+/**
+ * Virtual HTTP service client for Parsoid
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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
+ */
+
+/**
+ * Virtual REST service for Parsoid
+ * @since 1.25
+ */
+class ParsoidVirtualRESTService extends VirtualRESTService {
+       /**
+        * Example requests:
+        *  GET /local/v1/page/$title/html/$oldid
+        *   * $oldid is optional
+        *  POST /local/v1/transform/html/to/wikitext/$title/$oldid
+        *   * body: array( 'html' => ... )
+        *   * $title and $oldid are optional
+        *  POST /local/v1/transform/wikitext/to/html/$title
+        *   * body: array( 'wikitext' => ... ) or array( 'wikitext' => ..., 'body' => true/false )
+        *   * $title is optional
+        * @param array $params Key/value map
+        *   - URL            : Parsoid server URL
+        *   - prefix         : Parsoid prefix for this wiki
+        *   - timeout        : Parsoid timeout (optional)
+        *   - forwardCookies : Cookies to forward to Parsoid, or false. (optional)
+        *   - HTTPProxy      : Parsoid HTTP proxy (optional)
+        */
+       public function __construct( array $params ) {
+               parent::__construct( $params );
+       }
+
+       public function onRequests( array $reqs, Closure $idGeneratorFunc ) {
+               $result = array();
+               foreach ( $reqs as $key => $req ) {
+                       $parts = explode( '/', $req['url'] );
+
+                       list(
+                               $targetWiki, // 'local'
+                               $version, // 'v1'
+                               $reqType // 'page' or 'transform'
+                       ) = $parts;
+
+                       if ( $targetWiki !== 'local' ) {
+                               throw new Exception( "Only 'local' target wiki is currently supported" );
+                       } elseif ( $version !== 'v1' ) {
+                               throw new Exception( "Only version 1 exists" );
+                       } else if ( $reqType !== 'page' && $reqType !== 'transform' ) {
+                               throw new Exception( "Request type must be either 'page' or 'transform'" );
+                       }
+
+                       $req['url'] = $this->params['URL'] . '/' . urlencode( $this->params['prefix'] ) . '/';
+
+                       if ( $reqType === 'page' ) {
+                               $title = $parts[3];
+                               if ( $parts[4] !== 'html' ) {
+                                       throw new Exception( "Only 'html' output format is currently supported" );
+                               }
+                               if ( isset( $parts[5] ) ) {
+                                       $req['url'] .= $title . '?oldid=' . $parts[5];
+                               } else {
+                                       $req['url'] .= $title;
+                               }
+                       } elseif ( $reqType === 'transform' ) {
+                               if ( $parts[4] !== 'to' ) {
+                                       throw new Exception( "Part index 4 is not 'to'" );
+                               }
+
+                               if ( isset( $parts[6] ) ) {
+                                       $req['url'] .= $parts[6];
+                               }
+
+                               if ( $parts[3] === 'html' & $parts[5] === 'wikitext' ) {
+                                       if ( !isset( $req['body']['html'] ) ) {
+                                               throw new Exception( "You must set an 'html' body key for this request" );
+                                       }
+                                       if ( isset( $parts[6] ) ) {
+                                               $req['body']['oldid'] = $parts[6];
+                                       }
+                               } elseif ( $parts[3] == 'wikitext' && $parts[5] == 'html' ) {
+                                       if ( !isset( $req['body']['wikitext'] ) ) {
+                                               throw new Exception( "You must set a 'wikitext' body key for this request" );
+                                       }
+                                       $req['body']['wt'] = $req['body']['wikitext'];
+                                       unset( $req['body']['wikitext'] );
+                               } else {
+                                       throw new Exception( "Transformation unsupported" );
+                               }
+                       }
+
+                       if ( isset( $this->params['HTTPProxy'] ) && $this->params['HTTPProxy'] ) {
+                               $req['proxy'] = $this->params['HTTPProxy'];
+                       }
+                       if ( isset( $this->params['timeout'] ) ) {
+                               $req['reqTimeout'] = $this->params['timeout'];
+                       }
+
+                       // Forward cookies
+                       if ( isset( $this->params['forwardCookies'] ) ) {
+                               $req['headers']['Cookie'] = $this->params['forwardCookies'];
+                       }
+
+                       $result[$key] = $req;
+               }
+               return $result;
+       }
+}
index 46be144..e8bb38d 100644 (file)
@@ -208,6 +208,9 @@ class VirtualRESTServiceClient {
                        if ( ++$rounds > 5 ) { // sanity
                                throw new Exception( "Too many replacement rounds detected. Aborting." );
                        }
+                       // Track requests executed this round that have a prefix/service.
+                       // Note that this also includes requests where 'response' was forced.
+                       $checkReqIndexesByPrefix = array();
                        // Resolve the virtual URLs valid and qualified HTTP(S) URLs
                        // and add any required authentication headers for the backend.
                        // Services can also replace requests with new ones, either to
@@ -220,7 +223,7 @@ class VirtualRESTServiceClient {
                                        if ( isset( $servReqs[$index] ) || isset( $origPending[$index] ) ) {
                                                // A current or original request which was not modified
                                        } else {
-                                               // Replacement requests with pre-set responses should not execute
+                                               // Replacement request that will convert to original requests
                                                $newReplaceReqsByService[$prefix][$index] = $req;
                                        }
                                        if ( isset( $req['response'] ) ) {
@@ -232,6 +235,7 @@ class VirtualRESTServiceClient {
                                                // Original or mangled request included
                                                $executeReqs[$index] = $req;
                                        }
+                                       $checkReqIndexesByPrefix[$prefix][$index] = 1;
                                }
                        }
                        // Update index of requests to inspect for replacement
@@ -246,12 +250,12 @@ class VirtualRESTServiceClient {
                        // defer the original or to set a proxy response to the original.
                        // Any replacement requests executed above will need to be replaced
                        // with new requests (eventually the original). The responses can be
-                       // forced instead of having the request sent over the wire.
+                       // forced by setting 'response' rather than actually be sent over the wire.
                        $newReplaceReqsByService = array();
-                       foreach ( $replaceReqsByService as $prefix => $servReqs ) {
+                       foreach ( $checkReqIndexesByPrefix as $prefix => $servReqIndexes ) {
                                $service = $this->instances[$prefix];
-                               // Only the request copies stored in $doneReqs actually have the response
-                               $servReqs = array_intersect_key( $doneReqs, $servReqs );
+                               // $doneReqs actually has the requests (with 'response' set)
+                               $servReqs = array_intersect_key( $doneReqs, $servReqIndexes );
                                foreach ( $service->onResponses( $servReqs, $idFunc ) as $index => $req ) {
                                        // Services use unique IDs for replacement requests
                                        if ( isset( $servReqs[$index] ) || isset( $origPending[$index] ) ) {
index 256934e..bf489ab 100644 (file)
@@ -323,7 +323,6 @@ class LogPager extends ReverseChronologicalPager {
        }
 
        public function getStartBody() {
-               wfProfileIn( __METHOD__ );
                # Do a link batch query
                if ( $this->getNumRows() > 0 ) {
                        $lb = new LinkBatch;
@@ -339,7 +338,6 @@ class LogPager extends ReverseChronologicalPager {
                        $lb->execute();
                        $this->mResult->seek( 0 );
                }
-               wfProfileOut( __METHOD__ );
 
                return '';
        }
index 220c6b1..81c4e38 100644 (file)
@@ -205,8 +205,6 @@ class EmailNotification {
                global $wgEnotifWatchlist;
                global $wgEnotifMinorEdits, $wgEnotifUserTalk;
 
-               wfProfileIn( __METHOD__ );
-
                # The following code is only run, if several conditions are met:
                # 1. EmailNotification for pages (other than user_talk pages) must be enabled
                # 2. minor edits (changes) are only regarded if the global flag indicates so
@@ -226,7 +224,6 @@ class EmailNotification {
 
                Hooks::run( 'UpdateUserMailerFormattedPageStatus', array( &$formattedPageStatus ) );
                if ( !in_array( $this->pageStatus, $formattedPageStatus ) ) {
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( 'Not a valid page status!' );
                }
 
@@ -270,7 +267,6 @@ class EmailNotification {
                }
 
                $this->sendMails();
-               wfProfileOut( __METHOD__ );
        }
 
        /**
index d8b0ba6..52f9518 100644 (file)
@@ -71,7 +71,7 @@ class BmpHandler extends BitmapHandler {
                try {
                        $w = wfUnpack( 'V', $w, 4 );
                        $h = wfUnpack( 'V', $h, 4 );
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        return false;
                }
 
index cd77f3e..eadcf94 100644 (file)
@@ -169,10 +169,8 @@ class BitmapHandler extends TransformationalImageHandler {
                        array( $this->escapeMagickOutput( $params['dstPath'] ) ) ) );
 
                wfDebug( __METHOD__ . ": running ImageMagick: $cmd\n" );
-               wfProfileIn( 'convert' );
                $retval = 0;
                $err = wfShellExecWithStderr( $cmd, $retval, $env );
-               wfProfileOut( 'convert' );
 
                if ( $retval !== 0 ) {
                        $this->logErrorForExternalProcess( $retval, $err, $cmd );
@@ -280,10 +278,8 @@ class BitmapHandler extends TransformationalImageHandler {
                $cmd = str_replace( '%h', wfEscapeShellArg( $params['physicalHeight'] ),
                        str_replace( '%w', wfEscapeShellArg( $params['physicalWidth'] ), $cmd ) ); # Size
                wfDebug( __METHOD__ . ": Running custom convert command $cmd\n" );
-               wfProfileIn( 'convert' );
                $retval = 0;
                $err = wfShellExecWithStderr( $cmd, $retval );
-               wfProfileOut( 'convert' );
 
                if ( $retval !== 0 ) {
                        $this->logErrorForExternalProcess( $retval, $err, $cmd );
@@ -457,10 +453,8 @@ class BitmapHandler extends TransformationalImageHandler {
                                        " -rotate " . wfEscapeShellArg( "-$rotation" ) . " " .
                                        wfEscapeShellArg( $this->escapeMagickOutput( $params['dstPath'] ) );
                                wfDebug( __METHOD__ . ": running ImageMagick: $cmd\n" );
-                               wfProfileIn( 'convert' );
                                $retval = 0;
                                $err = wfShellExecWithStderr( $cmd, $retval );
-                               wfProfileOut( 'convert' );
                                if ( $retval !== 0 ) {
                                        $this->logErrorForExternalProcess( $retval, $err, $cmd );
 
index dd41c38..bb7a1e8 100644 (file)
@@ -61,7 +61,7 @@ class BitmapMetadataHandler {
        private function doApp13( $app13 ) {
                try {
                        $this->iptcType = JpegMetadataExtractor::doPSIR( $app13 );
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        // Error reading the iptc hash information.
                        // This probably means the App13 segment is something other than what we expect.
                        // However, still try to read it, and treat it as if the hash didn't exist.
index ba60af4..1b0eb49 100644 (file)
@@ -221,11 +221,9 @@ class DjVuHandler extends ImageHandler {
                        $cmd .= " | {$wgDjvuPostProcessor}";
                }
                $cmd .= ' > ' . wfEscapeShellArg( $dstPath ) . ') 2>&1';
-               wfProfileIn( 'ddjvu' );
                wfDebug( __METHOD__ . ": $cmd\n" );
                $retval = '';
                $err = wfShellExec( $cmd, $retval );
-               wfProfileOut( 'ddjvu' );
 
                $removed = $this->removeBadFile( $dstPath, $retval );
                if ( $retval != 0 || $removed ) {
@@ -313,7 +311,6 @@ class DjVuHandler extends ImageHandler {
 
                        return false;
                }
-               wfProfileIn( __METHOD__ );
 
                wfSuppressWarnings();
                try {
@@ -339,7 +336,6 @@ class DjVuHandler extends ImageHandler {
                        wfDebug( "Bogus multipage XML metadata on '{$image->getName()}'\n" );
                }
                wfRestoreWarnings();
-               wfProfileOut( __METHOD__ );
                if ( $gettext ) {
                        return $image->djvuTextTree;
                } else {
index 596d3e8..016728d 100644 (file)
@@ -269,7 +269,6 @@ class DjVuImage {
         */
        function retrieveMetaData() {
                global $wgDjvuToXML, $wgDjvuDump, $wgDjvuTxt;
-               wfProfileIn( __METHOD__ );
 
                if ( !$this->isValid() ) {
                        return false;
@@ -278,28 +277,22 @@ class DjVuImage {
                if ( isset( $wgDjvuDump ) ) {
                        # djvudump is faster as of version 3.5
                        # http://sourceforge.net/tracker/index.php?func=detail&aid=1704049&group_id=32953&atid=406583
-                       wfProfileIn( 'djvudump' );
                        $cmd = wfEscapeShellArg( $wgDjvuDump ) . ' ' . wfEscapeShellArg( $this->mFilename );
                        $dump = wfShellExec( $cmd );
                        $xml = $this->convertDumpToXML( $dump );
-                       wfProfileOut( 'djvudump' );
                } elseif ( isset( $wgDjvuToXML ) ) {
-                       wfProfileIn( 'djvutoxml' );
                        $cmd = wfEscapeShellArg( $wgDjvuToXML ) . ' --without-anno --without-text ' .
                                wfEscapeShellArg( $this->mFilename );
                        $xml = wfShellExec( $cmd );
-                       wfProfileOut( 'djvutoxml' );
                } else {
                        $xml = null;
                }
                # Text layer
                if ( isset( $wgDjvuTxt ) ) {
-                       wfProfileIn( 'djvutxt' );
                        $cmd = wfEscapeShellArg( $wgDjvuTxt ) . ' --detail=page ' . wfEscapeShellArg( $this->mFilename );
                        wfDebug( __METHOD__ . ": $cmd\n" );
                        $retval = '';
                        $txt = wfShellExec( $cmd, $retval, array(), array( 'memory' => self::DJVUTXT_MEMORY_LIMIT ) );
-                       wfProfileOut( 'djvutxt' );
                        if ( $retval == 0 ) {
                                # Strip some control characters
                                $txt = preg_replace( "/[\013\035\037]/", "", $txt );
@@ -320,7 +313,6 @@ EOR;
                                $xml = $xml . $txt . '</mw-djvu>';
                        }
                }
-               wfProfileOut( __METHOD__ );
 
                return $xml;
        }
index 8cf95dd..e8e73af 100644 (file)
@@ -1595,11 +1595,8 @@ class FormatMetadata extends ContextSource {
        public function fetchExtendedMetadata( File $file ) {
                global $wgMemc;
 
-               wfProfileIn( __METHOD__ );
-
                // If revision deleted, exit immediately
                if ( $file->isDeleted( File::DELETED_FILE ) ) {
-                       wfProfileOut( __METHOD__ );
 
                        return array();
                }
@@ -1634,8 +1631,6 @@ class FormatMetadata extends ContextSource {
                        $wgMemc->set( $cacheKey, $valueToCache, $maxCacheTime );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $extendedMetadata;
        }
 
@@ -1657,8 +1652,6 @@ class FormatMetadata extends ContextSource {
                        return $file->getExtendedMetadata() ?: array();
                }
 
-               wfProfileIn( __METHOD__ );
-
                $uploadDate = wfTimestamp( TS_ISO_8601, $file->getTimestamp() );
 
                $fileMetadata = array(
@@ -1697,8 +1690,6 @@ class FormatMetadata extends ContextSource {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $fileMetadata;
        }
 
@@ -1715,7 +1706,6 @@ class FormatMetadata extends ContextSource {
        protected function getExtendedMetadataFromHook( File $file, array $extendedMetadata,
                &$maxCacheTime
        ) {
-               wfProfileIn( __METHOD__ );
 
                Hooks::run( 'GetExtendedMetadata', array(
                        &$extendedMetadata,
@@ -1732,8 +1722,6 @@ class FormatMetadata extends ContextSource {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $extendedMetadata;
        }
 
index fbdbdfe..5463922 100644 (file)
@@ -106,7 +106,7 @@ class JpegHandler extends ExifBitmapHandler {
                        $meta['MEDIAWIKI_EXIF_VERSION'] = Exif::version();
 
                        return serialize( $meta );
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        // BitmapMetadataHandler throws an exception in certain exceptional
                        // cases like if file does not exist.
                        wfDebug( __METHOD__ . ': ' . $e->getMessage() . "\n" );
@@ -143,10 +143,8 @@ class JpegHandler extends ExifBitmapHandler {
                                " -outfile " . wfEscapeShellArg( $params['dstPath'] ) .
                                " " . wfEscapeShellArg( $params['srcPath'] );
                        wfDebug( __METHOD__ . ": running jpgtran: $cmd\n" );
-                       wfProfileIn( 'jpegtran' );
                        $retval = 0;
                        $err = wfShellExecWithStderr( $cmd, $retval );
-                       wfProfileOut( 'jpegtran' );
                        if ( $retval !== 0 ) {
                                $this->logErrorForExternalProcess( $retval, $err, $cmd );
 
index 74e5e04..53abfef 100644 (file)
@@ -272,10 +272,8 @@ class SvgHandler extends ImageHandler {
                                        $env['LANG'] = $lang;
                                }
 
-                               wfProfileIn( 'rsvg' );
                                wfDebug( __METHOD__ . ": $cmd\n" );
                                $err = wfShellExecWithStderr( $cmd, $retval, $env );
-                               wfProfileOut( 'rsvg' );
                        }
                }
                $removed = $this->removeBadFile( $dstPath, $retval );
@@ -364,7 +362,7 @@ class SvgHandler extends ImageHandler {
                $metadata = array( 'version' => self::SVG_METADATA_VERSION );
                try {
                        $metadata += SVGMetadataExtractor::getMetadata( $filename );
-               } catch ( MWException $e ) { // @todo SVG specific exceptions
+               } catch ( Exception $e ) { // @todo SVG specific exceptions
                        // File not found, broken, etc.
                        $metadata['error'] = array(
                                'message' => $e->getMessage(),
index bea6cab..750528f 100644 (file)
@@ -88,7 +88,7 @@ class TiffHandler extends ExifBitmapHandler {
                                $meta['MEDIAWIKI_EXIF_VERSION'] = Exif::version();
 
                                return serialize( $meta );
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                // BitmapMetadataHandler throws an exception in certain exceptional
                                // cases like if file does not exist.
                                wfDebug( __METHOD__ . ': ' . $e->getMessage() . "\n" );
index 48b7a47..6544d5c 100644 (file)
@@ -130,7 +130,7 @@ class XCFHandler extends BitmapHandler {
                                        "/Nbase_type", # /
                                $binaryHeader
                        );
-               } catch ( MWException $mwe ) {
+               } catch ( Exception $mwe ) {
                        return false;
                }
 
index 5b46af1..0d341aa 100644 (file)
@@ -316,7 +316,7 @@ class XMPReader {
                                $this->results = array(); // blank if error.
                                return false;
                        }
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        wfDebugLog( 'XMP', 'XMP parse error: ' . $e );
                        $this->results = array();
 
index 41eebfb..1e04d45 100644 (file)
@@ -413,7 +413,6 @@ class MWMemcached {
         * @return mixed
         */
        public function get( $key, &$casToken = null ) {
-               wfProfileIn( __METHOD__ );
 
                if ( $this->_debug ) {
                        $this->_debugprint( "get($key)\n" );
@@ -421,19 +420,16 @@ class MWMemcached {
 
                if ( !is_array( $key ) && strval( $key ) === '' ) {
                        $this->_debugprint( "Skipping key which equals to an empty string" );
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
                if ( !$this->_active ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
                $sock = $this->get_sock( $key );
 
                if ( !is_resource( $sock ) ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -446,7 +442,6 @@ class MWMemcached {
 
                $cmd = "gets $key\r\n";
                if ( !$this->_fwrite( $sock, $cmd ) ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -463,7 +458,6 @@ class MWMemcached {
                if ( isset( $val[$key] ) ) {
                        $value = $val[$key];
                }
-               wfProfileOut( __METHOD__ );
                return $value;
        }
 
index fcc37cb..7c0a645 100644 (file)
@@ -120,11 +120,9 @@ class MemcachedPeclBagOStuff extends MemcachedBagOStuff {
         * @return mixed
         */
        public function get( $key, &$casToken = null ) {
-               wfProfileIn( __METHOD__ );
                $this->debugLog( "get($key)" );
                $result = $this->client->get( $this->encodeKey( $key ), null, $casToken );
                $result = $this->checkResult( $key, $result );
-               wfProfileOut( __METHOD__ );
                return $result;
        }
 
@@ -243,11 +241,9 @@ class MemcachedPeclBagOStuff extends MemcachedBagOStuff {
         * @return array
         */
        public function getMulti( array $keys ) {
-               wfProfileIn( __METHOD__ );
                $this->debugLog( 'getMulti(' . implode( ', ', $keys ) . ')' );
                $callback = array( $this, 'encodeKey' );
                $result = $this->client->getMulti( array_map( $callback, $keys ) );
-               wfProfileOut( __METHOD__ );
                $result = $result ?: array(); // must be an array
                return $this->checkResult( false, $result );
        }
@@ -258,7 +254,6 @@ class MemcachedPeclBagOStuff extends MemcachedBagOStuff {
         * @return bool
         */
        public function setMulti( array $data, $exptime = 0 ) {
-               wfProfileIn( __METHOD__ );
                foreach ( $data as $key => $value ) {
                        $encKey = $this->encodeKey( $key );
                        if ( $encKey !== $key ) {
@@ -268,7 +263,6 @@ class MemcachedPeclBagOStuff extends MemcachedBagOStuff {
                }
                $this->debugLog( 'setMulti(' . implode( ', ', array_keys( $data ) ) . ')' );
                $result = $this->client->setMulti( $data, $this->fixExpiry( $exptime ) );
-               wfProfileOut( __METHOD__ );
                return $this->checkResult( false, $result );
        }
 }
index 633b34a..62856f9 100644 (file)
@@ -135,7 +135,7 @@ class ObjectCache {
                } elseif ( function_exists( 'wincache_ucache_get' ) ) {
                        $id = 'wincache';
                } else {
-                       if ( $fallback ) {
+                       if ( $fallback !== null ) {
                                return self::newFromId( $fallback );
                        }
                        throw new MWException( "CACHE_ACCEL requested but no suitable object " .
index ae8cc5b..6836f74 100644 (file)
@@ -73,7 +73,6 @@ class RedisBagOStuff extends BagOStuff {
        }
 
        public function get( $key, &$casToken = null ) {
-               $section = new ProfileSection( __METHOD__ );
 
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
@@ -93,7 +92,6 @@ class RedisBagOStuff extends BagOStuff {
        }
 
        public function set( $key, $value, $expiry = 0 ) {
-               $section = new ProfileSection( __METHOD__ );
 
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
@@ -117,7 +115,6 @@ class RedisBagOStuff extends BagOStuff {
        }
 
        public function cas( $casToken, $key, $value, $expiry = 0 ) {
-               $section = new ProfileSection( __METHOD__ );
 
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
@@ -151,7 +148,6 @@ class RedisBagOStuff extends BagOStuff {
        }
 
        public function delete( $key, $time = 0 ) {
-               $section = new ProfileSection( __METHOD__ );
 
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
@@ -171,7 +167,6 @@ class RedisBagOStuff extends BagOStuff {
        }
 
        public function getMulti( array $keys ) {
-               $section = new ProfileSection( __METHOD__ );
 
                $batches = array();
                $conns = array();
@@ -217,7 +212,6 @@ class RedisBagOStuff extends BagOStuff {
         * @return bool
         */
        public function setMulti( array $data, $expiry = 0 ) {
-               $section = new ProfileSection( __METHOD__ );
 
                $batches = array();
                $conns = array();
@@ -265,7 +259,6 @@ class RedisBagOStuff extends BagOStuff {
 
 
        public function add( $key, $value, $expiry = 0 ) {
-               $section = new ProfileSection( __METHOD__ );
 
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
@@ -303,7 +296,6 @@ class RedisBagOStuff extends BagOStuff {
         * @return int|bool New value or false on failure
         */
        public function incr( $key, $value = 1 ) {
-               $section = new ProfileSection( __METHOD__ );
 
                list( $server, $conn ) = $this->getConnection( $key );
                if ( !$conn ) {
index be138f1..438a17c 100644 (file)
@@ -226,7 +226,6 @@ class Article implements Page {
         * @since 1.21
         */
        protected function getContentObject() {
-               wfProfileIn( __METHOD__ );
 
                if ( $this->mPage->getID() === 0 ) {
                        # If this is a MediaWiki:x message, then load the messages
@@ -247,7 +246,6 @@ class Article implements Page {
                        $content = $this->mContentObject;
                }
 
-               wfProfileOut( __METHOD__ );
                return $content;
        }
 
@@ -344,12 +342,9 @@ class Article implements Page {
                        return $this->mContent;
                }
 
-               wfProfileIn( __METHOD__ );
-
                $content = $this->fetchContentObject();
 
                if ( !$content ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -357,8 +352,6 @@ class Article implements Page {
                $this->mContent = ContentHandler::getContentText( $content );
                ContentHandler::runLegacyHooks( 'ArticleAfterFetchContent', array( &$this, &$this->mContent ) );
 
-               wfProfileOut( __METHOD__ );
-
                return $this->mContent;
        }
 
@@ -379,8 +372,6 @@ class Article implements Page {
                        return $this->mContentObject;
                }
 
-               wfProfileIn( __METHOD__ );
-
                $this->mContentLoaded = true;
                $this->mContent = null;
 
@@ -397,7 +388,6 @@ class Article implements Page {
                                $this->mRevision = Revision::newFromId( $oldid );
                                if ( !$this->mRevision ) {
                                        wfDebug( __METHOD__ . " failed to retrieve specified revision, id $oldid\n" );
-                                       wfProfileOut( __METHOD__ );
                                        return false;
                                }
                        }
@@ -405,7 +395,6 @@ class Article implements Page {
                        if ( !$this->mPage->getLatest() ) {
                                wfDebug( __METHOD__ . " failed to find page data for title " .
                                        $this->getTitle()->getPrefixedText() . "\n" );
-                               wfProfileOut( __METHOD__ );
                                return false;
                        }
 
@@ -414,7 +403,6 @@ class Article implements Page {
                        if ( !$this->mRevision ) {
                                wfDebug( __METHOD__ . " failed to retrieve current page, rev_id " .
                                        $this->mPage->getLatest() . "\n" );
-                               wfProfileOut( __METHOD__ );
                                return false;
                        }
                }
@@ -430,8 +418,6 @@ class Article implements Page {
 
                Hooks::run( 'ArticleAfterFetchContentObject', array( &$this, &$this->mContentObject ) );
 
-               wfProfileOut( __METHOD__ );
-
                return $this->mContentObject;
        }
 
@@ -482,8 +468,6 @@ class Article implements Page {
        public function view() {
                global $wgUseFileCache, $wgUseETag, $wgDebugToolbar, $wgMaxRedirects;
 
-               wfProfileIn( __METHOD__ );
-
                # Get variables from query string
                # As side effect this will load the revision and update the title
                # in a revision ID is passed in the request, so this should remain
@@ -495,7 +479,6 @@ class Article implements Page {
                $permErrors = $this->getTitle()->getUserPermissionsErrors( 'read', $user );
                if ( count( $permErrors ) ) {
                        wfDebug( __METHOD__ . ": denied on secondary read check\n" );
-                       wfProfileOut( __METHOD__ );
                        throw new PermissionsError( 'read', $permErrors );
                }
 
@@ -504,7 +487,6 @@ class Article implements Page {
                if ( $this->mRedirectUrl ) {
                        $outputPage->redirect( $this->mRedirectUrl );
                        wfDebug( __METHOD__ . ": redirecting due to oldid\n" );
-                       wfProfileOut( __METHOD__ );
 
                        return;
                }
@@ -513,7 +495,6 @@ class Article implements Page {
                if ( $this->getContext()->getRequest()->getCheck( 'diff' ) ) {
                        wfDebug( __METHOD__ . ": showing diff page\n" );
                        $this->showDiffPage();
-                       wfProfileOut( __METHOD__ );
 
                        return;
                }
@@ -568,7 +549,6 @@ class Article implements Page {
                        # Is it client cached?
                        if ( $outputPage->checkLastModified( $timestamp ) ) {
                                wfDebug( __METHOD__ . ": done 304\n" );
-                               wfProfileOut( __METHOD__ );
 
                                return;
                        # Try file cache
@@ -577,7 +557,6 @@ class Article implements Page {
                                # tell wgOut that output is taken care of
                                $outputPage->disable();
                                $this->mPage->doViewUpdates( $user, $oldid );
-                               wfProfileOut( __METHOD__ );
 
                                return;
                        }
@@ -610,7 +589,6 @@ class Article implements Page {
                                                wfDebug( __METHOD__ . ": showing missing article\n" );
                                                $this->showMissingArticle();
                                                $this->mPage->doViewUpdates( $user );
-                                               wfProfileOut( __METHOD__ );
                                                return;
                                        }
 
@@ -649,7 +627,6 @@ class Article implements Page {
 
                                                if ( !$this->showDeletedRevisionHeader() ) {
                                                        wfDebug( __METHOD__ . ": cannot view deleted revision\n" );
-                                                       wfProfileOut( __METHOD__ );
                                                        return;
                                                }
                                        }
@@ -696,7 +673,6 @@ class Article implements Page {
                                                        $outputPage->addWikiText( '<div class="errorbox">' . $errortext . '</div>' );
                                                }
                                                # Connection or timeout error
-                                               wfProfileOut( __METHOD__ );
                                                return;
                                        }
 
@@ -755,7 +731,6 @@ class Article implements Page {
 
                $outputPage->addModules( 'mediawiki.action.view.postEdit' );
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -1100,8 +1075,6 @@ class Article implements Page {
                        return false;
                }
 
-               wfProfileIn( __METHOD__ );
-
                // New page patrol: Get the timestamp of the oldest revison which
                // the revision table holds for the given page. Then we look
                // whether it's within the RC lifespan and if it is, we try
@@ -1110,7 +1083,6 @@ class Article implements Page {
 
                // Check for cached results
                if ( $cache->get( wfMemcKey( 'NotPatrollablePage', $this->getTitle()->getArticleID() ) ) ) {
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -1119,7 +1091,6 @@ class Article implements Page {
                ) {
                        // The current revision is already older than what could be in the RC table
                        // 6h tolerance because the RC might not be cleaned out regularly
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -1155,14 +1126,12 @@ class Article implements Page {
                        // Don't cache in case we can patrol as this could change
                        $cache->set( wfMemcKey( 'NotPatrollablePage', $this->getTitle()->getArticleID() ), '1' );
 
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
                if ( $rc->getPerformer()->getName() == $user->getName() ) {
                        // Don't show a patrol link for own creations. If the user could
                        // patrol them, they already would be patrolled
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -1192,7 +1161,6 @@ class Article implements Page {
                        '</div>'
                );
 
-               wfProfileOut( __METHOD__ );
                return true;
        }
 
@@ -1626,7 +1594,7 @@ class Article implements Page {
                if ( !$reason ) {
                        try {
                                $reason = $this->generateReason( $hasHistory );
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                # if a page is horribly broken, we still want to be able to
                                # delete it. So be lenient about errors here.
                                wfDebug( "Error while building auto delete summary: $e" );
index dcebe54..8373dc0 100644 (file)
@@ -557,7 +557,6 @@ class WikiPage implements Page, IDBAccessObject {
         * @return Revision|null
         */
        public function getOldestRevision() {
-               wfProfileIn( __METHOD__ );
 
                // Try using the slave database first, then try the master
                $continue = 2;
@@ -588,7 +587,6 @@ class WikiPage implements Page, IDBAccessObject {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $row ? Revision::newFromRow( $row ) : null;
        }
 
@@ -1055,7 +1053,6 @@ class WikiPage implements Page, IDBAccessObject {
         * @return array Array of authors, duplicates not removed
         */
        public function getLastNAuthors( $num, $revLatest = 0 ) {
-               wfProfileIn( __METHOD__ );
                // First try the slave
                // If that doesn't have the latest revision, try the master
                $continue = 2;
@@ -1076,7 +1073,6 @@ class WikiPage implements Page, IDBAccessObject {
                        );
 
                        if ( !$res ) {
-                               wfProfileOut( __METHOD__ );
                                return array();
                        }
 
@@ -1096,7 +1092,6 @@ class WikiPage implements Page, IDBAccessObject {
                        $authors[] = $row->rev_user_text;
                }
 
-               wfProfileOut( __METHOD__ );
                return $authors;
        }
 
@@ -1129,7 +1124,6 @@ class WikiPage implements Page, IDBAccessObject {
         * @return ParserOutput|bool ParserOutput or false if the revision was not found
         */
        public function getParserOutput( ParserOptions $parserOptions, $oldid = null ) {
-               wfProfileIn( __METHOD__ );
 
                $useParserCache = $this->isParserCacheUsed( $parserOptions, $oldid );
                wfDebug( __METHOD__ . ': using parser cache: ' . ( $useParserCache ? 'yes' : 'no' ) . "\n" );
@@ -1140,7 +1134,6 @@ class WikiPage implements Page, IDBAccessObject {
                if ( $useParserCache ) {
                        $parserOutput = ParserCache::singleton()->get( $this, $parserOptions );
                        if ( $parserOutput !== false ) {
-                               wfProfileOut( __METHOD__ );
                                return $parserOutput;
                        }
                }
@@ -1152,8 +1145,6 @@ class WikiPage implements Page, IDBAccessObject {
                $pool = new PoolWorkArticleView( $this, $parserOptions, $oldid, $useParserCache );
                $pool->execute();
 
-               wfProfileOut( __METHOD__ );
-
                return $pool->getParserOutput();
        }
 
@@ -1228,7 +1219,6 @@ class WikiPage implements Page, IDBAccessObject {
         * @return int The newly created page_id key, or false if the title already existed
         */
        public function insertOn( $dbw ) {
-               wfProfileIn( __METHOD__ );
 
                $page_id = $dbw->nextSequenceValue( 'page_page_id_seq' );
                $dbw->insert( 'page', array(
@@ -1251,7 +1241,6 @@ class WikiPage implements Page, IDBAccessObject {
                        $this->mId = $newid;
                        $this->mTitle->resetArticleID( $newid );
                }
-               wfProfileOut( __METHOD__ );
 
                return $affected ? $newid : false;
        }
@@ -1274,8 +1263,6 @@ class WikiPage implements Page, IDBAccessObject {
        ) {
                global $wgContentHandlerUseDB;
 
-               wfProfileIn( __METHOD__ );
-
                $content = $revision->getContent();
                $len = $content ? $content->getSize() : 0;
                $rt = $content ? $content->getUltimateRedirectTarget() : null;
@@ -1317,7 +1304,6 @@ class WikiPage implements Page, IDBAccessObject {
                                                                                                        $this->mLatest, $revision->getContentModel() );
                }
 
-               wfProfileOut( __METHOD__ );
                return $result;
        }
 
@@ -1342,7 +1328,6 @@ class WikiPage implements Page, IDBAccessObject {
                        return true;
                }
 
-               wfProfileIn( __METHOD__ );
                if ( $isRedirect ) {
                        $this->insertRedirectEntry( $redirectTitle );
                } else {
@@ -1354,7 +1339,6 @@ class WikiPage implements Page, IDBAccessObject {
                if ( $this->getTitle()->getNamespace() == NS_FILE ) {
                        RepoGroup::singleton()->getLocalRepo()->invalidateImageRedirect( $this->getTitle() );
                }
-               wfProfileOut( __METHOD__ );
 
                return ( $dbw->affectedRows() != 0 );
        }
@@ -1370,7 +1354,6 @@ class WikiPage implements Page, IDBAccessObject {
         * @return bool
         */
        public function updateIfNewerOn( $dbw, $revision ) {
-               wfProfileIn( __METHOD__ );
 
                $row = $dbw->selectRow(
                        array( 'revision', 'page' ),
@@ -1382,7 +1365,6 @@ class WikiPage implements Page, IDBAccessObject {
 
                if ( $row ) {
                        if ( wfTimestamp( TS_MW, $row->rev_timestamp ) >= $revision->getTimestamp() ) {
-                               wfProfileOut( __METHOD__ );
                                return false;
                        }
                        $prev = $row->rev_id;
@@ -1395,7 +1377,6 @@ class WikiPage implements Page, IDBAccessObject {
 
                $ret = $this->updateRevisionOn( $dbw, $revision, $prev, $lastRevIsRedirect );
 
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -1514,7 +1495,6 @@ class WikiPage implements Page, IDBAccessObject {
         */
        public function replaceSectionContent( $sectionId, Content $sectionContent, $sectionTitle = '',
                $edittime = null ) {
-               wfProfileIn( __METHOD__ );
 
                $baseRevId = null;
                if ( $edittime && $sectionId !== 'new' ) {
@@ -1525,7 +1505,6 @@ class WikiPage implements Page, IDBAccessObject {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $this->replaceSectionAtRev( $sectionId, $sectionContent, $sectionTitle, $baseRevId );
        }
 
@@ -1545,14 +1524,12 @@ class WikiPage implements Page, IDBAccessObject {
        public function replaceSectionAtRev( $sectionId, Content $sectionContent,
                $sectionTitle = '', $baseRevId = null
        ) {
-               wfProfileIn( __METHOD__ );
 
                if ( strval( $sectionId ) === '' ) {
                        // Whole-page edit; let the whole text through
                        $newContent = $sectionContent;
                } else {
                        if ( !$this->supportsSections() ) {
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( "sections not supported for content model " .
                                        $this->getContentHandler()->getModelID() );
                        }
@@ -1568,7 +1545,6 @@ class WikiPage implements Page, IDBAccessObject {
                                if ( !$rev ) {
                                        wfDebug( __METHOD__ . " asked for bogus section (page: " .
                                                $this->getId() . "; section: $sectionId)\n" );
-                                       wfProfileOut( __METHOD__ );
                                        return null;
                                }
 
@@ -1577,14 +1553,12 @@ class WikiPage implements Page, IDBAccessObject {
 
                        if ( !$oldContent ) {
                                wfDebug( __METHOD__ . ": no page text\n" );
-                               wfProfileOut( __METHOD__ );
                                return null;
                        }
 
                        $newContent = $oldContent->replaceSection( $sectionId, $sectionContent, $sectionTitle );
                }
 
-               wfProfileOut( __METHOD__ );
                return $newContent;
        }
 
@@ -1726,10 +1700,7 @@ class WikiPage implements Page, IDBAccessObject {
                        throw new MWException( 'Something is trying to edit an article with an empty title' );
                }
 
-               wfProfileIn( __METHOD__ );
-
                if ( !$content->getContentHandler()->canBeUsedOn( $this->getTitle() ) ) {
-                       wfProfileOut( __METHOD__ );
                        return Status::newFatal( 'content-not-allowed-here',
                                ContentHandler::getLocalizedName( $content->getModel() ),
                                $this->getTitle()->getPrefixedText() );
@@ -1758,7 +1729,6 @@ class WikiPage implements Page, IDBAccessObject {
                                $status->fatal( 'edit-hook-aborted' );
                        }
 
-                       wfProfileOut( __METHOD__ );
                        return $status;
                }
 
@@ -1805,11 +1775,9 @@ class WikiPage implements Page, IDBAccessObject {
                                wfDebug( __METHOD__ . ": EDIT_UPDATE specified but article doesn't exist\n" );
                                $status->fatal( 'edit-gone-missing' );
 
-                               wfProfileOut( __METHOD__ );
                                return $status;
                        } elseif ( !$old_content ) {
                                // Sanity check for bug 37225
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( "Could not find text for current revision {$oldid}." );
                        }
 
@@ -1840,7 +1808,6 @@ class WikiPage implements Page, IDBAccessObject {
                                        if ( !$status->isOK() ) {
                                                $dbw->rollback( __METHOD__ );
 
-                                               wfProfileOut( __METHOD__ );
                                                return $status;
                                        }
                                        $revisionId = $revision->insertOn( $dbw );
@@ -1856,7 +1823,6 @@ class WikiPage implements Page, IDBAccessObject {
 
                                                $dbw->rollback( __METHOD__ );
 
-                                               wfProfileOut( __METHOD__ );
                                                return $status;
                                        }
 
@@ -1878,7 +1844,7 @@ class WikiPage implements Page, IDBAccessObject {
                                                }
                                        }
                                        $user->incEditCount();
-                               } catch ( MWException $e ) {
+                               } catch ( Exception $e ) {
                                        $dbw->rollback( __METHOD__ );
                                        // Question: Would it perhaps be better if this method turned all
                                        // exceptions into $status's?
@@ -1921,7 +1887,6 @@ class WikiPage implements Page, IDBAccessObject {
                                if ( !$status->isOK() ) {
                                        $dbw->rollback( __METHOD__ );
 
-                                       wfProfileOut( __METHOD__ );
                                        return $status;
                                }
 
@@ -1935,7 +1900,6 @@ class WikiPage implements Page, IDBAccessObject {
                                        $dbw->rollback( __METHOD__ );
                                        $status->fatal( 'edit-already-exists' );
 
-                                       wfProfileOut( __METHOD__ );
                                        return $status;
                                }
 
@@ -1983,7 +1947,7 @@ class WikiPage implements Page, IDBAccessObject {
                                }
                                $user->incEditCount();
 
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                $dbw->rollback( __METHOD__ );
                                throw $e;
                        }
@@ -2018,7 +1982,6 @@ class WikiPage implements Page, IDBAccessObject {
                        $user->addAutopromoteOnceGroups( 'onEdit' );
                } );
 
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -2078,7 +2041,7 @@ class WikiPage implements Page, IDBAccessObject {
        public function prepareContentForEdit(
                Content $content, $revid = null, User $user = null, $serialFormat = null, $useCache = true
        ) {
-               global $wgContLang, $wgUser;
+               global $wgContLang, $wgUser, $wgAjaxEditStash;
 
                $user = is_null( $user ) ? $wgUser : $user;
                //XXX: check $user->getId() here???
@@ -2100,7 +2063,7 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                // The edit may have already been prepared via api.php?action=stashedit
-               $cachedEdit = $useCache
+               $cachedEdit = $useCache && $wgAjaxEditStash
                        ? ApiStashEdit::checkCache( $this->getTitle(), $content, $user )
                        : false;
 
@@ -2166,8 +2129,6 @@ class WikiPage implements Page, IDBAccessObject {
        public function doEditUpdates( Revision $revision, User $user, array $options = array() ) {
                global $wgEnableParserCache;
 
-               wfProfileIn( __METHOD__ );
-
                $options += array(
                        'changed' => true,
                        'created' => false,
@@ -2214,7 +2175,6 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                if ( !$this->exists() ) {
-                       wfProfileOut( __METHOD__ );
                        return;
                }
 
@@ -2279,7 +2239,6 @@ class WikiPage implements Page, IDBAccessObject {
                        self::onArticleEdit( $this->mTitle );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -2315,7 +2274,6 @@ class WikiPage implements Page, IDBAccessObject {
        public function doQuickEditContent( Content $content, User $user, $comment = '', $minor = false,
                $serialFormat = null
        ) {
-               wfProfileIn( __METHOD__ );
 
                $serialized = $content->serialize( $serialFormat );
 
@@ -2335,7 +2293,6 @@ class WikiPage implements Page, IDBAccessObject {
 
                Hooks::run( 'NewRevisionFromEditComplete', array( $this, $revision, false, $user ) );
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -3156,7 +3113,7 @@ class WikiPage implements Page, IDBAccessObject {
         *
         * @param Title $title
         */
-       public static function onArticleCreate( $title ) {
+       public static function onArticleCreate( Title $title ) {
                // Update existence markers on article/talk tabs...
                $other = $title->getOtherPage();
 
@@ -3173,7 +3130,7 @@ class WikiPage implements Page, IDBAccessObject {
         *
         * @param Title $title
         */
-       public static function onArticleDelete( $title ) {
+       public static function onArticleDelete( Title $title ) {
                // Update existence markers on article/talk tabs...
                $other = $title->getOtherPage();
 
@@ -3214,10 +3171,8 @@ class WikiPage implements Page, IDBAccessObject {
         * Purge caches on page update etc
         *
         * @param Title $title
-        * @todo Verify that $title is always a Title object (and never false or
-        *   null), add Title hint to parameter $title.
         */
-       public static function onArticleEdit( $title ) {
+       public static function onArticleEdit( Title $title ) {
                // Invalidate caches of articles which include this page
                DeferredUpdates::addHTMLCacheUpdate( $title, 'templatelinks' );
 
index 9398e30..7a5952f 100644 (file)
@@ -196,7 +196,7 @@ abstract class IndexPager extends ContextSource implements Pager {
        public function doQuery() {
                # Use the child class name for profiling
                $fname = __METHOD__ . ' (' . get_class( $this ) . ')';
-               wfProfileIn( $fname );
+               $section = Profiler::instance()->scopedProfileIn( $fname );
 
                // @todo This should probably compare to DIR_DESCENDING and DIR_ASCENDING constants
                $descending = ( $this->mIsBackwards == $this->mDefaultDirection );
@@ -226,8 +226,6 @@ abstract class IndexPager extends ContextSource implements Pager {
 
                $this->preprocessResults( $this->mResult );
                $this->mResult->rewind(); // Paranoia
-
-               wfProfileOut( $fname );
        }
 
        /**
index a95bbfe..2b495b1 100644 (file)
@@ -309,15 +309,12 @@ class CoreParserFunctions {
         * @return string
         */
        public static function gender( $parser, $username ) {
-               wfProfileIn( __METHOD__ );
                $forms = array_slice( func_get_args(), 2 );
 
                // Some shortcuts to avoid loading user data unnecessarily
                if ( count( $forms ) === 0 ) {
-                       wfProfileOut( __METHOD__ );
                        return '';
                } elseif ( count( $forms ) === 1 ) {
-                       wfProfileOut( __METHOD__ );
                        return $forms[0];
                }
 
@@ -341,7 +338,6 @@ class CoreParserFunctions {
                        $gender = GenderCache::singleton()->getGenderOf( $parser->getOptions()->getUser(), __METHOD__ );
                }
                $ret = $parser->getFunctionLang()->gender( $gender, $forms );
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
index 0121072..7026c5c 100644 (file)
@@ -229,7 +229,6 @@ class LinkHolderArray {
         * @return string
         */
        public function makeHolder( $nt, $text = '', $query = array(), $trail = '', $prefix = '' ) {
-               wfProfileIn( __METHOD__ );
                if ( !is_object( $nt ) ) {
                        # Fail gracefully
                        $retVal = "<!-- ERROR -->{$prefix}{$text}{$trail}";
@@ -259,7 +258,6 @@ class LinkHolderArray {
                        }
                        $this->size++;
                }
-               wfProfileOut( __METHOD__ );
                return $retVal;
        }
 
@@ -269,13 +267,10 @@ class LinkHolderArray {
         * @param string $text
         */
        public function replace( &$text ) {
-               wfProfileIn( __METHOD__ );
 
                $this->replaceInternal( $text );
                $this->replaceInterwiki( $text );
 
-               wfProfileOut( __METHOD__ );
-
        }
 
        /**
@@ -287,14 +282,12 @@ class LinkHolderArray {
                        return;
                }
 
-               wfProfileIn( __METHOD__ );
                global $wgContLang, $wgContentHandlerUseDB;
 
                $colours = array();
                $linkCache = LinkCache::singleton();
                $output = $this->parent->getOutput();
 
-               wfProfileIn( __METHOD__ . '-check' );
                $dbr = wfGetDB( DB_SLAVE );
                $threshold = $this->parent->getOptions()->getStubThreshold();
 
@@ -380,7 +373,6 @@ class LinkHolderArray {
                        //pass an array of page_ids to an extension
                        Hooks::run( 'GetLinkColours', array( $linkcolour_ids, &$colours ) );
                }
-               wfProfileOut( __METHOD__ . '-check' );
 
                # Do a second query for different language variants of links and categories
                if ( $wgContLang->hasVariants() ) {
@@ -388,7 +380,6 @@ class LinkHolderArray {
                }
 
                # Construct search and replace arrays
-               wfProfileIn( __METHOD__ . '-construct' );
                $replacePairs = array();
                foreach ( $this->internals as $ns => $entries ) {
                        foreach ( $entries as $index => $entry ) {
@@ -424,18 +415,14 @@ class LinkHolderArray {
                        }
                }
                $replacer = new HashtableReplacer( $replacePairs, 1 );
-               wfProfileOut( __METHOD__ . '-construct' );
 
                # Do the thing
-               wfProfileIn( __METHOD__ . '-replace' );
                $text = preg_replace_callback(
                        '/(<!--LINK .*?-->)/',
                        $replacer->cb(),
                        $text
                );
 
-               wfProfileOut( __METHOD__ . '-replace' );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -447,7 +434,6 @@ class LinkHolderArray {
                        return;
                }
 
-               wfProfileIn( __METHOD__ );
                # Make interwiki link HTML
                $output = $this->parent->getOutput();
                $replacePairs = array();
@@ -461,7 +447,6 @@ class LinkHolderArray {
                        '/<!--IWLINK (.*?)-->/',
                        $replacer->cb(),
                        $text );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -642,14 +627,12 @@ class LinkHolderArray {
         * @return string
         */
        public function replaceText( $text ) {
-               wfProfileIn( __METHOD__ );
 
                $text = preg_replace_callback(
                        '/<!--(LINK|IWLINK) (.*?)-->/',
                        array( &$this, 'replaceTextCallback' ),
                        $text );
 
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
index 6c62302..d446ccf 100644 (file)
@@ -195,7 +195,6 @@ class MWTidy {
         */
        private static function externalClean( $text, $stderr = false, &$retval = null ) {
                global $wgTidyConf, $wgTidyBin, $wgTidyOpts;
-               wfProfileIn( __METHOD__ );
 
                $cleansource = '';
                $opts = ' -utf8';
@@ -247,7 +246,6 @@ class MWTidy {
                        $cleansource = null;
                }
 
-               wfProfileOut( __METHOD__ );
                return $cleansource;
        }
 
@@ -262,7 +260,6 @@ class MWTidy {
         */
        private static function phpClean( $text, $stderr = false, &$retval = null ) {
                global $wgTidyConf, $wgDebugTidy;
-               wfProfileIn( __METHOD__ );
 
                if ( ( !wfIsHHVM() && !class_exists( 'tidy' ) ) ||
                        ( wfIsHHVM() && !function_exists( 'tidy_repair_string' ) )
@@ -270,7 +267,6 @@ class MWTidy {
                        wfWarn( "Unable to load internal tidy class." );
                        $retval = -1;
 
-                       wfProfileOut( __METHOD__ );
                        return null;
                }
 
@@ -279,8 +275,6 @@ class MWTidy {
 
                if ( $stderr ) {
                        $retval = $tidy->getStatus();
-
-                       wfProfileOut( __METHOD__ );
                        return $tidy->errorBuffer;
                }
 
@@ -299,7 +293,6 @@ class MWTidy {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $cleansource;
        }
 
@@ -316,7 +309,7 @@ class MWTidy {
         */
        private static function hhvmClean( $text, &$retval ) {
                global $wgTidyConf;
-               wfProfileIn( __METHOD__ );
+
                $cleansource = tidy_repair_string( $text, $wgTidyConf, 'utf8' );
                if ( $cleansource === false ) {
                        $cleansource = null;
@@ -324,7 +317,7 @@ class MWTidy {
                } else {
                        $retval = 0;
                }
-               wfProfileOut( __METHOD__ );
+
                return $cleansource;
        }
 }
index b7f8cf2..fc7040a 100644 (file)
@@ -299,14 +299,11 @@ class Parser {
                }
                $this->mFirstCall = false;
 
-               wfProfileIn( __METHOD__ );
-
                CoreParserFunctions::register( $this );
                CoreTagHooks::register( $this );
                $this->initialiseVariables();
 
                Hooks::run( 'ParserFirstCallInit', array( &$this ) );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -315,7 +312,6 @@ class Parser {
         * @private
         */
        public function clearState() {
-               wfProfileIn( __METHOD__ );
                if ( $this->mFirstCall ) {
                        $this->firstCallInit();
                }
@@ -374,7 +370,6 @@ class Parser {
                $this->mProfiler = new SectionProfiler();
 
                Hooks::run( 'ParserClearState', array( &$this ) );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -399,8 +394,6 @@ class Parser {
 
                global $wgShowHostnames;
                $fname = __METHOD__ . '-' . wfGetCaller();
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( $fname );
 
                if ( $clearState ) {
                        $magicScopeVariable = $this->lock();
@@ -561,8 +554,6 @@ class Parser {
                $this->mRevisionSize = $oldRevisionSize;
                $this->mInputSize = false;
                $this->currentRevisionCache = null;
-               wfProfileOut( $fname );
-               wfProfileOut( __METHOD__ );
 
                return $this->mOutput;
        }
@@ -590,11 +581,9 @@ class Parser {
         * @return string UNSAFE half-parsed HTML
         */
        public function recursiveTagParse( $text, $frame = false ) {
-               wfProfileIn( __METHOD__ );
                Hooks::run( 'ParserBeforeStrip', array( &$this, &$text, &$this->mStripState ) );
                Hooks::run( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
                $text = $this->internalParse( $text, false, $frame );
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -616,10 +605,8 @@ class Parser {
         * @return string Fully parsed HTML
         */
        public function recursiveTagParseFully( $text, $frame = false ) {
-               wfProfileIn( __METHOD__ );
                $text = $this->recursiveTagParse( $text, $frame );
                $text = $this->internalParseHalfParsed( $text, false );
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -637,7 +624,6 @@ class Parser {
        public function preprocess( $text, Title $title = null,
                ParserOptions $options, $revid = null, $frame = false
        ) {
-               wfProfileIn( __METHOD__ );
                $magicScopeVariable = $this->lock();
                $this->startParse( $title, $options, self::OT_PREPROCESS, true );
                if ( $revid !== null ) {
@@ -647,7 +633,6 @@ class Parser {
                Hooks::run( 'ParserAfterStrip', array( &$this, &$text, &$this->mStripState ) );
                $text = $this->replaceVariables( $text, $frame );
                $text = $this->mStripState->unstripBoth( $text );
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -661,10 +646,8 @@ class Parser {
         * @since 1.19
         */
        public function recursivePreprocess( $text, $frame = false ) {
-               wfProfileIn( __METHOD__ );
                $text = $this->replaceVariables( $text, $frame );
                $text = $this->mStripState->unstripBoth( $text );
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -1019,7 +1002,6 @@ class Parser {
         * @return string
         */
        public function doTableStuff( $text ) {
-               wfProfileIn( __METHOD__ );
 
                $lines = StringUtils::explode( "\n", $text );
                $out = '';
@@ -1206,8 +1188,6 @@ class Parser {
                        $out = '';
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $out;
        }
 
@@ -1224,13 +1204,11 @@ class Parser {
         * @return string
         */
        public function internalParse( $text, $isMain = true, $frame = false ) {
-               wfProfileIn( __METHOD__ );
 
                $origText = $text;
 
                # Hook to suspend the parser in this state
                if ( !Hooks::run( 'ParserBeforeInternalParse', array( &$this, &$text, &$this->mStripState ) ) ) {
-                       wfProfileOut( __METHOD__ );
                        return $text;
                }
 
@@ -1281,7 +1259,6 @@ class Parser {
                $text = $this->doMagicLinks( $text );
                $text = $this->formatHeadings( $text, $origText, $isMain );
 
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -1392,7 +1369,6 @@ class Parser {
         * @return string
         */
        public function doMagicLinks( $text ) {
-               wfProfileIn( __METHOD__ );
                $prots = wfUrlProtocolsWithoutProtRel();
                $urlChar = self::EXT_LINK_URL_CLASS;
                $space = self::SPACE_NOT_NL; #  non-newline space
@@ -1411,7 +1387,6 @@ class Parser {
                                        [0-9Xx]                 # check digit
                                )\b
                        )!xu", array( &$this, 'magicLinkCallback' ), $text );
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -1476,7 +1451,6 @@ class Parser {
         * @private
         */
        public function makeFreeExternalLink( $url ) {
-               wfProfileIn( __METHOD__ );
 
                $trail = '';
 
@@ -1530,7 +1504,6 @@ class Parser {
                        $pasteurized = self::normalizeLinkUrl( $url );
                        $this->mOutput->addExternalLink( $pasteurized );
                }
-               wfProfileOut( __METHOD__ );
                return $text . $trail;
        }
 
@@ -1544,12 +1517,10 @@ class Parser {
         * @return string
         */
        public function doHeadings( $text ) {
-               wfProfileIn( __METHOD__ );
                for ( $i = 6; $i >= 1; --$i ) {
                        $h = str_repeat( '=', $i );
                        $text = preg_replace( "/^$h(.+)$h\\s*$/m", "<h$i>\\1</h$i>", $text );
                }
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -1562,14 +1533,12 @@ class Parser {
         * @return string The altered text
         */
        public function doAllQuotes( $text ) {
-               wfProfileIn( __METHOD__ );
                $outtext = '';
                $lines = StringUtils::explode( "\n", $text );
                foreach ( $lines as $line ) {
                        $outtext .= $this->doQuotes( $line ) . "\n";
                }
                $outtext = substr( $outtext, 0, -1 );
-               wfProfileOut( __METHOD__ );
                return $outtext;
        }
 
@@ -1771,11 +1740,9 @@ class Parser {
         * @return string
         */
        public function replaceExternalLinks( $text ) {
-               wfProfileIn( __METHOD__ );
 
                $bits = preg_split( $this->mExtLinkBracketedRegex, $text, -1, PREG_SPLIT_DELIM_CAPTURE );
                if ( $bits === false ) {
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( "PCRE needs to be compiled with "
                                . "--enable-unicode-properties in order for MediaWiki to function" );
                }
@@ -1839,7 +1806,6 @@ class Parser {
                        $this->mOutput->addExternalLink( $pasteurized );
                }
 
-               wfProfileOut( __METHOD__ );
                return $s;
        }
 
@@ -2037,9 +2003,7 @@ class Parser {
         */
        public function replaceInternalLinks2( &$s ) {
                global $wgExtraInterlanguageLinkPrefixes;
-               wfProfileIn( __METHOD__ );
 
-               wfProfileIn( __METHOD__ . '-setup' );
                static $tc = false, $e1, $e1_img;
                # the % is needed to support urlencoded titles as well
                if ( !$tc ) {
@@ -2071,8 +2035,6 @@ class Parser {
                }
 
                if ( is_null( $this->mTitle ) ) {
-                       wfProfileOut( __METHOD__ . '-setup' );
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( __METHOD__ . ": \$this->mTitle is null\n" );
                }
                $nottalk = !$this->mTitle->isTalkPage();
@@ -2089,7 +2051,6 @@ class Parser {
                }
 
                $useSubpages = $this->areSubpagesAllowed();
-               wfProfileOut( __METHOD__ . '-setup' );
 
                // @codingStandardsIgnoreStart Squiz.WhiteSpace.SemicolonSpacing.Incorrect
                # Loop for each link
@@ -2105,7 +2066,6 @@ class Parser {
                        }
 
                        if ( $useLinkPrefixExtension ) {
-                               wfProfileIn( __METHOD__ . '-prefixhandling' );
                                if ( preg_match( $e2, $s, $m ) ) {
                                        $prefix = $m[2];
                                        $s = $m[1];
@@ -2117,12 +2077,10 @@ class Parser {
                                        $prefix = $first_prefix;
                                        $first_prefix = false;
                                }
-                               wfProfileOut( __METHOD__ . '-prefixhandling' );
                        }
 
                        $might_be_img = false;
 
-                       wfProfileIn( __METHOD__ . "-e1" );
                        if ( preg_match( $e1, $line, $m ) ) { # page with normal text or alt
                                $text = $m[2];
                                # If we get a ] at the beginning of $m[3] that means we have a link that's something like:
@@ -2156,11 +2114,8 @@ class Parser {
                                $trail = "";
                        } else { # Invalid form; output directly
                                $s .= $prefix . '[[' . $line;
-                               wfProfileOut( __METHOD__ . "-e1" );
                                continue;
                        }
-                       wfProfileOut( __METHOD__ . "-e1" );
-                       wfProfileIn( __METHOD__ . "-misc" );
 
                        $origLink = $m[1];
 
@@ -2169,7 +2124,6 @@ class Parser {
                        # should be external links.
                        if ( preg_match( '/^(?i:' . $this->mUrlProtocols . ')/', $origLink ) ) {
                                $s .= $prefix . '[[' . $line;
-                               wfProfileOut( __METHOD__ . "-misc" );
                                continue;
                        }
 
@@ -2186,21 +2140,16 @@ class Parser {
                                $link = substr( $link, 1 );
                        }
 
-                       wfProfileOut( __METHOD__ . "-misc" );
-                       wfProfileIn( __METHOD__ . "-title" );
                        $nt = Title::newFromText( $this->mStripState->unstripNoWiki( $link ) );
                        if ( $nt === null ) {
                                $s .= $prefix . '[[' . $line;
-                               wfProfileOut( __METHOD__ . "-title" );
                                continue;
                        }
 
                        $ns = $nt->getNamespace();
                        $iw = $nt->getInterwiki();
-                       wfProfileOut( __METHOD__ . "-title" );
 
                        if ( $might_be_img ) { # if this is actually an invalid link
-                               wfProfileIn( __METHOD__ . "-might_be_img" );
                                if ( $ns == NS_FILE && $noforce ) { # but might be an image
                                        $found = false;
                                        while ( true ) {
@@ -2232,16 +2181,13 @@ class Parser {
                                                $holders->merge( $this->replaceInternalLinks2( $text ) );
                                                $s .= "{$prefix}[[$link|$text";
                                                # note: no $trail, because without an end, there *is* no trail
-                                               wfProfileOut( __METHOD__ . "-might_be_img" );
                                                continue;
                                        }
                                } else { # it's not an image, so output it raw
                                        $s .= "{$prefix}[[$link|$text";
                                        # note: no $trail, because without an end, there *is* no trail
-                                       wfProfileOut( __METHOD__ . "-might_be_img" );
                                        continue;
                                }
-                               wfProfileOut( __METHOD__ . "-might_be_img" );
                        }
 
                        $wasblank = ( $text == '' );
@@ -2258,7 +2204,6 @@ class Parser {
                        # Link not escaped by : , create the various objects
                        if ( $noforce && !$nt->wasLocalInterwiki() ) {
                                # Interwikis
-                               wfProfileIn( __METHOD__ . "-interwiki" );
                                if (
                                        $iw && $this->mOptions->getInterwikiMagic() && $nottalk && (
                                                Language::fetchLanguageName( $iw, null, 'mw' ) ||
@@ -2273,13 +2218,10 @@ class Parser {
 
                                        $s = rtrim( $s . $prefix );
                                        $s .= trim( $trail, "\n" ) == '' ? '': $prefix . $trail;
-                                       wfProfileOut( __METHOD__ . "-interwiki" );
                                        continue;
                                }
-                               wfProfileOut( __METHOD__ . "-interwiki" );
 
                                if ( $ns == NS_FILE ) {
-                                       wfProfileIn( __METHOD__ . "-image" );
                                        if ( !wfIsBadImage( $nt->getDBkey(), $this->mTitle ) ) {
                                                if ( $wasblank ) {
                                                        # if no parameters were passed, $text
@@ -2300,12 +2242,10 @@ class Parser {
                                        } else {
                                                $s .= $prefix . $trail;
                                        }
-                                       wfProfileOut( __METHOD__ . "-image" );
                                        continue;
                                }
 
                                if ( $ns == NS_CATEGORY ) {
-                                       wfProfileIn( __METHOD__ . "-category" );
                                        $s = rtrim( $s . "\n" ); # bug 87
 
                                        if ( $wasblank ) {
@@ -2323,7 +2263,6 @@ class Parser {
                                         */
                                        $s .= trim( $prefix . $trail, "\n" ) == '' ? '' : $prefix . $trail;
 
-                                       wfProfileOut( __METHOD__ . "-category" );
                                        continue;
                                }
                        }
@@ -2339,7 +2278,6 @@ class Parser {
                        # NS_MEDIA is a pseudo-namespace for linking directly to a file
                        # @todo FIXME: Should do batch file existence checks, see comment below
                        if ( $ns == NS_MEDIA ) {
-                               wfProfileIn( __METHOD__ . "-media" );
                                # Give extensions a chance to select the file revision for us
                                $options = array();
                                $descQuery = false;
@@ -2350,11 +2288,9 @@ class Parser {
                                # Cloak with NOPARSE to avoid replacement in replaceExternalLinks
                                $s .= $prefix . $this->armorLinks(
                                        Linker::makeMediaLinkFile( $nt, $file, $text ) ) . $trail;
-                               wfProfileOut( __METHOD__ . "-media" );
                                continue;
                        }
 
-                       wfProfileIn( __METHOD__ . "-always_known" );
                        # Some titles, such as valid special pages or files in foreign repos, should
                        # be shown as bluelinks even though they're not included in the page table
                        #
@@ -2367,9 +2303,7 @@ class Parser {
                                # Links will be added to the output link list after checking
                                $s .= $holders->makeHolder( $nt, $text, array(), $trail, $prefix );
                        }
-                       wfProfileOut( __METHOD__ . "-always_known" );
                }
-               wfProfileOut( __METHOD__ );
                return $holders;
        }
 
@@ -2568,7 +2502,6 @@ class Parser {
         * @return string The lists rendered as HTML
         */
        public function doBlockLevels( $text, $linestart ) {
-               wfProfileIn( __METHOD__ );
 
                # Parsing through the text line by line.  The main thing
                # happening here is handling of block-level elements p, pre,
@@ -2677,7 +2610,6 @@ class Parser {
 
                        # If we have no prefixes, go to paragraph mode.
                        if ( 0 == $prefixLength ) {
-                               wfProfileIn( __METHOD__ . "-paragraph" );
                                # No prefix (not in list)--go to paragraph mode
                                # XXX: use a stack for nestable elements like span, table and div
                                $openmatch = preg_match(
@@ -2746,7 +2678,6 @@ class Parser {
                                                }
                                        }
                                }
-                               wfProfileOut( __METHOD__ . "-paragraph" );
                        }
                        # somewhere above we forget to get out of pre block (bug 785)
                        if ( $preCloseMatch && $this->mInPre ) {
@@ -2771,7 +2702,6 @@ class Parser {
                        $this->mLastSection = '';
                }
 
-               wfProfileOut( __METHOD__ );
                return $output;
        }
 
@@ -2786,12 +2716,10 @@ class Parser {
         * @return string The position of the ':', or false if none found
         */
        public function findColonNoLinks( $str, &$before, &$after ) {
-               wfProfileIn( __METHOD__ );
 
                $pos = strpos( $str, ':' );
                if ( $pos === false ) {
                        # Nothing to find!
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -2800,7 +2728,6 @@ class Parser {
                        # Easy; no tag nesting to worry about
                        $before = substr( $str, 0, $pos );
                        $after = substr( $str, $pos + 1 );
-                       wfProfileOut( __METHOD__ );
                        return $pos;
                }
 
@@ -2824,7 +2751,6 @@ class Parser {
                                                # We found it!
                                                $before = substr( $str, 0, $i );
                                                $after = substr( $str, $i + 1 );
-                                               wfProfileOut( __METHOD__ );
                                                return $i;
                                        }
                                        # Embedded in a tag; don't break it.
@@ -2834,7 +2760,6 @@ class Parser {
                                        $colon = strpos( $str, ':', $i );
                                        if ( $colon === false ) {
                                                # Nothing else interesting
-                                               wfProfileOut( __METHOD__ );
                                                return false;
                                        }
                                        $lt = strpos( $str, '<', $i );
@@ -2843,7 +2768,6 @@ class Parser {
                                                        # We found it!
                                                        $before = substr( $str, 0, $colon );
                                                        $after = substr( $str, $colon + 1 );
-                                                       wfProfileOut( __METHOD__ );
                                                        return $i;
                                                }
                                        }
@@ -2894,7 +2818,6 @@ class Parser {
                                        $stack--;
                                        if ( $stack < 0 ) {
                                                wfDebug( __METHOD__ . ": Invalid input; too many close tags\n" );
-                                               wfProfileOut( __METHOD__ );
                                                return false;
                                        }
                                        $state = self::COLON_STATE_TEXT;
@@ -2929,16 +2852,13 @@ class Parser {
                                }
                                break;
                        default:
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( "State machine error in " . __METHOD__ );
                        }
                }
                if ( $stack > 0 ) {
                        wfDebug( __METHOD__ . ": Invalid input; not enough close tags (stack $stack, state $state)\n" );
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
-               wfProfileOut( __METHOD__ );
                return false;
        }
 
@@ -3306,13 +3226,11 @@ class Parser {
         * @private
         */
        public function initialiseVariables() {
-               wfProfileIn( __METHOD__ );
                $variableIDs = MagicWord::getVariableIDs();
                $substIDs = MagicWord::getSubstIDs();
 
                $this->mVariables = new MagicWordArray( $variableIDs );
                $this->mSubstWords = new MagicWordArray( $substIDs );
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -3387,7 +3305,6 @@ class Parser {
                if ( strlen( $text ) < 1 || strlen( $text ) > $this->mOptions->getMaxIncludeSize() ) {
                        return $text;
                }
-               wfProfileIn( __METHOD__ );
 
                if ( $frame === false ) {
                        $frame = $this->getPreprocessor()->newFrame();
@@ -3401,7 +3318,6 @@ class Parser {
                $flags = $argsOnly ? PPFrame::NO_TEMPLATES : 0;
                $text = $frame->expand( $dom, $flags );
 
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -3479,8 +3395,6 @@ class Parser {
         * @return string The text of the template
         */
        public function braceSubstitution( $piece, $frame ) {
-               wfProfileIn( __METHOD__ );
-               wfProfileIn( __METHOD__ . '-setup' );
 
                // Flags
 
@@ -3513,12 +3427,10 @@ class Parser {
                # @todo FIXME: If piece['parts'] is null then the call to getLength()
                # below won't work b/c this $args isn't an object
                $args = ( null == $piece['parts'] ) ? array() : $piece['parts'];
-               wfProfileOut( __METHOD__ . '-setup' );
 
                $profileSection = null; // profile templates
 
                # SUBST
-               wfProfileIn( __METHOD__ . '-modifiers' );
                if ( !$found ) {
 
                        $substMatch = $this->mSubstWords->matchStartAndRemove( $part1 );
@@ -3575,11 +3487,9 @@ class Parser {
                                $forceRawInterwiki = true;
                        }
                }
-               wfProfileOut( __METHOD__ . '-modifiers' );
 
                # Parser functions
                if ( !$found ) {
-                       wfProfileIn( __METHOD__ . '-pfunc' );
 
                        $colonPos = strpos( $part1, ':' );
                        if ( $colonPos !== false ) {
@@ -3591,8 +3501,6 @@ class Parser {
                                try {
                                        $result = $this->callParserFunction( $frame, $func, $funcArgs );
                                } catch ( Exception $ex ) {
-                                       wfProfileOut( __METHOD__ . '-pfunc' );
-                                       wfProfileOut( __METHOD__ );
                                        throw $ex;
                                }
 
@@ -3601,7 +3509,6 @@ class Parser {
                                # here.
                                extract( $result );
                        }
-                       wfProfileOut( __METHOD__ . '-pfunc' );
                }
 
                # Finish mangling title and then check for loops.
@@ -3637,7 +3544,6 @@ class Parser {
                # Load from database
                if ( !$found && $title ) {
                        $profileSection = $this->mProfiler->scopedProfileIn( $title->getPrefixedDBkey() );
-                       wfProfileIn( __METHOD__ . '-loadtpl' );
                        if ( !$title->isExternal() ) {
                                if ( $title->isSpecialPage()
                                        && $this->mOptions->getAllowSpecialInclusion()
@@ -3711,7 +3617,6 @@ class Parser {
                                        . '</span>';
                                wfDebug( __METHOD__ . ": template loop broken at '$titleText'\n" );
                        }
-                       wfProfileOut( __METHOD__ . '-loadtpl' );
                }
 
                # If we haven't found text to substitute by now, we're done
@@ -3721,7 +3626,6 @@ class Parser {
                        if ( $profileSection ) {
                                $this->mProfiler->scopedProfileOut( $profileSection );
                        }
-                       wfProfileOut( __METHOD__ );
                        return array( 'object' => $text );
                }
 
@@ -3787,7 +3691,6 @@ class Parser {
                        $ret = array( 'text' => $text );
                }
 
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -3813,7 +3716,6 @@ class Parser {
        public function callParserFunction( $frame, $function, array $args = array() ) {
                global $wgContLang;
 
-               wfProfileIn( __METHOD__ );
 
                # Case sensitive functions
                if ( isset( $this->mFunctionSynonyms[1][$function] ) ) {
@@ -3824,18 +3726,14 @@ class Parser {
                        if ( isset( $this->mFunctionSynonyms[0][$function] ) ) {
                                $function = $this->mFunctionSynonyms[0][$function];
                        } else {
-                               wfProfileOut( __METHOD__ );
                                return array( 'found' => false );
                        }
                }
 
-               wfProfileIn( __METHOD__ . '-pfunc-' . $function );
                list( $callback, $flags ) = $this->mFunctionHooks[$function];
 
                # Workaround for PHP bug 35229 and similar
                if ( !is_callable( $callback ) ) {
-                       wfProfileOut( __METHOD__ . '-pfunc-' . $function );
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( "Tag hook for $function is not callable\n" );
                }
 
@@ -3900,8 +3798,6 @@ class Parser {
                        $result['text'] = $this->preprocessToDom( $result['text'], $preprocessFlags );
                        $result['isChildObj'] = true;
                }
-               wfProfileOut( __METHOD__ . '-pfunc-' . $function );
-               wfProfileOut( __METHOD__ );
 
                return $result;
        }
@@ -4231,7 +4127,6 @@ class Parser {
         * @return array
         */
        public function argSubstitution( $piece, $frame ) {
-               wfProfileIn( __METHOD__ );
 
                $error = false;
                $parts = $piece['parts'];
@@ -4266,7 +4161,6 @@ class Parser {
                        $ret = array( 'text' => $text );
                }
 
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -4397,7 +4291,6 @@ class Parser {
         * @return string
         */
        public function doDoubleUnderscore( $text ) {
-               wfProfileIn( __METHOD__ );
 
                # The position of __TOC__ needs to be recorded
                $mw = MagicWord::get( 'toc' );
@@ -4445,7 +4338,6 @@ class Parser {
                        $this->mOutput->setProperty( $key, '' );
                }
 
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -5151,7 +5043,6 @@ class Parser {
                }
                $executing = true;
 
-               wfProfileIn( __METHOD__ );
                if ( !$title ) {
                        global $wgTitle;
                        $title = $wgTitle;
@@ -5160,7 +5051,6 @@ class Parser {
                $text = $this->preprocess( $text, $title, $options );
 
                $executing = false;
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -5387,7 +5277,6 @@ class Parser {
         * @return string HTML
         */
        public function renderImageGallery( $text, $params ) {
-               wfProfileIn( __METHOD__ );
 
                $mode = false;
                if ( isset( $params['mode'] ) ) {
@@ -5396,7 +5285,7 @@ class Parser {
 
                try {
                        $ig = ImageGalleryBase::factory( $mode );
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        // If invalid type set, fallback to default.
                        $ig = ImageGalleryBase::factory( false );
                }
@@ -5463,7 +5352,6 @@ class Parser {
                        $file = $this->fetchFileNoRegister( $title, $options );
                        $handler = $file ? $file->getHandler() : false;
 
-                       wfProfileIn( __METHOD__ . '-getMagicWord' );
                        $paramMap = array(
                                'img_alt' => 'gallery-internal-alt',
                                'img_link' => 'gallery-internal-link',
@@ -5476,7 +5364,6 @@ class Parser {
                        }
 
                        $mwArray = new MagicWordArray( array_keys( $paramMap ) );
-                       wfProfileOut( __METHOD__ . '-getMagicWord' );
 
                        $label = '';
                        $alt = '';
@@ -5539,7 +5426,6 @@ class Parser {
                }
                $html = $ig->toHTML();
                Hooks::run( 'AfterParserFetchFileAndTitle', array( $this, $ig, &$html ) );
-               wfProfileOut( __METHOD__ );
                return $html;
        }
 
@@ -6111,7 +5997,6 @@ class Parser {
         */
        public function getRevisionTimestamp() {
                if ( is_null( $this->mRevisionTimestamp ) ) {
-                       wfProfileIn( __METHOD__ );
 
                        global $wgContLang;
 
@@ -6126,7 +6011,6 @@ class Parser {
                        # it needs to be consistent for all visitors.
                        $this->mRevisionTimestamp = $wgContLang->userAdjust( $timestamp, '' );
 
-                       wfProfileOut( __METHOD__ );
                }
                return $this->mRevisionTimestamp;
        }
@@ -6381,14 +6265,12 @@ class Parser {
         * @return array
         */
        public function serializeHalfParsedText( $text ) {
-               wfProfileIn( __METHOD__ );
                $data = array(
                        'text' => $text,
                        'version' => self::HALF_PARSED_VERSION,
                        'stripState' => $this->mStripState->getSubState( $text ),
                        'linkHolders' => $this->mLinkHolders->getSubArray( $text )
                );
-               wfProfileOut( __METHOD__ );
                return $data;
        }
 
index 7952300..ad131f4 100644 (file)
@@ -184,12 +184,10 @@ class ParserCache {
         */
        public function get( $article, $popts, $useOutdated = false ) {
                global $wgCacheEpoch;
-               wfProfileIn( __METHOD__ );
 
                $canCache = $article->checkTouched();
                if ( !$canCache ) {
                        // It's a redirect now
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -198,7 +196,6 @@ class ParserCache {
                $parserOutputKey = $this->getKey( $article, $popts, $useOutdated );
                if ( $parserOutputKey === false ) {
                        wfIncrStats( 'pcache_miss_absent' );
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -206,7 +203,6 @@ class ParserCache {
                if ( !$value ) {
                        wfDebug( "ParserOutput cache miss.\n" );
                        wfIncrStats( "pcache_miss_absent" );
-                       wfProfileOut( __METHOD__ );
                        return false;
                }
 
@@ -233,7 +229,6 @@ class ParserCache {
                        wfIncrStats( "pcache_hit" );
                }
 
-               wfProfileOut( __METHOD__ );
                return $value;
        }
 
index ddeb906..b09fe76 100644 (file)
@@ -639,8 +639,6 @@ class ParserOptions {
                        $wgCleanSignatures, $wgExternalLinkTarget, $wgExpensiveParserFunctionLimit,
                        $wgMaxGeneratedPPNodeCount, $wgDisableLangConversion, $wgDisableTitleConversion;
 
-               wfProfileIn( __METHOD__ );
-
                // *UPDATE* ParserOptions::matches() if any of this changes as needed
                $this->mInterwikiMagic = $wgInterwikiMagic;
                $this->mAllowExternalImages = $wgAllowExternalImages;
@@ -664,7 +662,6 @@ class ParserOptions {
                $this->mStubThreshold = $user->getStubThreshold();
                $this->mUserLang = $lang;
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
index 1a2be5f..117e04a 100644 (file)
@@ -54,6 +54,7 @@ class ParserOutput extends CacheTime {
        private $mIndexPolicy = '';       # 'index' or 'noindex'?  Any other value will result in no change.
        private $mAccessedOptions = array(); # List of ParserOptions (stored in the keys)
        private $mSecondaryDataUpdates = array(); # List of DataUpdate, used to save info from the page somewhere else.
+       private $mCustomDataUpdateCount = 0; # Number of custom updaters in $mSecondaryDataUpdates.
        private $mExtensionData = array(); # extra data used by extensions
        private $mLimitReportData = array(); # Parser limit report data
        private $mParseStartTime = array(); # Timestamps for getTimeSinceStart()
@@ -73,7 +74,6 @@ class ParserOutput extends CacheTime {
        }
 
        public function getText() {
-               wfProfileIn( __METHOD__ );
                $text = $this->mText;
                if ( $this->mEditSectionTokens ) {
                        $text = preg_replace_callback(
@@ -111,7 +111,6 @@ class ParserOutput extends CacheTime {
                                $text
                        );
                }
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -682,12 +681,30 @@ class ParserOutput extends CacheTime {
         * from the page's content. This is triggered by calling getSecondaryDataUpdates()
         * and is used for forward links updates on edit and backlink updates by jobs.
         *
+        * @note: custom DataUpdates do not survive serialization of the ParserOutput!
+        * This is especially relevant when using a cached ParserOutput for updating
+        * the database, as WikiPage does if $wgAjaxStashEdit is enabled. For this
+        * reason, ApiStashEdit will skip any ParserOutput that has custom DataUpdates.
+        *
         * @since 1.20
         *
         * @param DataUpdate $update
         */
        public function addSecondaryDataUpdate( DataUpdate $update ) {
                $this->mSecondaryDataUpdates[] = $update;
+               $this->mCustomDataUpdateCount = count( $this->mSecondaryDataUpdates );
+       }
+
+       /**
+        * Whether this ParserOutput contains custom DataUpdate objects that may not survive
+        * serialization of the ParserOutput.
+        *
+        * @see __sleep()
+        *
+        * @return bool
+        */
+       public function hasCustomDataUpdates() {
+               return ( $this->mCustomDataUpdateCount > 0 );
        }
 
        /**
@@ -704,6 +721,9 @@ class ParserOutput extends CacheTime {
         *    be created based on $this->getTitleText()
         * @param bool $recursive Queue jobs for recursive updates?
         *
+        * @throws MWException if called on a ParserOutput instance that was restored from serialization.
+        *         DataUpdates are generally not serializable, so after serialization, they are undefined.
+        *
         * @return array An array of instances of DataUpdate
         */
        public function getSecondaryDataUpdates( Title $title = null, $recursive = true ) {
@@ -711,6 +731,15 @@ class ParserOutput extends CacheTime {
                        $title = Title::newFromText( $this->getTitleText() );
                }
 
+               if ( count( $this->mSecondaryDataUpdates ) !== $this->mCustomDataUpdateCount ) {
+                       // NOTE: This happens when mSecondaryDataUpdates are lost during serialization
+                       // (see __sleep below). After (un)serialization, getSecondaryDataUpdates()
+                       // has no defined behavior in that case, and should throw an exception.
+                       throw new MWException( 'getSecondaryDataUpdates() must not be called on ParserOutput restored from serialization.' );
+               }
+
+               // NOTE: ApiStashEdit knows about this "magic" update object. If this goes away,
+               // ApiStashEdit::buildStashValue needs to be adjusted.
                $linksUpdate = new LinksUpdate( $title, $this, $recursive );
 
                return array_merge( $this->mSecondaryDataUpdates, array( $linksUpdate ) );
index 7e0405c..3435881 100644 (file)
@@ -86,7 +86,6 @@ class Preprocessor_DOM implements Preprocessor {
 
                $xml .= "</list>";
 
-               wfProfileIn( __METHOD__ . '-loadXML' );
                $dom = new DOMDocument();
                wfSuppressWarnings();
                $result = $dom->loadXML( $xml );
@@ -98,7 +97,6 @@ class Preprocessor_DOM implements Preprocessor {
                        // don't barf when the XML is >256 levels deep
                        $result = $dom->loadXML( $xml, 1 << 19 );
                }
-               wfProfileOut( __METHOD__ . '-loadXML' );
 
                if ( !$result ) {
                        throw new MWException( 'Parameters passed to ' . __METHOD__ . ' result in invalid XML' );
@@ -150,14 +148,12 @@ class Preprocessor_DOM implements Preprocessor {
         * @return PPNode_DOM
         */
        public function preprocessToObj( $text, $flags = 0 ) {
-               wfProfileIn( __METHOD__ );
                global $wgMemc, $wgPreprocessorCacheThreshold;
 
                $xml = false;
                $cacheable = ( $wgPreprocessorCacheThreshold !== false
                        && strlen( $text ) > $wgPreprocessorCacheThreshold );
                if ( $cacheable ) {
-                       wfProfileIn( __METHOD__ . '-cacheable' );
 
                        $cacheKey = wfMemcKey( 'preprocess-xml', md5( $text ), $flags );
                        $cacheValue = $wgMemc->get( $cacheKey );
@@ -170,11 +166,9 @@ class Preprocessor_DOM implements Preprocessor {
                                }
                        }
                        if ( $xml === false ) {
-                               wfProfileIn( __METHOD__ . '-cache-miss' );
                                $xml = $this->preprocessToXml( $text, $flags );
                                $cacheValue = sprintf( "%08d", self::CACHE_VERSION ) . $xml;
                                $wgMemc->set( $cacheKey, $cacheValue, 86400 );
-                               wfProfileOut( __METHOD__ . '-cache-miss' );
                                wfDebugLog( "Preprocessor", "Saved preprocessor XML to memcached (key $cacheKey)" );
                        }
                } else {
@@ -187,13 +181,10 @@ class Preprocessor_DOM implements Preprocessor {
                $max = $this->parser->mOptions->getMaxGeneratedPPNodeCount();
                if ( $this->parser->mGeneratedPPNodeCount > $max ) {
                        if ( $cacheable ) {
-                               wfProfileOut( __METHOD__ . '-cacheable' );
                        }
-                       wfProfileOut( __METHOD__ );
                        throw new MWException( __METHOD__ . ': generated node count limit exceeded' );
                }
 
-               wfProfileIn( __METHOD__ . '-loadXML' );
                $dom = new DOMDocument;
                wfSuppressWarnings();
                $result = $dom->loadXML( $xml );
@@ -208,14 +199,10 @@ class Preprocessor_DOM implements Preprocessor {
                if ( $result ) {
                        $obj = new PPNode_DOM( $dom->documentElement );
                }
-               wfProfileOut( __METHOD__ . '-loadXML' );
 
                if ( $cacheable ) {
-                       wfProfileOut( __METHOD__ . '-cacheable' );
                }
 
-               wfProfileOut( __METHOD__ );
-
                if ( !$result ) {
                        throw new MWException( __METHOD__ . ' generated invalid XML' );
                }
@@ -228,7 +215,6 @@ class Preprocessor_DOM implements Preprocessor {
         * @return string
         */
        public function preprocessToXml( $text, $flags = 0 ) {
-               wfProfileIn( __METHOD__ );
                $rules = array(
                        '{' => array(
                                'end' => '}',
@@ -765,8 +751,6 @@ class Preprocessor_DOM implements Preprocessor {
                $stack->rootAccum .= '</root>';
                $xml = $stack->rootAccum;
 
-               wfProfileOut( __METHOD__ );
-
                return $xml;
        }
 }
@@ -1102,7 +1086,6 @@ class PPFrame_DOM implements PPFrame {
                        );
                        return '<span class="error">Expansion depth limit exceeded</span>';
                }
-               wfProfileIn( __METHOD__ );
                ++$expansionDepth;
                if ( $expansionDepth > $this->parser->mHighestExpansionDepth ) {
                        $this->parser->mHighestExpansionDepth = $expansionDepth;
@@ -1291,7 +1274,6 @@ class PPFrame_DOM implements PPFrame {
                                        $newIterator = $contextNode->childNodes;
                                }
                        } else {
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( __METHOD__ . ': Invalid parameter type' );
                        }
 
@@ -1315,7 +1297,6 @@ class PPFrame_DOM implements PPFrame {
                        }
                }
                --$expansionDepth;
-               wfProfileOut( __METHOD__ );
                return $outStack[0];
        }
 
index b4b14dc..af91ad4 100644 (file)
@@ -112,7 +112,6 @@ class Preprocessor_Hash implements Preprocessor {
         * @return PPNode_Hash_Tree
         */
        public function preprocessToObj( $text, $flags = 0 ) {
-               wfProfileIn( __METHOD__ );
 
                // Check cache.
                global $wgMemc, $wgPreprocessorCacheThreshold;
@@ -121,7 +120,6 @@ class Preprocessor_Hash implements Preprocessor {
                        && strlen( $text ) > $wgPreprocessorCacheThreshold;
 
                if ( $cacheable ) {
-                       wfProfileIn( __METHOD__ . '-cacheable' );
 
                        $cacheKey = wfMemcKey( 'preprocess-hash', md5( $text ), $flags );
                        $cacheValue = $wgMemc->get( $cacheKey );
@@ -132,12 +130,9 @@ class Preprocessor_Hash implements Preprocessor {
                                        // From the cache
                                        wfDebugLog( "Preprocessor",
                                                "Loaded preprocessor hash from memcached (key $cacheKey)" );
-                                       wfProfileOut( __METHOD__ . '-cacheable' );
-                                       wfProfileOut( __METHOD__ );
                                        return $hash;
                                }
                        }
-                       wfProfileIn( __METHOD__ . '-cache-miss' );
                }
 
                $rules = array(
@@ -637,18 +632,12 @@ class Preprocessor_Hash implements Preprocessor {
                                                        }
                                                        if ( !$node ) {
                                                                if ( $cacheable ) {
-                                                                       wfProfileOut( __METHOD__ . '-cache-miss' );
-                                                                       wfProfileOut( __METHOD__ . '-cacheable' );
                                                                }
-                                                               wfProfileOut( __METHOD__ );
                                                                throw new MWException( __METHOD__ . ': eqpos not found' );
                                                        }
                                                        if ( $node->name !== 'equals' ) {
                                                                if ( $cacheable ) {
-                                                                       wfProfileOut( __METHOD__ . '-cache-miss' );
-                                                                       wfProfileOut( __METHOD__ . '-cacheable' );
                                                                }
-                                                               wfProfileOut( __METHOD__ );
                                                                throw new MWException( __METHOD__ . ': eqpos is not equals' );
                                                        }
                                                        $equalsNode = $node;
@@ -748,12 +737,9 @@ class Preprocessor_Hash implements Preprocessor {
                if ( $cacheable ) {
                        $cacheValue = sprintf( "%08d", self::CACHE_VERSION ) . serialize( $rootNode );
                        $wgMemc->set( $cacheKey, $cacheValue, 86400 );
-                       wfProfileOut( __METHOD__ . '-cache-miss' );
-                       wfProfileOut( __METHOD__ . '-cacheable' );
                        wfDebugLog( "Preprocessor", "Saved preprocessor Hash to memcached (key $cacheKey)" );
                }
 
-               wfProfileOut( __METHOD__ );
                return $rootNode;
        }
 }
index 5d1743e..51ae42d 100644 (file)
@@ -117,12 +117,10 @@ class StripState {
                        return $text;
                }
 
-               wfProfileIn( __METHOD__ );
                $oldType = $this->tempType;
                $this->tempType = $type;
                $text = preg_replace_callback( $this->regex, array( $this, 'unstripCallback' ), $text );
                $this->tempType = $oldType;
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
index 0f025f3..98797a3 100644 (file)
@@ -121,7 +121,6 @@ class PoolCounterRedis extends PoolCounter {
        }
 
        function acquireForMe() {
-               $section = new ProfileSection( __METHOD__ );
 
                $status = $this->precheckAcquire();
                if ( !$status->isGood() ) {
@@ -132,7 +131,6 @@ class PoolCounterRedis extends PoolCounter {
        }
 
        function acquireForAnyone() {
-               $section = new ProfileSection( __METHOD__ );
 
                $status = $this->precheckAcquire();
                if ( !$status->isGood() ) {
@@ -143,7 +141,6 @@ class PoolCounterRedis extends PoolCounter {
        }
 
        function release() {
-               $section = new ProfileSection( __METHOD__ );
 
                if ( $this->slot === null ) {
                        return Status::newGood( PoolCounter::NOT_LOCKED ); // not locked
index ca80ebc..68ef668 100644 (file)
  * Class for handling function-scope profiling
  *
  * @since 1.22
+ * @deprecated 1.25 No-op now
  */
 class ProfileSection {
-       /** @var string $name Method name */
-       protected $name;
-       /** @var boolean $enabled Is profiling enabled? */
-       protected $enabled = false;
-
        /**
         * Begin profiling of a function and return an object that ends profiling
         * of the function when that object leaves scope. As long as the object is
@@ -43,21 +39,5 @@ class ProfileSection {
         *
         * @param string $name Name of the function to profile
         */
-       public function __construct( $name ) {
-               $this->name = $name;
-               // Use Profiler member variable directly to reduce overhead
-               if ( Profiler::$__instance === null ) {
-                       Profiler::instance();
-               }
-               if ( !( Profiler::$__instance instanceof ProfilerStub ) ) {
-                       $this->enabled = true;
-                       Profiler::$__instance->profileIn( $this->name );
-               }
-       }
-
-       function __destruct() {
-               if ( $this->enabled ) {
-                       Profiler::$__instance->profileOut( $this->name );
-               }
-       }
+       public function __construct( $name ) {}
 }
index 667a9e2..9bb2db9 100644 (file)
@@ -118,19 +118,9 @@ abstract class Profiler {
                }
        }
 
-       /**
-        * Called by wfProfieIn()
-        *
-        * @param string $functionname
-        */
-       abstract public function profileIn( $functionname );
-
-       /**
-        * Called by wfProfieOut()
-        *
-        * @param string $functionname
-        */
-       abstract public function profileOut( $functionname );
+       // Kept BC for now, remove when possible
+       public function profileIn( $functionname ) {}
+       public function profileOut( $functionname ) {}
 
        /**
         * Mark the start of a custom profiling frame (e.g. DB queries).
index a0d5943..4984e77 100644 (file)
@@ -42,27 +42,15 @@ function wfGetRusage() {
 /**
  * Begin profiling of a function
  * @param string $functionname Name of the function we will profile
+ * @deprecated 1.25
  */
 function wfProfileIn( $functionname ) {
-       // Use Profiler member variable directly to reduce overhead
-       if ( Profiler::$__instance === null ) {
-               Profiler::instance();
-       }
-       if ( !( Profiler::$__instance instanceof ProfilerStub ) ) {
-               Profiler::$__instance->profileIn( $functionname );
-       }
 }
 
 /**
  * Stop profiling of a function
  * @param string $functionname Name of the function we have profiled
+ * @deprecated 1.25
  */
 function wfProfileOut( $functionname = 'missing' ) {
-       // Use Profiler member variable directly to reduce overhead
-       if ( Profiler::$__instance === null ) {
-               Profiler::instance();
-       }
-       if ( !( Profiler::$__instance instanceof ProfilerStub ) ) {
-               Profiler::$__instance->profileOut( $functionname );
-       }
 }
diff --git a/includes/profiler/ProfilerSectionOnly.php b/includes/profiler/ProfilerSectionOnly.php
new file mode 100755 (executable)
index 0000000..1f8d33b
--- /dev/null
@@ -0,0 +1,104 @@
+<?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
+ */
+
+/**
+ * Profiler that only tracks explicit profiling sections
+ *
+ * @code
+ * $wgProfiler['class'] = 'ProfilerSectionOnly';
+ * $wgProfiler['output'] = 'text';
+ * $wgProfiler['visible'] = true;
+ * @endcode
+ *
+ * @author Aaron Schulz
+ * @ingroup Profiler
+ * @since 1.25
+ */
+class ProfilerSectionOnly extends Profiler {
+       /** @var SectionProfiler */
+       protected $sprofiler;
+
+       public function __construct( array $params = array() ) {
+               parent::__construct( $params );
+               $this->sprofiler = new SectionProfiler();
+       }
+
+       public function scopedProfileIn( $section ) {
+               return $this->sprofiler->scopedProfileIn( $section );
+       }
+
+       public function close() {
+       }
+
+       public function getFunctionStats() {
+               return $this->sprofiler->getFunctionStats();
+       }
+
+       public function getOutput() {
+               return $this->getFunctionReport();
+       }
+
+       /**
+        * Get a report of profiled functions sorted by inclusive wall clock time
+        * in descending order.
+        *
+        * Each line of the report includes this data:
+        * - Function name
+        * - Number of times function was called
+        * - Total wall clock time spent in function in microseconds
+        * - Minimum wall clock time spent in function in microseconds
+        * - Average wall clock time spent in function in microseconds
+        * - Maximum wall clock time spent in function in microseconds
+        * - Percentage of total wall clock time spent in function
+        * - Total delta of memory usage from start to end of function in bytes
+        *
+        * @return string
+        */
+       protected function getFunctionReport() {
+               $data = $this->getFunctionStats();
+               usort( $data, function( $a, $b ) {
+                       if ( $a['real'] === $b['real'] ) {
+                               return 0;
+                       }
+                       return ( $a['real'] > $b['real'] ) ? -1 : 1; // descending
+               } );
+
+               $width = 140;
+               $nameWidth = $width - 65;
+               $format = "%-{$nameWidth}s %6d %9d %9d %9d %9d %7.3f%% %9d";
+               $out = array();
+               $out[] = sprintf( "%-{$nameWidth}s %6s %9s %9s %9s %9s %7s %9s",
+                       'Name', 'Calls', 'Total', 'Min', 'Each', 'Max', '%', 'Mem'
+               );
+               foreach ( $data as $stats ) {
+                       $out[] = sprintf( $format,
+                               $stats['name'],
+                               $stats['calls'],
+                               $stats['real'] * 1000,
+                               $stats['min_real'] * 1000,
+                               $stats['real'] / $stats['calls'] * 1000,
+                               $stats['max_real'] * 1000,
+                               $stats['%real'],
+                               $stats['memory']
+                       );
+               }
+               return implode( "\n", $out );
+       }
+}
diff --git a/includes/profiler/ProfilerSimpleTrace.php b/includes/profiler/ProfilerSimpleTrace.php
deleted file mode 100644 (file)
index 893d960..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-<?php
-/**
- * Profiler showing execution trace.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 Profiler
- */
-
-/**
- * Execution trace profiler
- * @todo document methods (?)
- * @ingroup Profiler
- */
-class ProfilerSimpleTrace extends ProfilerStandard {
-       protected $trace = "Beginning trace: \n";
-       protected $memory = 0;
-
-       public function profileIn( $functionname ) {
-               parent::profileIn( $functionname );
-
-               $this->trace .= "         " . sprintf( "%6.1f", $this->memoryDiff() ) .
-                       str_repeat( " ", count( $this->workStack ) ) . " > " . $functionname . "\n";
-       }
-
-       public function profileOut( $functionname ) {
-               $item = end( $this->workStack );
-
-               parent::profileOut( $functionname );
-
-               if ( !$item ) {
-                       $this->trace .= "Profiling error: $functionname\n";
-               } else {
-                       list( $ofname, /* $ocount */, $ortime ) = $item;
-                       if ( $functionname == 'close' ) {
-                               $message = "Profile section ended by close(): {$ofname}";
-                               $functionname = $ofname;
-                               $this->trace .= $message . "\n";
-                       } elseif ( $ofname != $functionname ) {
-                               $this->trace .= "Profiling error: in({$ofname}), out($functionname)";
-                       }
-                       $elapsedreal = $this->getTime() - $ortime;
-                       $this->trace .= sprintf( "%03.6f %6.1f", $elapsedreal, $this->memoryDiff() ) .
-                               str_repeat( " ", count( $this->workStack ) + 1 ) . " < " . $functionname . "\n";
-               }
-       }
-
-       protected function memoryDiff() {
-               $diff = memory_get_usage() - $this->memory;
-               $this->memory = memory_get_usage();
-               return $diff / 1024;
-       }
-
-       public function logData() {
-               if ( $this->templated ) {
-                       $contentType = $this->getContentType();
-                       if ( PHP_SAPI === 'cli' ) {
-                               print "<!-- \n {$this->trace} \n -->";
-                       } elseif ( $contentType === 'text/html' ) {
-                               print "<!-- \n {$this->trace} \n -->";
-                       } elseif ( $contentType === 'text/javascript' ) {
-                               print "\n/*\n {$this->trace}\n*/";
-                       } elseif ( $contentType === 'text/css' ) {
-                               print "\n/*\n {$this->trace}\n*/";
-                       }
-               }
-       }
-}
diff --git a/includes/profiler/ProfilerStandard.php b/includes/profiler/ProfilerStandard.php
deleted file mode 100644 (file)
index 4ce88bd..0000000
+++ /dev/null
@@ -1,628 +0,0 @@
-<?php
-/**
- * Common implementation class for profiling.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public 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 Profiler
- */
-
-/**
- * Standard profiler that tracks real time, cpu time, and memory deltas
- *
- * This supports profile reports, the debug toolbar, and high-contention
- * DB query warnings. This does not persist the profiling data though.
- *
- * @ingroup Profiler
- * @since 1.24
- */
-class ProfilerStandard extends Profiler {
-       /** @var array List of resolved profile calls with start/end data */
-       protected $stack = array();
-       /** @var array Queue of open profile calls with start data */
-       protected $workStack = array();
-
-       /** @var array Map of (function name => aggregate data array) */
-       protected $collated = array();
-       /** @var bool */
-       protected $collateDone = false;
-       /** @var bool Whether to collect the full stack trace or just aggregates */
-       protected $collateOnly = true;
-       /** @var array Cache of a standard broken collation entry */
-       protected $errorEntry;
-
-       /**
-        * @param array $params
-        *   - initTotal : set to false to omit -total/-setup entries (which use request start time)
-        */
-       public function __construct( array $params ) {
-               parent::__construct( $params );
-
-               if ( !isset( $params['initTotal'] ) || $params['initTotal'] ) {
-                       $this->addInitialStack();
-               }
-       }
-
-       /**
-        * Add the inital item in the stack.
-        */
-       protected function addInitialStack() {
-               $this->errorEntry = $this->getErrorEntry();
-
-               $initialTime = $this->getInitialTime( 'wall' );
-               $initialCpu = $this->getInitialTime( 'cpu' );
-               if ( $initialTime !== null && $initialCpu !== null ) {
-                       $this->workStack[] = array( '-total', 0, $initialTime, $initialCpu, 0 );
-                       if ( $this->collateOnly ) {
-                               $this->workStack[] = array( '-setup', 1, $initialTime, $initialCpu, 0 );
-                               $this->profileOut( '-setup' );
-                       } else {
-                               $this->stack[] = array( '-setup', 1, $initialTime, $initialCpu, 0,
-                                       $this->getTime( 'wall' ), $this->getTime( 'cpu' ), 0 );
-                       }
-               } else {
-                       $this->profileIn( '-total' );
-               }
-       }
-
-       /**
-        * @return array Initial collation entry
-        */
-       protected function getZeroEntry() {
-               return array(
-                       'cpu'      => 0.0,
-                       'cpu_sq'   => 0.0,
-                       'real'     => 0.0,
-                       'real_sq'  => 0.0,
-                       'memory'   => 0,
-                       'count'    => 0,
-                       'min_cpu'  => 0.0,
-                       'max_cpu'  => 0.0,
-                       'min_real' => 0.0,
-                       'max_real' => 0.0,
-                       'periods'  => array(), // not filled if collateOnly
-                       'overhead' => 0 // not filled if collateOnly
-               );
-       }
-
-       /**
-        * @return array Initial collation entry for errors
-        */
-       protected function getErrorEntry() {
-               $entry = $this->getZeroEntry();
-               $entry['count'] = 1;
-               return $entry;
-       }
-
-       /**
-        * Update the collation entry for a given method name
-        *
-        * @param string $name
-        * @param float $elapsedCpu
-        * @param float $elapsedReal
-        * @param int $memChange
-        * @param int $subcalls
-        * @param array|null $period Map of ('start','end','memory','subcalls')
-        */
-       protected function updateEntry(
-               $name, $elapsedCpu, $elapsedReal, $memChange, $subcalls = 0, $period = null
-       ) {
-               $entry =& $this->collated[$name];
-               if ( !is_array( $entry ) ) {
-                       $entry = $this->getZeroEntry();
-                       $this->collated[$name] =& $entry;
-               }
-               $entry['cpu'] += $elapsedCpu;
-               $entry['cpu_sq'] += $elapsedCpu * $elapsedCpu;
-               $entry['real'] += $elapsedReal;
-               $entry['real_sq'] += $elapsedReal * $elapsedReal;
-               $entry['memory'] += $memChange > 0 ? $memChange : 0;
-               $entry['count']++;
-               $entry['min_cpu'] = $elapsedCpu < $entry['min_cpu'] ? $elapsedCpu : $entry['min_cpu'];
-               $entry['max_cpu'] = $elapsedCpu > $entry['max_cpu'] ? $elapsedCpu : $entry['max_cpu'];
-               $entry['min_real'] = $elapsedReal < $entry['min_real'] ? $elapsedReal : $entry['min_real'];
-               $entry['max_real'] = $elapsedReal > $entry['max_real'] ? $elapsedReal : $entry['max_real'];
-               // Apply optional fields
-               $entry['overhead'] += $subcalls;
-               if ( $period ) {
-                       $entry['periods'][] = $period;
-               }
-       }
-
-       /**
-        * Called by wfProfieIn()
-        *
-        * @param string $functionname
-        */
-       public function profileIn( $functionname ) {
-               global $wgDebugFunctionEntry;
-
-               if ( $wgDebugFunctionEntry ) {
-                       $this->debug( str_repeat( ' ', count( $this->workStack ) ) .
-                               'Entering ' . $functionname . "\n" );
-               }
-
-               $this->workStack[] = array(
-                       $functionname,
-                       count( $this->workStack ),
-                       $this->getTime( 'time' ),
-                       $this->getTime( 'cpu' ),
-                       memory_get_usage()
-               );
-       }
-
-       /**
-        * Called by wfProfieOut()
-        *
-        * @param string $functionname
-        */
-       public function profileOut( $functionname ) {
-               global $wgDebugFunctionEntry;
-
-               if ( $wgDebugFunctionEntry ) {
-                       $this->debug( str_repeat( ' ', count( $this->workStack ) - 1 ) .
-                               'Exiting ' . $functionname . "\n" );
-               }
-
-               $item = array_pop( $this->workStack );
-               list( $ofname, /* $ocount */, $ortime, $octime, $omem ) = $item;
-
-               if ( $item === null ) {
-                       $this->debugGroup( 'profileerror', "Profiling error: $functionname" );
-               } else {
-                       if ( $functionname === 'close' ) {
-                               if ( $ofname !== '-total' ) {
-                                       $message = "Profile section ended by close(): {$ofname}";
-                                       $this->debugGroup( 'profileerror', $message );
-                                       if ( $this->collateOnly ) {
-                                               $this->collated[$message] = $this->errorEntry;
-                                       } else {
-                                               $this->stack[] = array( $message, 0, 0.0, 0.0, 0, 0.0, 0.0, 0 );
-                                       }
-                               }
-                               $functionname = $ofname;
-                       } elseif ( $ofname !== $functionname ) {
-                               $message = "Profiling error: in({$ofname}), out($functionname)";
-                               $this->debugGroup( 'profileerror', $message );
-                               if ( $this->collateOnly ) {
-                                       $this->collated[$message] = $this->errorEntry;
-                               } else {
-                                       $this->stack[] = array( $message, 0, 0.0, 0.0, 0, 0.0, 0.0, 0 );
-                               }
-                       }
-                       $realTime = $this->getTime( 'wall' );
-                       $cpuTime = $this->getTime( 'cpu' );
-                       if ( $this->collateOnly ) {
-                               $elapsedcpu = $cpuTime - $octime;
-                               $elapsedreal = $realTime - $ortime;
-                               $memchange = memory_get_usage() - $omem;
-                               $this->updateEntry( $functionname, $elapsedcpu, $elapsedreal, $memchange );
-                       } else {
-                               $this->stack[] = array_merge( $item,
-                                       array( $realTime, $cpuTime,     memory_get_usage() ) );
-                       }
-               }
-       }
-
-       public function scopedProfileIn( $section ) {
-               $this->profileIn( $section );
-
-               $that = $this;
-               return new ScopedCallback( function () use ( $that, $section ) {
-                       $that->profileOut( $section );
-               } );
-       }
-
-       /**
-        * Close opened profiling sections
-        */
-       public function close() {
-               while ( count( $this->workStack ) ) {
-                       $this->profileOut( 'close' );
-               }
-       }
-
-       /**
-        * Returns a profiling output to be stored in debug file
-        *
-        * @return string
-        */
-       public function getOutput() {
-               global $wgDebugFunctionEntry, $wgProfileCallTree;
-
-               $wgDebugFunctionEntry = false; // hack
-
-               if ( !count( $this->stack ) && !count( $this->collated ) ) {
-                       return "No profiling output\n";
-               }
-
-               if ( $wgProfileCallTree ) {
-                       return $this->getCallTree();
-               } else {
-                       return $this->getFunctionReport();
-               }
-       }
-
-       /**
-        * Returns a tree of function call instead of a list of functions
-        * @return string
-        */
-       protected function getCallTree() {
-               return implode( '', array_map(
-                       array( &$this, 'getCallTreeLine' ), $this->remapCallTree( $this->stack )
-               ) );
-       }
-
-       /**
-        * Recursive function the format the current profiling array into a tree
-        *
-        * @param array $stack Profiling array
-        * @return array
-        */
-       protected function remapCallTree( array $stack ) {
-               if ( count( $stack ) < 2 ) {
-                       return $stack;
-               }
-               $outputs = array();
-               for ( $max = count( $stack ) - 1; $max > 0; ) {
-                       /* Find all items under this entry */
-                       $level = $stack[$max][1];
-                       $working = array();
-                       for ( $i = $max -1; $i >= 0; $i-- ) {
-                               if ( $stack[$i][1] > $level ) {
-                                       $working[] = $stack[$i];
-                               } else {
-                                       break;
-                               }
-                       }
-                       $working = $this->remapCallTree( array_reverse( $working ) );
-                       $output = array();
-                       foreach ( $working as $item ) {
-                               array_push( $output, $item );
-                       }
-                       array_unshift( $output, $stack[$max] );
-                       $max = $i;
-
-                       array_unshift( $outputs, $output );
-               }
-               $final = array();
-               foreach ( $outputs as $output ) {
-                       foreach ( $output as $item ) {
-                               $final[] = $item;
-                       }
-               }
-               return $final;
-       }
-
-       /**
-        * Callback to get a formatted line for the call tree
-        * @param array $entry
-        * @return string
-        */
-       protected function getCallTreeLine( $entry ) {
-               list( $fname, $level, $startreal, , , $endreal ) = $entry;
-               $delta = $endreal - $startreal;
-               $space = str_repeat( ' ', $level );
-               # The ugly double sprintf is to work around a PHP bug,
-               # which has been fixed in recent releases.
-               return sprintf( "%10s %s %s\n",
-                       trim( sprintf( "%7.3f", $delta * 1000.0 ) ), $space, $fname );
-       }
-
-       /**
-        * Return the collated data, collating first if need be
-        * @return array
-        */
-       public function getCollatedData() {
-               if ( !$this->collateDone ) {
-                       $this->collateData();
-               }
-               return $this->collated;
-       }
-
-       /**
-        * Populate collated
-        */
-       protected function collateData() {
-               if ( $this->collateDone ) {
-                       return;
-               }
-               $this->collateDone = true;
-               $this->close(); // set "-total" entry
-
-               if ( $this->collateOnly ) {
-                       // already collated as methods exited
-                       $this->sortCollated();
-                       return;
-               }
-
-               $this->collated = array();
-
-               # Estimate profiling overhead
-               $profileCount = count( $this->stack );
-               self::calculateOverhead( $profileCount );
-
-               # First, subtract the overhead!
-               $overheadTotal = $overheadMemory = $overheadInternal = array();
-               foreach ( $this->stack as $entry ) {
-                       // $entry is (name,pos,rtime0,cputime0,mem0,rtime1,cputime1,mem1)
-                       $fname = $entry[0];
-                       $elapsed = $entry[5] - $entry[2];
-                       $memchange = $entry[7] - $entry[4];
-
-                       if ( $fname === '-overhead-total' ) {
-                               $overheadTotal[] = $elapsed;
-                               $overheadMemory[] = max( 0, $memchange );
-                       } elseif ( $fname === '-overhead-internal' ) {
-                               $overheadInternal[] = $elapsed;
-                       }
-               }
-               $overheadTotal = $overheadTotal ?
-                       array_sum( $overheadTotal ) / count( $overheadInternal ) : 0;
-               $overheadMemory = $overheadMemory ?
-                       array_sum( $overheadMemory ) / count( $overheadInternal ) : 0;
-               $overheadInternal = $overheadInternal ?
-                       array_sum( $overheadInternal ) / count( $overheadInternal ) : 0;
-
-               # Collate
-               foreach ( $this->stack as $index => $entry ) {
-                       // $entry is (name,pos,rtime0,cputime0,mem0,rtime1,cputime1,mem1)
-                       $fname = $entry[0];
-                       $elapsedCpu = $entry[6] - $entry[3];
-                       $elapsedReal = $entry[5] - $entry[2];
-                       $memchange = $entry[7] - $entry[4];
-                       $subcalls = $this->calltreeCount( $this->stack, $index );
-
-                       if ( substr( $fname, 0, 9 ) !== '-overhead' ) {
-                               # Adjust for profiling overhead (except special values with elapsed=0
-                               if ( $elapsed ) {
-                                       $elapsed -= $overheadInternal;
-                                       $elapsed -= ( $subcalls * $overheadTotal );
-                                       $memchange -= ( $subcalls * $overheadMemory );
-                               }
-                       }
-
-                       $period = array( 'start' => $entry[2], 'end' => $entry[5],
-                               'memory' => $memchange, 'subcalls' => $subcalls );
-                       $this->updateEntry( $fname, $elapsedCpu, $elapsedReal, $memchange, $subcalls, $period );
-               }
-
-               $this->collated['-overhead-total']['count'] = $profileCount;
-               $this->sortCollated();
-       }
-
-       protected function sortCollated() {
-               uksort( $this->collated, function ( $a, $b ) {
-                       $ca = $this->collated[$a]['real'];
-                       $cb = $this->collated[$b]['real'];
-                       if ( $ca > $cb ) {
-                               return -1;
-                       } elseif ( $cb > $ca ) {
-                               return 1;
-                       } else {
-                               return 0;
-                       }
-               } );
-       }
-
-       /**
-        * Returns a list of profiled functions.
-        *
-        * @return string
-        */
-       protected function getFunctionReport() {
-               $this->collateData();
-
-               $width = 140;
-               $nameWidth = $width - 65;
-               $format = "%-{$nameWidth}s %6d %13.3f %13.3f %13.3f%% %9d  (%13.3f -%13.3f) [%d]\n";
-               $titleFormat = "%-{$nameWidth}s %6s %13s %13s %13s %9s\n";
-               $prof = "\nProfiling data\n";
-               $prof .= sprintf( $titleFormat, 'Name', 'Calls', 'Total', 'Each', '%', 'Mem' );
-
-               $total = isset( $this->collated['-total'] )
-                       ? $this->collated['-total']['real']
-                       : 0;
-
-               foreach ( $this->collated as $fname => $data ) {
-                       $calls = $data['count'];
-                       $percent = $total ? 100 * $data['real'] / $total : 0;
-                       $memory = $data['memory'];
-                       $prof .= sprintf( $format,
-                               substr( $fname, 0, $nameWidth ),
-                               $calls,
-                               (float)( $data['real'] * 1000 ),
-                               (float)( $data['real'] * 1000 ) / $calls,
-                               $percent,
-                               $memory,
-                               ( $data['min_real'] * 1000.0 ),
-                               ( $data['max_real'] * 1000.0 ),
-                               $data['overhead']
-                       );
-               }
-               $prof .= "\nTotal: $total\n\n";
-
-               return $prof;
-       }
-
-       public function getFunctionStats() {
-               // This method is called before shutdown in the footer method on Skins.
-               // If some outer methods have not yet called wfProfileOut(), work around
-               // that by clearing anything in the work stack to just the "-total" entry.
-               // Collate after doing this so the results do not include profile errors.
-               if ( count( $this->workStack ) > 1 ) {
-                       $oldWorkStack = $this->workStack;
-                       $this->workStack = array( $this->workStack[0] ); // just the "-total" one
-               } else {
-                       $oldWorkStack = null;
-               }
-               $this->collateData();
-               // If this trick is used, then the old work stack is swapped back afterwards
-               // and collateDone is reset to false. This means that logData() will still
-               // make use of all the method data since the missing wfProfileOut() calls
-               // should be made by the time it is called.
-               if ( $oldWorkStack ) {
-                       $this->workStack = $oldWorkStack;
-                       $this->collateDone = false;
-               }
-
-               $totalCpu = isset( $this->collated['-total'] )
-                       ? $this->collated['-total']['cpu']
-                       : 0;
-               $totalReal = isset( $this->collated['-total'] )
-                       ? $this->collated['-total']['real']
-                       : 0;
-               $totalMem = isset( $this->collated['-total'] )
-                       ? $this->collated['-total']['memory']
-                       : 0;
-
-               $profile = array();
-               foreach ( $this->collated as $fname => $data ) {
-                       $profile[] = array(
-                               'name' => $fname,
-                               'calls' => $data['count'],
-                               'real' => $data['real'] * 1000,
-                               '%real' => $totalReal ? 100 * $data['real'] / $totalReal : 0,
-                               'cpu' => $data['cpu'] * 1000,
-                               '%cpu' => $totalCpu ? 100 * $data['cpu'] / $totalCpu : 0,
-                               'memory' => $data['memory'],
-                               '%memory' => $totalMem ? 100 * $data['memory'] / $totalMem : 0,
-                               'min_real' => $data['min_real'] * 1000,
-                               'max_real' => $data['max_real'] * 1000
-                       );
-               }
-
-               return $profile;
-       }
-
-       /**
-        * Dummy calls to wfProfileIn/wfProfileOut to calculate its overhead
-        * @param int $profileCount
-        */
-       protected static function calculateOverhead( $profileCount ) {
-               wfProfileIn( '-overhead-total' );
-               for ( $i = 0; $i < $profileCount; $i++ ) {
-                       wfProfileIn( '-overhead-internal' );
-                       wfProfileOut( '-overhead-internal' );
-               }
-               wfProfileOut( '-overhead-total' );
-       }
-
-       /**
-        * Counts the number of profiled function calls sitting under
-        * the given point in the call graph. Not the most efficient algo.
-        *
-        * @param array $stack
-        * @param int $start
-        * @return int
-        */
-       protected function calltreeCount( $stack, $start ) {
-               $level = $stack[$start][1];
-               $count = 0;
-               for ( $i = $start -1; $i >= 0 && $stack[$i][1] > $level; $i-- ) {
-                       $count ++;
-               }
-               return $count;
-       }
-
-       /**
-        * Get the initial time of the request, based either on $wgRequestTime or
-        * $wgRUstart. Will return null if not able to find data.
-        *
-        * @param string|bool $metric Metric to use, with the following possibilities:
-        *   - user: User CPU time (without system calls)
-        *   - cpu: Total CPU time (user and system calls)
-        *   - wall (or any other string): elapsed time
-        *   - false (default): will fall back to default metric
-        * @return float|null
-        */
-       protected function getTime( $metric = 'wall' ) {
-               if ( $metric === 'cpu' || $metric === 'user' ) {
-                       $ru = wfGetRusage();
-                       if ( !$ru ) {
-                               return 0;
-                       }
-                       $time = $ru['ru_utime.tv_sec'] + $ru['ru_utime.tv_usec'] / 1e6;
-                       if ( $metric === 'cpu' ) {
-                               # This is the time of system calls, added to the user time
-                               # it gives the total CPU time
-                               $time += $ru['ru_stime.tv_sec'] + $ru['ru_stime.tv_usec'] / 1e6;
-                       }
-                       return $time;
-               } else {
-                       return microtime( true );
-               }
-       }
-
-       /**
-        * Get the initial time of the request, based either on $wgRequestTime or
-        * $wgRUstart. Will return null if not able to find data.
-        *
-        * @param string|bool $metric Metric to use, with the following possibilities:
-        *   - user: User CPU time (without system calls)
-        *   - cpu: Total CPU time (user and system calls)
-        *   - wall (or any other string): elapsed time
-        *   - false (default): will fall back to default metric
-        * @return float|null
-        */
-       protected function getInitialTime( $metric = 'wall' ) {
-               global $wgRequestTime, $wgRUstart;
-
-               if ( $metric === 'cpu' || $metric === 'user' ) {
-                       if ( !count( $wgRUstart ) ) {
-                               return null;
-                       }
-
-                       $time = $wgRUstart['ru_utime.tv_sec'] + $wgRUstart['ru_utime.tv_usec'] / 1e6;
-                       if ( $metric === 'cpu' ) {
-                               # This is the time of system calls, added to the user time
-                               # it gives the total CPU time
-                               $time += $wgRUstart['ru_stime.tv_sec'] + $wgRUstart['ru_stime.tv_usec'] / 1e6;
-                       }
-                       return $time;
-               } else {
-                       if ( empty( $wgRequestTime ) ) {
-                               return null;
-                       } else {
-                               return $wgRequestTime;
-                       }
-               }
-       }
-
-       /**
-        * Add an entry in the debug log file
-        *
-        * @param string $s String to output
-        */
-       protected function debug( $s ) {
-               if ( function_exists( 'wfDebug' ) ) {
-                       wfDebug( $s );
-               }
-       }
-
-       /**
-        * Add an entry in the debug log group
-        *
-        * @param string $group Group to send the message to
-        * @param string $s String to output
-        */
-       protected function debugGroup( $group, $s ) {
-               if ( function_exists( 'wfDebugLog' ) ) {
-                       wfDebugLog( $group, $s );
-               }
-       }
-}
index 1d77cc0..5580f94 100644 (file)
  * @ingroup Profiler
  */
 class ProfilerStub extends Profiler {
-       public function profileIn( $fn ) {
-       }
-
-       public function profileOut( $fn ) {
-       }
-
        public function scopedProfileIn( $section ) {
                return new ScopedCallback( null ); // no-op
        }
index 624433b..7a50497 100644 (file)
@@ -21,9 +21,6 @@
 /**
  * Profiler wrapper for XHProf extension.
  *
- * Mimics the output of ProfilerStandard using data collected via the XHProf
- * PHP extension.
- *
  * @code
  * $wgProfiler['class'] = 'ProfilerXhprof';
  * $wgProfiler['flags'] = XHPROF_FLAGS_NO_BUILTINS;
  * $wgProfiler['output'] = 'udp';
  * @endcode
  *
- * Rather than obeying wfProfileIn() and wfProfileOut() calls placed in the
- * application code, ProfilerXhprof profiles all functions using the XHProf
- * PHP extenstion. For PHP5 users, this extension can be installed via PECL or
- * your operating system's package manager. XHProf support is built into HHVM.
+ * ProfilerXhprof profiles all functions using the XHProf PHP extenstion.
+ * For PHP5 users, this extension can be installed via PECL or your operating
+ * system's package manager. XHProf support is built into HHVM.
  *
  * To restrict the functions for which profiling data is collected, you can
  * use either a whitelist ($wgProfiler['include']) or a blacklist
@@ -80,28 +76,6 @@ class ProfilerXhprof extends Profiler {
                $this->sprofiler = new SectionProfiler();
        }
 
-       /**
-        * No-op for xhprof profiling.
-        *
-        * Use the 'include' configuration key instead if you need to constrain
-        * the functions that are profiled.
-        *
-        * @param string $functionname
-        */
-       public function profileIn( $functionname ) {
-       }
-
-       /**
-        * No-op for xhprof profiling.
-        *
-        * Use the 'include' configuration key instead if you need to constrain
-        * the functions that are profiled.
-        *
-        * @param string $functionname
-        */
-       public function profileOut( $functionname ) {
-       }
-
        public function scopedProfileIn( $section ) {
                return $this->sprofiler->scopedProfileIn( $section );
        }
@@ -118,7 +92,7 @@ class ProfilerXhprof extends Profiler {
 
                $main = null; // units in ms
                foreach ( $metrics as $fname => $stats ) {
-                       // Convert elapsed times from μs to ms to match ProfilerStandard
+                       // Convert elapsed times from μs to ms to match interface
                        $entry = array(
                                'name' => $fname,
                                'calls' => $stats['ct'],
diff --git a/includes/registration/ExtensionProcessor.php b/includes/registration/ExtensionProcessor.php
new file mode 100644 (file)
index 0000000..459d95b
--- /dev/null
@@ -0,0 +1,257 @@
+<?php
+
+class ExtensionProcessor implements Processor {
+
+       /**
+        * Keys that should be set to $GLOBALS
+        *
+        * @var array
+        */
+       protected static $globalSettings = array(
+               'ResourceLoaderSources',
+               'ResourceLoaderLESSVars',
+               'ResourceLoaderLESSImportPaths',
+               'TrackingCategories',
+               'DefaultUserOptions',
+               'HiddenPrefs',
+               'GroupPermissions',
+               'RevokePermissions',
+               'ImplicitGroups',
+               'GroupsAddToSelf',
+               'GroupsRemoveFromSelf',
+               'AddGroups',
+               'RemoveGroups',
+               'AvailableRights',
+               'ContentHandlers',
+               'RateLimits',
+               'ParserTestFiles',
+               'RecentChangesFlags',
+               'ExtensionFunctions',
+               'ExtensionEntryPointListFiles',
+               'SpecialPages',
+               'SpecialPageGroups',
+               'JobClasses',
+               'LogTypes',
+               'LogRestrictions',
+               'FilterLogTypes',
+               'LogNames',
+               'LogHeaders',
+               'LogActions',
+               'LogActionsHandlers',
+               'Actions',
+               'APIModules',
+               'APIFormatModules',
+               'APIMetaModules',
+               'APIPropModules',
+               'APIListModules',
+       );
+
+       /**
+        * Keys that are part of the extension credits
+        *
+        * @var array
+        */
+       protected static $creditsAttributes = array(
+               'name',
+               'author',
+               'version',
+               'url',
+               'description',
+               'descriptionmsg',
+               'license-name',
+       );
+
+       /**
+        * Stuff that is going to be set to $GLOBALS
+        *
+        * Some keys are pre-set to arrays so we can += to them
+        *
+        * @var array
+        */
+       protected $globals = array(
+               'wgExtensionMessagesFiles' => array(),
+               'wgMessagesDirs' => array(),
+       );
+
+       /**
+        * Things that should be define()'d
+        *
+        * @var array
+        */
+       protected $defines = array();
+
+       /**
+        * Things to be called once registration of these extensions are done
+        *
+        * @var callable[]
+        */
+       protected $callbacks = array();
+
+       /**
+        * @var array
+        */
+       protected $credits = array();
+
+       /**
+        * Any thing else in the $info that hasn't
+        * already been processed
+        *
+        * @var array
+        */
+       protected $attributes = array();
+
+       /**
+        * List of keys that have already been processed
+        *
+        * @var array
+        */
+       protected $processed = array();
+
+       /**
+        * @param string $path
+        * @param array $info
+        * @return array
+        */
+       public function extractInfo( $path, array $info ) {
+               $this->extractConfig( $info );
+               $this->extractHooks( $info );
+               $dir = dirname( $path );
+               $this->extractMessageSettings( $dir, $info );
+               $this->extractNamespaces( $info );
+               $this->extractResourceLoaderModules( $dir, $info );
+               if ( isset( $info['callback'] ) ) {
+                       $this->callbacks[] = $info['callback'];
+                       $this->processed[] = 'callback';
+               }
+
+               $this->extractCredits( $path, $info );
+               foreach ( $info as $key => $val ) {
+                       if ( in_array( $key, self::$globalSettings ) ) {
+                               $this->storeToArray( "wg$key", $val, $this->globals );
+                       } elseif ( !in_array( $key, $this->processed ) ) {
+                               $this->storeToArray( $key, $val, $this->attributes );
+                       }
+               }
+
+       }
+
+       public function getExtractedInfo() {
+               return array(
+                       'globals' => $this->globals,
+                       'defines' => $this->defines,
+                       'callbacks' => $this->callbacks,
+                       'credits' => $this->credits,
+                       'attributes' => $this->attributes,
+               );
+       }
+
+       protected function extractHooks( array $info ) {
+               if ( isset( $info['Hooks'] ) ) {
+                       foreach ( $info['Hooks'] as $name => $callable ) {
+                               $this->globals['wgHooks'][$name][] = $callable;
+                       }
+                       $this->processed[] = 'Hooks';
+               }
+       }
+
+       /**
+        * Register namespaces with the appropriate global settings
+        *
+        * @param array $info
+        */
+       protected function extractNamespaces( array $info ) {
+               if ( isset( $info['namespaces'] ) ) {
+                       foreach ( $info['namespaces'] as $ns ) {
+                               $id = $ns['id'];
+                               $this->defines[$ns['constant']] = $id;
+                               $this->globals['wgExtraNamespaces'][$id] = $ns['name'];
+                               if ( isset( $ns['gender'] ) ) {
+                                       $this->globals['wgExtraGenderNamespaces'][$id] = $ns['gender'];
+                               }
+                               if ( isset( $ns['subpages'] ) && $ns['subpages'] ) {
+                                       $this->globals['wgNamespacesWithSubpages'][$id] = true;
+                               }
+                               if ( isset( $ns['content'] ) && $ns['content'] ) {
+                                       $this->globals['wgContentNamespaces'][] = $id;
+                               }
+                               if ( isset( $ns['defaultcontentmodel'] ) ) {
+                                       $this->globals['wgNamespaceContentModels'][$id] = $ns['defaultcontentmodel'];
+                               }
+                       }
+                       $this->processed[] = 'namespaces';
+               }
+       }
+
+       protected function extractResourceLoaderModules( $dir, array $info ) {
+               if ( isset( $info['ResourceModules'] ) ) {
+                       foreach ( $info['ResourceModules'] as $name => $data ) {
+                               if ( isset( $data['localBasePath'] ) ) {
+                                       $data['localBasePath'] = "$dir/{$data['localBasePath']}";
+                               }
+                               $this->globals['wgResourceModules'][$name] = $data;
+                       }
+               }
+       }
+
+       /**
+        * Set message-related settings, which need to be expanded to use
+        * absolute paths
+        *
+        * @param string $dir
+        * @param array $info
+        */
+       protected function extractMessageSettings( $dir, array $info ) {
+               foreach ( array( 'ExtensionMessagesFiles', 'MessagesDirs' ) as $key ) {
+                       if ( isset( $info[$key] ) ) {
+                               $this->globals["wg$key"] += array_map( function( $file ) use ( $dir ) {
+                                       return "$dir/$file";
+                               }, $info[$key] );
+                               $this->processed[] = $key;
+                       }
+               }
+       }
+
+       protected function extractCredits( $path, array $info ) {
+               $credits = array(
+                       'path' => $path,
+                       'type' => isset( $info['type'] ) ? $info['type'] : 'other',
+               );
+               $this->processed[] = 'type';
+               foreach ( self::$creditsAttributes as $attr ) {
+                       if ( isset( $info[$attr] ) ) {
+                               $credits[$attr] = $info[$attr];
+                               $this->processed[] = $attr;
+                       }
+               }
+
+               $this->credits[$credits['name']] = $credits;
+       }
+
+       /**
+        * Set configuration settings
+        * @todo In the future, this should be done via Config interfaces
+        *
+        * @param array $info
+        */
+       protected function extractConfig( array $info ) {
+               if ( isset( $info['config'] ) ) {
+                       foreach ( $info['config'] as $key => $val ) {
+                               $this->globals["wg$key"] = $val;
+                       }
+                       $this->processed[] = 'config';
+               }
+       }
+
+       /**
+        * @param string $name
+        * @param mixed $value
+        * @param array &$array
+        */
+       protected function storeToArray( $name, $value, &$array ) {
+               if ( isset( $array[$name] ) ) {
+                       $array[$name] = array_merge_recursive( $array[$name], $value );
+               } else {
+                       $array[$name] = $value;
+               }
+       }
+}
diff --git a/includes/registration/ExtensionRegistry.php b/includes/registration/ExtensionRegistry.php
new file mode 100644 (file)
index 0000000..44855d8
--- /dev/null
@@ -0,0 +1,260 @@
+<?php
+
+/**
+ * ExtensionRegistry class
+ *
+ * The Registry loads JSON files, and uses a Processor
+ * to extract information from them. It also registers
+ * classes with the autoloader.
+ *
+ * @since 1.25
+ */
+class ExtensionRegistry {
+
+       /**
+        * @var BagOStuff
+        */
+       protected $cache;
+
+       /**
+        * Array of loaded things, keyed by name, values are credits information
+        *
+        * @var array
+        */
+       private $loaded = array();
+
+       /**
+        * List of paths that should be loaded
+        *
+        * @var array
+        */
+       protected $queued = array();
+
+       /**
+        * Items in the JSON file that aren't being
+        * set as globals
+        *
+        * @var array
+        */
+       protected $attributes = array();
+
+       /**
+        * Processors, 'default' should be set by subclasses in the constructor
+        *
+        * @var Processor[]
+        */
+       protected $processors = array();
+
+       /**
+        * @var ExtensionRegistry
+        */
+       private static $instance;
+
+       /**
+        * @return ExtensionRegistry
+        */
+       public static function getInstance() {
+               if ( self::$instance === null ) {
+                       self::$instance = new self();
+               }
+
+               return self::$instance;
+       }
+
+       public function __construct() {
+               $this->cache = ObjectCache::newAccelerator( array(), CACHE_NONE );
+       }
+
+       /**
+        * @param string $path Absolute path to the JSON file
+        */
+       public function queue( $path ) {
+               global $wgExtensionInfoMTime;
+               if ( $wgExtensionInfoMTime !== false ) {
+                       $mtime = $wgExtensionInfoMTime;
+               } else {
+                       $mtime = filemtime( $path );
+               }
+               $this->queued[$path] = $mtime;
+       }
+
+       public function loadFromQueue() {
+               if ( !$this->queued ) {
+                       return;
+               }
+
+               $this->queued = array_unique( $this->queued );
+
+               // See if this queue is in APC
+               $key = wfMemcKey( 'registration', md5( json_encode( $this->queued ) ) );
+               $data = $this->cache->get( $key );
+               if ( $data ) {
+                       $this->exportExtractedData( $data );
+               } else {
+                       $data = array( 'globals' => array( 'wgAutoloadClasses' => array() ) );
+                       $autoloadClasses = array();
+                       foreach ( $this->queued as $path => $mtime ) {
+                               $json = file_get_contents( $path );
+                               $info = json_decode( $json, /* $assoc = */ true );
+                               $autoload = $this->processAutoLoader( dirname( $path ), $info );
+                               // Set up the autoloader now so custom processors will work
+                               $GLOBALS['wgAutoloadClasses'] += $autoload;
+                               $autoloadClasses += $autoload;
+                               if ( isset( $info['processor'] ) ) {
+                                       $processor = $this->getProcessor( $info['processor'] );
+                               } else {
+                                       $processor = $this->getProcessor( 'default' );
+                               }
+                               $processor->extractInfo( $path, $info );
+                       }
+                       foreach ( $this->processors as $processor ) {
+                               $data = array_merge_recursive( $data, $processor->getExtractedInfo() );
+                       }
+                       foreach ( $data['credits'] as $credit ) {
+                               $data['globals']['wgExtensionCredits'][$credit['type']][] = $credit;
+                       }
+                       $this->processors = array(); // Reset
+                       $this->exportExtractedData( $data );
+                       // Do this late since we don't want to extract it since we already
+                       // did that, but it should be cached
+                       $data['globals']['wgAutoloadClasses'] += $autoloadClasses;
+                       $this->cache->set( $key, $data );
+               }
+               $this->queued = array();
+       }
+
+       protected function getProcessor( $type ) {
+               if ( !isset( $this->processors[$type] ) ) {
+                       $processor = $type === 'default' ? new ExtensionProcessor() : new $type();
+                       if ( !$processor instanceof Processor ) {
+                               throw new Exception( "$type is not a Processor" );
+                       }
+                       $this->processors[$type] = $processor;
+               }
+
+               return $this->processors[$type];
+       }
+
+       protected function exportExtractedData( array $info ) {
+               foreach ( $info['globals'] as $key => $val ) {
+                       if ( !isset( $GLOBALS[$key] ) || !$GLOBALS[$key] ) {
+                               $GLOBALS[$key] = $val;
+                       } elseif ( is_array( $GLOBALS[$key] ) && is_array( $val ) ) {
+                               $GLOBALS[$key] = array_merge_recursive( $GLOBALS[$key], $val );
+                       } // else case is a config setting where it has already been overriden, so don't set it
+               }
+               foreach ( $info['defines'] as $name => $val ) {
+                       define( $name, $val );
+               }
+               foreach ( $info['callbacks'] as $cb ) {
+                       call_user_func( $cb );
+               }
+
+               $this->loaded += $info['credits'];
+
+               if ( $info['attributes'] ) {
+                       if ( !$this->attributes ) {
+                               $this->attributes = $info['attributes'];
+                       } else {
+                               $this->attributes = array_merge_recursive( $this->attributes, $info['attributes'] );
+                       }
+               }
+       }
+
+       /**
+        * Loads and processes the given JSON file without delay
+        *
+        * If some extensions are already queued, this will load
+        * those as well.
+        *
+        * @param string $path Absolute path to the JSON file
+        */
+       public function load( $path ) {
+               $this->loadFromQueue(); // First clear the queue
+               $this->queue( $path );
+               $this->loadFromQueue();
+       }
+
+       /**
+        * Whether a thing has been loaded
+        * @param string $name
+        * @return bool
+        */
+       public function isLoaded( $name ) {
+               return isset( $this->loaded[$name] );
+       }
+
+       /**
+        * @param string $name
+        * @return array
+        */
+       public function getAttribute( $name ) {
+               if ( isset( $this->attributes[$name] ) ) {
+                       return $this->attributes[$name];
+               } else {
+                       return array();
+               }
+       }
+
+       /**
+        * Get information about all things
+        *
+        * @return array
+        */
+       public function getAllThings() {
+               return $this->loaded;
+       }
+
+       /**
+        * Mark a thing as loaded
+        *
+        * @param string $name
+        * @param array $credits
+        */
+       protected function markLoaded( $name, array $credits ) {
+               $this->loaded[$name] = $credits;
+       }
+
+       /**
+        * Register classes with the autoloader
+        *
+        * @param string $dir
+        * @param array $info
+        * @return array
+        */
+       protected function processAutoLoader( $dir, array $info ) {
+               if ( isset( $info['AutoloadClasses'] ) ) {
+                       // Make paths absolute, relative to the JSON file
+                       return array_map( function( $file ) use ( $dir ) {
+                               return "$dir/$file";
+                       }, $info['AutoloadClasses'] );
+               } else {
+                       return array();
+               }
+       }
+
+       /**
+        * @param string $filename absolute path to the JSON file
+        * @param int $mtime modified time of the file
+        * @return array
+        */
+       protected function loadInfoFromFile( $filename, $mtime ) {
+               $key = wfMemcKey( 'registry', md5( $filename ) );
+               $cached = $this->cache->get( $key );
+               if ( isset( $cached['mtime'] ) && $cached['mtime'] === $mtime ) {
+                       return $cached['info'];
+               }
+
+               $contents = file_get_contents( $filename );
+               $json = json_decode( $contents, /* $assoc = */ true );
+               if ( is_array( $json ) ) {
+                       $this->cache->set( $key, array( 'mtime' => $mtime, 'info' => $json ) );
+               } else {
+                       // Don't throw an error here, but don't cache it either.
+                       // @todo log somewhere?
+                       $json = array();
+               }
+
+               return $json;
+       }
+}
diff --git a/includes/registration/Processor.php b/includes/registration/Processor.php
new file mode 100644 (file)
index 0000000..e930fd3
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+
+/**
+ * Processors read associated arrays and register
+ * whatever is required
+ *
+ * @since 1.25
+ */
+interface Processor {
+
+       /**
+        * Main entry point, processes the information
+        * provided.
+        * Callers should call "callback" after calling
+        * this function.
+        *
+        * @param string $path Absolute path of JSON file
+        * @param array $info
+        * @return array "credits" information to store
+        */
+       public function extractInfo( $path, array $info );
+
+       /**
+        * @return array With 'globals', 'defines', 'callbacks', 'credits' keys.
+        */
+       public function getExtractedInfo();
+}
index 933397c..15bb13f 100644 (file)
@@ -165,12 +165,10 @@ class ResourceLoader {
         * @return string Filtered data, or a comment containing an error message
         */
        public function filter( $filter, $data, $cacheReport = true ) {
-               wfProfileIn( __METHOD__ );
 
                // For empty/whitespace-only data or for unknown filters, don't perform
                // any caching or processing
                if ( trim( $data ) === '' || !in_array( $filter, array( 'minify-js', 'minify-css' ) ) ) {
-                       wfProfileOut( __METHOD__ );
                        return $data;
                }
 
@@ -181,7 +179,6 @@ class ResourceLoader {
                $cacheEntry = $cache->get( $key );
                if ( is_string( $cacheEntry ) ) {
                        wfIncrStats( "rl-$filter-cache-hits" );
-                       wfProfileOut( __METHOD__ );
                        return $cacheEntry;
                }
 
@@ -215,8 +212,6 @@ class ResourceLoader {
                        $this->errors[] = self::formatExceptionNoComment( $e );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $result;
        }
 
@@ -229,8 +224,6 @@ class ResourceLoader {
        public function __construct( Config $config = null ) {
                global $IP;
 
-               wfProfileIn( __METHOD__ );
-
                if ( $config === null ) {
                        wfDebug( __METHOD__ . ' was called without providing a Config instance' );
                        $config = ConfigFactory::getDefaultInstance()->makeConfig( 'main' );
@@ -254,7 +247,6 @@ class ResourceLoader {
                        $this->registerTestModules();
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -278,14 +270,12 @@ class ResourceLoader {
         *   not registered
         */
        public function register( $name, $info = null ) {
-               wfProfileIn( __METHOD__ );
 
                // Allow multiple modules to be registered in one call
                $registrations = is_array( $name ) ? $name : array( $name => $info );
                foreach ( $registrations as $name => $info ) {
                        // Disallow duplicate registrations
                        if ( isset( $this->moduleInfos[$name] ) ) {
-                               wfProfileOut( __METHOD__ );
                                // A module has already been registered by this name
                                throw new MWException(
                                        'ResourceLoader duplicate registration error. ' .
@@ -295,7 +285,6 @@ class ResourceLoader {
 
                        // Check $name for validity
                        if ( !self::isValidModuleName( $name ) ) {
-                               wfProfileOut( __METHOD__ );
                                throw new MWException( "ResourceLoader module name '$name' is invalid, "
                                        . "see ResourceLoader::isValidModuleName()" );
                        }
@@ -309,7 +298,6 @@ class ResourceLoader {
                                // New calling convention
                                $this->moduleInfos[$name] = $info;
                        } else {
-                               wfProfileOut( __METHOD__ );
                                throw new MWException(
                                        'ResourceLoader module info type error for module \'' . $name .
                                        '\': expected ResourceLoaderModule or array (got: ' . gettype( $info ) . ')'
@@ -357,7 +345,6 @@ class ResourceLoader {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -371,8 +358,6 @@ class ResourceLoader {
                                . 'Edit your <code>LocalSettings.php</code> to enable it.' );
                }
 
-               wfProfileIn( __METHOD__ );
-
                // Get core test suites
                $testModules = array();
                $testModules['qunit'] = array();
@@ -400,7 +385,6 @@ class ResourceLoader {
                        $this->testModuleNames[$id] = array_keys( $testModules[$id] );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -579,8 +563,6 @@ class ResourceLoader {
                // See http://bugs.php.net/bug.php?id=36514
                ob_start();
 
-               wfProfileIn( __METHOD__ );
-
                // Find out which modules are missing and instantiate the others
                $modules = array();
                $missing = array();
@@ -609,8 +591,6 @@ class ResourceLoader {
                        $this->errors[] = self::formatExceptionNoComment( $e );
                }
 
-               wfProfileIn( __METHOD__ . '-getModifiedTime' );
-
                // To send Last-Modified and support If-Modified-Since, we need to detect
                // the last modified time
                $mtime = wfTimestamp( TS_UNIX, $this->config->get( 'CacheEpoch' ) );
@@ -628,11 +608,8 @@ class ResourceLoader {
                        }
                }
 
-               wfProfileOut( __METHOD__ . '-getModifiedTime' );
-
                // If there's an If-Modified-Since header, respond with a 304 appropriately
                if ( $this->tryRespondLastModified( $context, $mtime ) ) {
-                       wfProfileOut( __METHOD__ );
                        return; // output handled (buffers cleared)
                }
 
@@ -682,7 +659,6 @@ class ResourceLoader {
                $this->errors = array();
                echo $response;
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -880,8 +856,6 @@ class ResourceLoader {
    no modules were requested. Max made me put this here. */";
                }
 
-               wfProfileIn( __METHOD__ );
-
                $image = $context->getImageObj();
                if ( $image ) {
                        $data = $image->getImageData( $context );
@@ -889,7 +863,6 @@ class ResourceLoader {
                                $data = '';
                                $this->errors[] = 'Image generation failed';
                        }
-                       wfProfileOut( __METHOD__ );
                        return $data;
                }
 
@@ -920,7 +893,6 @@ class ResourceLoader {
                         * @var $module ResourceLoaderModule
                         */
 
-                       wfProfileIn( __METHOD__ . '-' . $name );
                        try {
                                $scripts = '';
                                if ( $context->shouldIncludeScripts() ) {
@@ -1034,7 +1006,6 @@ class ResourceLoader {
                                unset( $modules[$name] );
                        }
                        $isRaw |= $module->isRaw();
-                       wfProfileOut( __METHOD__ . '-' . $name );
                }
 
                // Update module states
@@ -1066,7 +1037,6 @@ class ResourceLoader {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $out;
        }
 
index 3decabf..fbca08e 100644 (file)
@@ -527,7 +527,6 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                if ( isset( $this->modifiedTime[$context->getHash()] ) ) {
                        return $this->modifiedTime[$context->getHash()];
                }
-               wfProfileIn( __METHOD__ );
 
                $files = array();
 
@@ -567,13 +566,10 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                // giving max() an empty array
                if ( count( $files ) === 0 ) {
                        $this->modifiedTime[$context->getHash()] = 1;
-                       wfProfileOut( __METHOD__ );
                        return $this->modifiedTime[$context->getHash()];
                }
 
-               wfProfileIn( __METHOD__ . '-filemtime' );
                $filesMtime = max( array_map( array( __CLASS__, 'safeFilemtime' ), $files ) );
-               wfProfileOut( __METHOD__ . '-filemtime' );
 
                $this->modifiedTime[$context->getHash()] = max(
                        $filesMtime,
@@ -581,7 +577,6 @@ class ResourceLoaderFileModule extends ResourceLoaderModule {
                        $this->getDefinitionMtime( $context )
                );
 
-               wfProfileOut( __METHOD__ );
                return $this->modifiedTime[$context->getHash()];
        }
 
index 9246df7..67806ff 100644 (file)
@@ -158,10 +158,14 @@ class ResourceLoaderImageModule extends ResourceLoaderModule {
                                                isset( $options['variants'] ) ? $options['variants'] : array(),
                                                $this->getGlobalVariants( $type )
                                        );
-                                       $variantConfig = array_intersect_key(
-                                               $this->variants[$type],
-                                               array_fill_keys( $allowedVariants, true )
-                                       );
+                                       if ( isset( $this->variants[$type] ) ) {
+                                               $variantConfig = array_intersect_key(
+                                                       $this->variants[$type],
+                                                       array_fill_keys( $allowedVariants, true )
+                                               );
+                                       } else {
+                                               $variantConfig = array();
+                                       }
 
                                        $image = new ResourceLoaderImage( $name, $this->getName(), $imageDesc, $this->localBasePath, $variantConfig );
                                        $this->imageObjects[ $image->getName() ] = $image;
@@ -182,9 +186,11 @@ class ResourceLoaderImageModule extends ResourceLoaderModule {
                if ( !isset( $this->globalVariants[$type] ) ) {
                        $this->globalVariants[$type] = array();
 
-                       foreach ( $this->variants[$type] as $name => $config ) {
-                               if ( isset( $config['global'] ) && $config['global'] ) {
-                                       $this->globalVariants[$type][] = $name;
+                       if ( isset( $this->variants[$type] ) ) {
+                               foreach ( $this->variants[$type] as $name => $config ) {
+                                       if ( isset( $config['global'] ) && $config['global'] ) {
+                                               $this->globalVariants[$type][] = $name;
+                                       }
                                }
                        }
                }
index 3f95ce6..4c2c2b2 100644 (file)
@@ -498,10 +498,8 @@ abstract class ResourceLoaderModule {
         * @return int UNIX timestamp
         */
        public function getDefinitionMtime( ResourceLoaderContext $context ) {
-               wfProfileIn( __METHOD__ );
                $summary = $this->getDefinitionSummary( $context );
                if ( $summary === null ) {
-                       wfProfileOut( __METHOD__ );
                        return 1;
                }
 
@@ -523,7 +521,6 @@ abstract class ResourceLoaderModule {
                $data = $cache->get( $key );
                if ( is_int( $data ) && $data > 0 ) {
                        // We've seen this hash before, re-use the timestamp of when we first saw it.
-                       wfProfileOut( __METHOD__ );
                        return $data;
                }
 
@@ -533,7 +530,6 @@ abstract class ResourceLoaderModule {
                $timestamp = time();
                $cache->set( $key, $timestamp );
 
-               wfProfileOut( __METHOD__ );
                return $timestamp;
        }
 
index fb206b9..48b3576 100644 (file)
@@ -187,7 +187,6 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         * @return string JavaScript code for registering all modules with the client loader
         */
        public function getModuleRegistrations( ResourceLoaderContext $context ) {
-               wfProfileIn( __METHOD__ );
 
                $resourceLoader = $context->getResourceLoader();
                $target = $context->getRequest()->getVal( 'target', 'desktop' );
@@ -278,7 +277,6 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                // Register modules
                $out .= ResourceLoader::makeLoaderRegisterScript( $registrations );
 
-               wfProfileOut( __METHOD__ );
                return $out;
        }
 
index cd6cf7d..5770276 100644 (file)
@@ -47,6 +47,7 @@ class SearchEngine {
 
        /** @var bool */
        protected $showSuggestion = true;
+       private $sort = 'relevance';
 
        /** @var array Feature values */
        protected $features = array();
@@ -309,6 +310,43 @@ class SearchEngine {
                $this->showSuggestion = $showSuggestion;
        }
 
+       /**
+        * Get the valid sort directions.  All search engines support 'relevance' but others
+        * might support more. The default in all implementations should be 'relevance.'
+        *
+        * @since 1.25
+        * @return array(string) the valid sort directions for setSort
+        */
+       public function getValidSorts() {
+               return array( 'relevance' );
+       }
+
+       /**
+        * Set the sort direction of the search results. Must be one returned by
+        * SearchEngine::getValidSorts()
+        *
+        * @since 1.25
+        * @throws InvalidArgumentException
+        * @param string $sort sort direction for query result
+        */
+       public function setSort( $sort ) {
+               if ( !in_array( $sort, $this->getValidSorts() ) ) {
+                       throw new InvalidArgumentException( "Invalid sort: $sort. " .
+                               "Must be one of: " . implode( ', ', $this->getValidSorts() ) );
+               }
+               $this->sort = $sort;
+       }
+
+       /**
+        * Get the sort direction of the search results
+        *
+        * @since 1.25
+        * @return string
+        */
+       public function getSort() {
+               return $this->sort;
+       }
+
        /**
         * Parse some common prefixes: all (search everything)
         * or namespace names
index c3c3a8f..255d005 100644 (file)
@@ -67,7 +67,6 @@ class SearchHighlighter {
                $spat .= '/';
                $textExt = array(); // text extracts
                $otherExt = array(); // other extracts
-               wfProfileIn( "$fname-split" );
                $start = 0;
                $textLen = strlen( $text );
                $count = 0; // sequence number to maintain ordering
@@ -132,8 +131,6 @@ class SearchHighlighter {
 
                $all = $textExt + $otherExt; // these have disjunct key sets
 
-               wfProfileOut( "$fname-split" );
-
                // prepare regexps
                foreach ( $terms as $index => $term ) {
                        // manually do upper/lowercase stuff for utf-8 since PHP won't do it
@@ -163,8 +160,6 @@ class SearchHighlighter {
                $pat1 = "/(" . $phrase . ")/ui";
                $pat2 = "/$patPre(" . $anyterm . ")$patPost/ui";
 
-               wfProfileIn( "$fname-extract" );
-
                $left = $contextlines;
 
                $snippets = array();
@@ -287,8 +282,6 @@ class SearchHighlighter {
                        }
                }
 
-               wfProfileOut( "$fname-extract" );
-
                return $extract;
        }
 
@@ -452,7 +445,6 @@ class SearchHighlighter {
         */
        function removeWiki( $text ) {
                $fname = __METHOD__;
-               wfProfileIn( $fname );
 
                // $text = preg_replace( "/'{2,5}/", "", $text );
                // $text = preg_replace( "/\[[a-z]+:\/\/[^ ]+ ([^]]+)\]/", "\\2", $text );
@@ -474,7 +466,6 @@ class SearchHighlighter {
                $text = preg_replace( "/('''|<\/?[iIuUbB]>)/", "", $text );
                $text = preg_replace( "/''/", "", $text );
 
-               wfProfileOut( $fname );
                return $text;
        }
 
@@ -523,7 +514,6 @@ class SearchHighlighter {
                $lineno = 0;
 
                $extract = "";
-               wfProfileIn( "$fname-extract" );
                foreach ( $lines as $line ) {
                        if ( 0 == $contextlines ) {
                                break;
@@ -551,7 +541,6 @@ class SearchHighlighter {
 
                        $extract .= "${line}\n";
                }
-               wfProfileOut( "$fname-extract" );
 
                return $extract;
        }
index 78eba2d..485088c 100644 (file)
@@ -382,8 +382,6 @@ class SearchMySQL extends SearchDatabase {
        function normalizeText( $string ) {
                global $wgContLang;
 
-               wfProfileIn( __METHOD__ );
-
                $out = parent::normalizeText( $string );
 
                // MySQL fulltext index doesn't grok utf-8, so we
@@ -416,8 +414,6 @@ class SearchMySQL extends SearchDatabase {
                        "$1u82e$2",
                        $out );
 
-               wfProfileOut( __METHOD__ );
-
                return $out;
        }
 
index c1a350d..8f25c76 100644 (file)
@@ -104,7 +104,6 @@ class SiteSQLStore implements SiteStore {
         * @return string The cache key.
         */
        protected function getCacheKey() {
-               wfProfileIn( __METHOD__ );
 
                if ( $this->cacheKey === null ) {
                        $type = 'SiteList#' . SiteList::getSerialVersionId();
@@ -117,7 +116,6 @@ class SiteSQLStore implements SiteStore {
                        $this->cacheKey = wfMemcKey( "$source/$type" );
                }
 
-               wfProfileOut( __METHOD__ );
                return $this->cacheKey;
        }
 
@@ -131,7 +129,6 @@ class SiteSQLStore implements SiteStore {
         * @return SiteList
         */
        public function getSites( $source = 'cache' ) {
-               wfProfileIn( __METHOD__ );
 
                if ( $source === 'cache' ) {
                        if ( $this->sites === null ) {
@@ -148,7 +145,6 @@ class SiteSQLStore implements SiteStore {
                        $this->loadSites();
                }
 
-               wfProfileOut( __METHOD__ );
                return $this->sites;
        }
 
@@ -162,7 +158,6 @@ class SiteSQLStore implements SiteStore {
         * @return Site
         */
        protected function siteFromRow( ORMRow $siteRow ) {
-               wfProfileIn( __METHOD__ );
 
                $site = Site::newForType( $siteRow->getField( 'type', Site::TYPE_UNKNOWN ) );
 
@@ -197,7 +192,6 @@ class SiteSQLStore implements SiteStore {
                        $site->setExtraConfig( $siteRow->getField( 'config' ) );
                }
 
-               wfProfileOut( __METHOD__ );
                return $site;
        }
 
@@ -240,7 +234,6 @@ class SiteSQLStore implements SiteStore {
         * @since 1.21
         */
        protected function loadSites() {
-               wfProfileIn( __METHOD__ );
 
                $this->sites = new SiteList();
 
@@ -270,7 +263,6 @@ class SiteSQLStore implements SiteStore {
 
                $this->cache->set( $this->getCacheKey(), $this->sites, $this->cacheTimeout );
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -284,11 +276,9 @@ class SiteSQLStore implements SiteStore {
         * @return Site|null
         */
        public function getSite( $globalId, $source = 'cache' ) {
-               wfProfileIn( __METHOD__ );
 
                $sites = $this->getSites( $source );
 
-               wfProfileOut( __METHOD__ );
                return $sites->hasSite( $globalId ) ? $sites->getSite( $globalId ) : null;
        }
 
@@ -315,10 +305,8 @@ class SiteSQLStore implements SiteStore {
         * @return bool Success indicator
         */
        public function saveSites( array $sites ) {
-               wfProfileIn( __METHOD__ );
 
                if ( empty( $sites ) ) {
-                       wfProfileOut( __METHOD__ );
                        return true;
                }
 
@@ -371,7 +359,6 @@ class SiteSQLStore implements SiteStore {
                // purge cache
                $this->reset();
 
-               wfProfileOut( __METHOD__ );
                return $success;
        }
 
@@ -382,12 +369,10 @@ class SiteSQLStore implements SiteStore {
         * @since 1.21
         */
        public function reset() {
-               wfProfileIn( __METHOD__ );
                // purge cache
                $this->cache->delete( $this->getCacheKey() );
                $this->sites = null;
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -398,7 +383,6 @@ class SiteSQLStore implements SiteStore {
         * @return bool Success
         */
        public function clear() {
-               wfProfileIn( __METHOD__ );
                $dbw = $this->sitesTable->getWriteDbConnection();
 
                $dbw->startAtomic( __METHOD__ );
@@ -408,7 +392,6 @@ class SiteSQLStore implements SiteStore {
 
                $this->reset();
 
-               wfProfileOut( __METHOD__ );
                return $ok;
        }
 
index 3cdfca0..eedd2a1 100644 (file)
@@ -55,7 +55,6 @@ abstract class BaseTemplate extends QuickTemplate {
         * @return array
         */
        function getToolbox() {
-               wfProfileIn( __METHOD__ );
 
                $toolbox = array();
                if ( isset( $this->data['nav_urls']['whatlinkshere'] )
@@ -113,7 +112,6 @@ abstract class BaseTemplate extends QuickTemplate {
                }
 
                Hooks::run( 'BaseTemplateToolbox', array( &$this, &$toolbox ) );
-               wfProfileOut( __METHOD__ );
                return $toolbox;
        }
 
index 8bd77cc..6e48d04 100644 (file)
@@ -33,7 +33,6 @@ class MediaWikiI18N {
        }
 
        function translate( $value ) {
-               wfProfileIn( __METHOD__ );
 
                // Hack for i18n:attributes in PHPTAL 1.0.0 dev version as of 2004-10-23
                $value = preg_replace( '/^string:/', '', $value );
@@ -48,7 +47,6 @@ class MediaWikiI18N {
                        wfRestoreWarnings();
                        $value = str_replace( $src, $varValue, $value );
                }
-               wfProfileOut( __METHOD__ );
                return $value;
        }
 }
index 3b08e74..999dda8 100644 (file)
@@ -168,11 +168,9 @@ abstract class Skin extends ContextSource {
         * @param OutputPage $out
         */
        function initPage( OutputPage $out ) {
-               wfProfileIn( __METHOD__ );
 
                $this->preloadExistence();
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -942,7 +940,6 @@ abstract class Skin extends ContextSource {
         * @return string HTML anchor
         */
        public function footerLink( $desc, $page ) {
-               $section = new ProfileSection( __METHOD__ );
                // if the link description has been set to "-" in the default language,
                if ( $this->msg( $desc )->inContentLanguage()->isDisabled() ) {
                        // then it is disabled, for all languages.
@@ -1224,7 +1221,6 @@ abstract class Skin extends ContextSource {
         */
        function buildSidebar() {
                global $wgMemc, $wgEnableSidebarCache, $wgSidebarCacheExpiry;
-               wfProfileIn( __METHOD__ );
 
                $key = wfMemcKey( 'sidebar', $this->getLanguage()->getCode() );
 
@@ -1233,7 +1229,6 @@ abstract class Skin extends ContextSource {
                        if ( $cachedsidebar ) {
                                Hooks::run( 'SidebarBeforeOutput', array( $this, &$cachedsidebar ) );
 
-                               wfProfileOut( __METHOD__ );
                                return $cachedsidebar;
                        }
                }
@@ -1248,7 +1243,6 @@ abstract class Skin extends ContextSource {
 
                Hooks::run( 'SidebarBeforeOutput', array( $this, &$bar ) );
 
-               wfProfileOut( __METHOD__ );
                return $bar;
        }
 
@@ -1474,8 +1468,6 @@ abstract class Skin extends ContextSource {
        private function getCachedNotice( $name ) {
                global $wgRenderHashAppend, $parserMemc, $wgContLang;
 
-               wfProfileIn( __METHOD__ );
-
                $needParse = false;
 
                if ( $name === 'default' ) {
@@ -1483,13 +1475,11 @@ abstract class Skin extends ContextSource {
                        global $wgSiteNotice;
                        $notice = $wgSiteNotice;
                        if ( empty( $notice ) ) {
-                               wfProfileOut( __METHOD__ );
                                return false;
                        }
                } else {
                        $msg = $this->msg( $name )->inContentLanguage();
                        if ( $msg->isDisabled() ) {
-                               wfProfileOut( __METHOD__ );
                                return false;
                        }
                        $notice = $msg->plain();
@@ -1516,7 +1506,6 @@ abstract class Skin extends ContextSource {
 
                $notice = Html::rawElement( 'div', array( 'id' => 'localNotice',
                        'lang' => $wgContLang->getHtmlCode(), 'dir' => $wgContLang->getDir() ), $notice );
-               wfProfileOut( __METHOD__ );
                return $notice;
        }
 
@@ -1526,7 +1515,6 @@ abstract class Skin extends ContextSource {
         * @return string HTML fragment
         */
        function getNamespaceNotice() {
-               wfProfileIn( __METHOD__ );
 
                $key = 'namespacenotice-' . $this->getTitle()->getNsText();
                $namespaceNotice = $this->getCachedNotice( $key );
@@ -1536,7 +1524,6 @@ abstract class Skin extends ContextSource {
                        $namespaceNotice = '';
                }
 
-               wfProfileOut( __METHOD__ );
                return $namespaceNotice;
        }
 
@@ -1546,7 +1533,6 @@ abstract class Skin extends ContextSource {
         * @return string HTML fragment
         */
        function getSiteNotice() {
-               wfProfileIn( __METHOD__ );
                $siteNotice = '';
 
                if ( Hooks::run( 'SiteNoticeBefore', array( &$siteNotice, $this ) ) ) {
@@ -1566,7 +1552,6 @@ abstract class Skin extends ContextSource {
                }
 
                Hooks::run( 'SiteNoticeAfter', array( &$siteNotice, $this ) );
-               wfProfileOut( __METHOD__ );
                return $siteNotice;
        }
 
index d393280..45a1a8b 100644 (file)
@@ -175,17 +175,13 @@ class SkinTemplate extends Skin {
        }
 
        protected function setupTemplateForOutput() {
-               wfProfileIn( __METHOD__ );
 
                $request = $this->getRequest();
                $user = $this->getUser();
                $title = $this->getTitle();
 
-               wfProfileIn( __METHOD__ . '-init' );
                $tpl = $this->setupTemplate( $this->template, 'skins' );
-               wfProfileOut( __METHOD__ . '-init' );
 
-               wfProfileIn( __METHOD__ . '-stuff' );
                $this->thispage = $title->getPrefixedDBkey();
                $this->titletxt = $title->getPrefixedText();
                $this->userpage = $user->getUserPage()->getPrefixedText();
@@ -208,10 +204,6 @@ class SkinTemplate extends Skin {
                        $this->userpageUrlDetails = self::makeKnownUrlDetails( $this->userpage );
                }
 
-               wfProfileOut( __METHOD__ . '-stuff' );
-
-               wfProfileOut( __METHOD__ );
-
                return $tpl;
        }
 
@@ -221,7 +213,6 @@ class SkinTemplate extends Skin {
         * @param OutputPage $out
         */
        function outputPage( OutputPage $out = null ) {
-               wfProfileIn( __METHOD__ );
                Profiler::instance()->setTemplated( true );
 
                $oldContext = null;
@@ -234,14 +225,10 @@ class SkinTemplate extends Skin {
 
                $out = $this->getOutput();
 
-               wfProfileIn( __METHOD__ . '-init' );
                $this->initPage( $out );
-               wfProfileOut( __METHOD__ . '-init' );
                $tpl = $this->prepareQuickTemplate( $out );
                // execute template
-               wfProfileIn( __METHOD__ . '-execute' );
                $res = $tpl->execute();
-               wfProfileOut( __METHOD__ . '-execute' );
 
                // result may be an error
                $this->printOrError( $res );
@@ -250,7 +237,6 @@ class SkinTemplate extends Skin {
                        $this->setContext( $oldContext );
                }
 
-               wfProfileOut( __METHOD__ );
        }
 
        /**
@@ -265,14 +251,11 @@ class SkinTemplate extends Skin {
                        $wgShowCreditsIfMax, $wgArticlePath,
                        $wgScriptPath, $wgServer;
 
-               wfProfileIn( __METHOD__ );
-
                $title = $this->getTitle();
                $request = $this->getRequest();
                $out = $this->getOutput();
                $tpl = $this->setupTemplateForOutput();
 
-               wfProfileIn( __METHOD__ . '-stuff2' );
                $tpl->set( 'title', $out->getPageTitle() );
                $tpl->set( 'pagetitle', $out->getHTMLTitle() );
                $tpl->set( 'displaytitle', $out->mPageLinkTitle );
@@ -367,9 +350,6 @@ class SkinTemplate extends Skin {
                        $tpl->set( 'userlangattributes', $attrs );
                }
 
-               wfProfileOut( __METHOD__ . '-stuff2' );
-
-               wfProfileIn( __METHOD__ . '-stuff3' );
                $tpl->set( 'newtalk', $this->getNewtalks() );
                $tpl->set( 'logo', $this->logoText() );
 
@@ -390,9 +370,7 @@ class SkinTemplate extends Skin {
                        }
                        $tpl->set( 'copyright', $this->getCopyright() );
                }
-               wfProfileOut( __METHOD__ . '-stuff3' );
 
-               wfProfileIn( __METHOD__ . '-stuff4' );
                $tpl->set( 'copyrightico', $this->getCopyrightIcon() );
                $tpl->set( 'poweredbyico', $this->getPoweredBy() );
                $tpl->set( 'disclaimer', $this->disclaimerLink() );
@@ -463,9 +441,7 @@ class SkinTemplate extends Skin {
                } else {
                        $tpl->set( 'language_urls', false );
                }
-               wfProfileOut( __METHOD__ . '-stuff4' );
 
-               wfProfileIn( __METHOD__ . '-stuff5' );
                # Personal toolbar
                $tpl->set( 'personal_urls', $this->buildPersonalUrls() );
                $content_navigation = $this->buildContentNavigationUrls();
@@ -505,9 +481,7 @@ class SkinTemplate extends Skin {
                // allow extensions adding stuff after the page content.
                // See Skin::afterContentHook() for further documentation.
                $tpl->set( 'dataAfterContent', $this->afterContentHook() );
-               wfProfileOut( __METHOD__ . '-stuff5' );
 
-               wfProfileOut( __METHOD__ );
                return $tpl;
        }
 
@@ -571,7 +545,6 @@ class SkinTemplate extends Skin {
                $title = $this->getTitle();
                $request = $this->getRequest();
                $pageurl = $title->getLocalURL();
-               wfProfileIn( __METHOD__ );
 
                /* set up the default links for the personal toolbar */
                $personal_urls = array();
@@ -704,7 +677,6 @@ class SkinTemplate extends Skin {
                }
 
                Hooks::run( 'PersonalUrls', array( &$personal_urls, &$title, $this ) );
-               wfProfileOut( __METHOD__ );
                return $personal_urls;
        }
 
@@ -822,8 +794,6 @@ class SkinTemplate extends Skin {
        protected function buildContentNavigationUrls() {
                global $wgDisableLangConversion;
 
-               wfProfileIn( __METHOD__ );
-
                // Display tabs for the relevant title rather than always the title itself
                $title = $this->getRelevantTitle();
                $onPage = $title->equals( $this->getTitle() );
@@ -909,8 +879,6 @@ class SkinTemplate extends Skin {
                                        );
                                }
 
-                               wfProfileIn( __METHOD__ . '-edit' );
-
                                // Checks if user can edit the current page if it exists or create it otherwise
                                if ( $title->quickUserCan( 'edit', $user )
                                        && ( $title->exists() || $title->quickUserCan( 'create', $user ) )
@@ -967,9 +935,7 @@ class SkinTemplate extends Skin {
                                                'primary' => true, // don't collapse this in vector
                                        );
                                }
-                               wfProfileOut( __METHOD__ . '-edit' );
 
-                               wfProfileIn( __METHOD__ . '-live' );
                                // Checks if the page exists
                                if ( $title->exists() ) {
                                        // Adds history view link
@@ -1030,8 +996,6 @@ class SkinTemplate extends Skin {
                                        );
                                }
 
-                               wfProfileOut( __METHOD__ . '-live' );
-
                                // Checks if the user is logged in
                                if ( $this->loggedin && $user->isAllowedAll( 'viewmywatchlist', 'editmywatchlist' ) ) {
                                        /**
@@ -1138,8 +1102,6 @@ class SkinTemplate extends Skin {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $content_navigation;
        }
 
@@ -1150,8 +1112,6 @@ class SkinTemplate extends Skin {
         */
        private function buildContentActionUrls( $content_navigation ) {
 
-               wfProfileIn( __METHOD__ );
-
                // content_actions has been replaced with content_navigation for backwards
                // compatibility and also for skins that just want simple tabs content_actions
                // is now built by flattening the content_navigation arrays into one
@@ -1183,8 +1143,6 @@ class SkinTemplate extends Skin {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $content_actions;
        }
 
@@ -1195,8 +1153,6 @@ class SkinTemplate extends Skin {
        protected function buildNavUrls() {
                global $wgUploadNavigationUrl;
 
-               wfProfileIn( __METHOD__ );
-
                $out = $this->getOutput();
                $request = $this->getRequest();
 
@@ -1301,7 +1257,6 @@ class SkinTemplate extends Skin {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $nav_urls;
        }
 
index e31ebf6..175b0cb 100644 (file)
@@ -220,7 +220,6 @@ class SpecialPageFactory {
                global $wgPageLanguageUseDB;
 
                if ( !is_array( self::$list ) ) {
-                       wfProfileIn( __METHOD__ );
 
                        self::$list = self::$coreList;
 
@@ -254,7 +253,6 @@ class SpecialPageFactory {
                        // This hook can be used to remove undesired built-in special pages
                        Hooks::run( 'SpecialPage_initList', array( &self::$list ) );
 
-                       wfProfileOut( __METHOD__ );
                }
 
                return self::$list;
@@ -527,7 +525,6 @@ class SpecialPageFactory {
         * @return bool
         */
        public static function executePath( Title &$title, IContextSource &$context, $including = false ) {
-               wfProfileIn( __METHOD__ );
 
                // @todo FIXME: Redirects broken due to this call
                $bits = explode( '/', $title->getDBkey(), 2 );
@@ -549,7 +546,6 @@ class SpecialPageFactory {
                        }
 
                        $context->getOutput()->showErrorPage( 'nosuchspecialpage', 'nospecialpagetext' );
-                       wfProfileOut( __METHOD__ );
 
                        return false;
                }
@@ -569,14 +565,12 @@ class SpecialPageFactory {
                                $title = $page->getPageTitle( $par );
                                $url = $title->getFullURL( $query );
                                $context->getOutput()->redirect( $url );
-                               wfProfileOut( __METHOD__ );
 
                                return $title;
                        } else {
                                $context->setTitle( $page->getPageTitle( $par ) );
                        }
                } elseif ( !$page->isIncludable() ) {
-                       wfProfileOut( __METHOD__ );
 
                        return false;
                }
@@ -584,11 +578,7 @@ class SpecialPageFactory {
                $page->including( $including );
 
                // Execute special page
-               $profName = 'Special:' . $page->getName();
-               wfProfileIn( $profName );
                $page->run( $par );
-               wfProfileOut( $profName );
-               wfProfileOut( __METHOD__ );
 
                return true;
        }
index fe06375..0caf6b4 100644 (file)
@@ -115,15 +115,23 @@ class ActiveUsersPager extends UsersPager {
                        ) . ')';
                }
 
+               if ( $dbr->implicitGroupby() ) {
+                       $options = array( 'GROUP BY' => array( 'qcc_title' ) );
+               } else {
+                       $options = array( 'GROUP BY' => array( 'user_name', 'user_id', 'qcc_title' ) );
+               }
+
                return array(
                        'tables' => array( 'querycachetwo', 'user', 'recentchanges' ),
                        'fields' => array( 'user_name', 'user_id', 'recentedits' => 'COUNT(*)', 'qcc_title' ),
-                       'options' => array( 'GROUP BY' => array( 'qcc_title' ) ),
+                       'options' => $options,
                        'conds' => $conds
                );
        }
 
        function doBatchLookups() {
+               parent::doBatchLookups();
+
                $uids = array();
                foreach ( $this->mResult as $row ) {
                        $uids[] = $row->user_id;
@@ -172,7 +180,8 @@ class ActiveUsersPager extends UsersPager {
                // Note: This is a different loop than for user rights,
                // because we're reusing it to build the group links
                // at the same time
-               foreach ( $user->getGroups() as $group ) {
+               $groups_list = self::getGroups( intval( $row->user_id ), $this->userGroupCache );
+               foreach ( $groups_list as $group ) {
                        if ( in_array( $group, $this->hideGroups ) ) {
                                return '';
                        }
index 96be4d0..7cf94cc 100644 (file)
@@ -223,7 +223,6 @@ class AllMessagesTablePager extends TablePager {
        }
 
        function getAllMessages( $descending ) {
-               wfProfileIn( __METHOD__ );
                $messageNames = Language::getLocalisationCache()->getSubitemList( 'en', 'messages' );
                if ( $descending ) {
                        rsort( $messageNames );
@@ -234,8 +233,6 @@ class AllMessagesTablePager extends TablePager {
                // Normalise message names so they look like page titles
                $messageNames = array_map( array( $this->lang, 'ucfirst' ), $messageNames );
 
-               wfProfileOut( __METHOD__ );
-
                return $messageNames;
        }
 
@@ -252,7 +249,6 @@ class AllMessagesTablePager extends TablePager {
         */
        public static function getCustomisedStatuses( $messageNames, $langcode = 'en', $foreign = false ) {
                // FIXME: This function should be moved to Language:: or something.
-               wfProfileIn( __METHOD__ . '-db' );
 
                $dbr = wfGetDB( DB_SLAVE );
                $res = $dbr->select( 'page',
@@ -288,8 +284,6 @@ class AllMessagesTablePager extends TablePager {
                        }
                }
 
-               wfProfileOut( __METHOD__ . '-db' );
-
                return array( 'pages' => $pageFlags, 'talks' => $talkFlags );
        }
 
index 23b739a..4583430 100644 (file)
@@ -427,7 +427,6 @@ class BlockListPager extends TablePager {
         * @param ResultWrapper $result
         */
        function preprocessResults( $result ) {
-               wfProfileIn( __METHOD__ );
                # Do a link batch query
                $lb = new LinkBatch;
                $lb->setCaller( __METHOD__ );
@@ -452,6 +451,5 @@ class BlockListPager extends TablePager {
                }
 
                $lb->execute();
-               wfProfileOut( __METHOD__ );
        }
 }
index 5030c1c..c2cd812 100644 (file)
@@ -954,7 +954,6 @@ class ContribsPager extends ReverseChronologicalPager {
         * @return string
         */
        function formatRow( $row ) {
-               wfProfileIn( __METHOD__ );
 
                $ret = '';
                $classes = array();
@@ -970,7 +969,7 @@ class ContribsPager extends ReverseChronologicalPager {
                try {
                        $rev = new Revision( $row );
                        $validRevision = (bool)$rev->getId();
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        $validRevision = false;
                }
                wfRestoreWarnings();
@@ -1118,8 +1117,6 @@ class ContribsPager extends ReverseChronologicalPager {
                        $ret = Html::rawElement( 'li', array( 'class' => $classes ), $ret ) . "\n";
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $ret;
        }
 
index 7e5d13c..680aa35 100644 (file)
@@ -151,7 +151,6 @@ class DeletedContribsPager extends IndexPager {
         * @return string
         */
        function formatRow( $row ) {
-               wfProfileIn( __METHOD__ );
 
                $page = Title::makeTitle( $row->ar_namespace, $row->ar_title );
 
@@ -258,8 +257,6 @@ class DeletedContribsPager extends IndexPager {
 
                $ret = Html::rawElement( 'li', array(), $ret ) . "\n";
 
-               wfProfileOut( __METHOD__ );
-
                return $ret;
        }
 
index 4480ac3..aa9b0f4 100644 (file)
@@ -194,7 +194,7 @@ class SpecialImport extends SpecialPage {
                        $reporter->open();
                        try {
                                $importer->doImport();
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                $exception = $e;
                        }
                        $result = $reporter->close();
@@ -521,13 +521,14 @@ class ImportReporter extends ContextSource {
 
        /**
         * @param Title $title
-        * @param Title $origTitle
+        * @param ForeignTitle $foreignTitle
         * @param int $revisionCount
         * @param int $successCount
         * @param array $pageInfo
         * @return void
         */
-       function reportPage( $title, $origTitle, $revisionCount, $successCount, $pageInfo ) {
+       function reportPage( $title, $foreignTitle, $revisionCount,
+                       $successCount, $pageInfo ) {
                $args = func_get_args();
                call_user_func_array( $this->mOriginalPageOutCallback, $args );
 
@@ -556,7 +557,7 @@ class ImportReporter extends ContextSource {
                                $log->addEntry( 'upload', $title, $detail, array(), $this->getUser() );
                        } else {
                                $interwiki = '[[:' . $this->mInterwiki . ':' .
-                                       $origTitle->getPrefixedText() . ']]';
+                                       $foreignTitle->getFullText() . ']]';
                                $detail = $this->msg( 'import-logentry-interwiki-detail' )->numParams(
                                        $successCount )->params( $interwiki )->inContentLanguage()->text();
                                if ( $this->reason ) {
index 3dc4410..fa719eb 100644 (file)
@@ -160,7 +160,6 @@ class SpecialJavaScriptTest extends SpecialPage {
                $baseHtml = <<<HTML
 <div class="mw-content-ltr">
 <div id="qunit"></div>
-<div id="qunit-fixture"></div>
 </div>
 HTML;
 
@@ -254,7 +253,6 @@ HTML;
 <title>QUnit</title>
 $head
 <div id="qunit"></div>
-<div id="qunit-fixture"></div>
 HTML;
                $html .= "\n" . Html::linkedScript( $url );
 
index 0b40d2f..56c4eb5 100644 (file)
@@ -37,7 +37,7 @@ class UsersPager extends AlphabeticPager {
        /**
         * @var array A array with user ids as key and a array of groups as value
         */
-       private $userGroupCache;
+       protected $userGroupCache;
 
        /**
         * @param IContextSource $context
@@ -246,7 +246,7 @@ class UsersPager extends AlphabeticPager {
                $this->userGroupCache = $cache;
 
                // Add page of groups to link batch
-               foreach( $groups as $group => $unused ) {
+               foreach ( $groups as $group => $unused ) {
                        $groupPage = User::getGroupPage( $group );
                        if ( $groupPage ) {
                                $batch->addObj( $groupPage );
@@ -386,7 +386,7 @@ class UsersPager extends AlphabeticPager {
        protected static function buildGroupLink( $group, $username ) {
                return User::makeGroupLinkHtml(
                        $group,
-                       htmlspecialchars( User::getGroupMember( $group, $username ) )
+                       User::getGroupMember( $group, $username )
                );
        }
 }
index 07a18b0..7e74cd5 100644 (file)
@@ -521,7 +521,6 @@ class MergeHistoryPager extends ReverseChronologicalPager {
        }
 
        function getStartBody() {
-               wfProfileIn( __METHOD__ );
                # Do a link batch query
                $this->mResult->seek( 0 );
                $batch = new LinkBatch();
@@ -544,8 +543,6 @@ class MergeHistoryPager extends ReverseChronologicalPager {
                $batch->execute();
                $this->mResult->seek( 0 );
 
-               wfProfileOut( __METHOD__ );
-
                return '';
        }
 
index bc16925..94e77e3 100644 (file)
@@ -141,7 +141,7 @@ class NewFilesPager extends ReverseChronologicalPager {
                        $mode = $this->getRequest()->getVal( 'gallerymode', null );
                        try {
                                $this->gallery = ImageGalleryBase::factory( $mode, $this->getContext() );
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                // User specified something invalid, fallback to default.
                                $this->gallery = ImageGalleryBase::factory( false, $this->getContext() );
                        }
index a40da87..d25c2c8 100644 (file)
@@ -72,7 +72,6 @@ class SpecialProtectedtitles extends SpecialPage {
         * @return string
         */
        function formatRow( $row ) {
-               wfProfileIn( __METHOD__ );
 
                static $infinity = null;
 
@@ -82,7 +81,6 @@ class SpecialProtectedtitles extends SpecialPage {
 
                $title = Title::makeTitleSafe( $row->pt_namespace, $row->pt_title );
                if ( !$title ) {
-                       wfProfileOut( __METHOD__ );
 
                        return Html::rawElement(
                                'li',
@@ -119,8 +117,6 @@ class SpecialProtectedtitles extends SpecialPage {
                        )->escaped();
                }
 
-               wfProfileOut( __METHOD__ );
-
                // @todo i18n: This should use a comma separator instead of a hard coded comma, right?
                return '<li>' . $lang->specialList( $link, implode( $description_items, ', ' ) ) . "</li>\n";
        }
@@ -227,7 +223,6 @@ class ProtectedTitlesPager extends AlphabeticPager {
        }
 
        function getStartBody() {
-               wfProfileIn( __METHOD__ );
                # Do a link batch query
                $this->mResult->seek( 0 );
                $lb = new LinkBatch;
@@ -237,7 +232,6 @@ class ProtectedTitlesPager extends AlphabeticPager {
                }
 
                $lb->execute();
-               wfProfileOut( __METHOD__ );
 
                return '';
        }
index b4af7ba..69436bf 100644 (file)
@@ -230,7 +230,7 @@ class SpecialRandomInCategory extends FormSpecialPage {
                if ( !$this->minTimestamp || !$this->maxTimestamp ) {
                        try {
                                list( $this->minTimestamp, $this->maxTimestamp ) = $this->getMinAndMaxForCat( $this->category );
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                // Possibly no entries in category.
                                return false;
                        }
index b3b72ea..55be2c2 100644 (file)
@@ -206,7 +206,6 @@ class SpecialSearch extends SpecialPage {
        public function showResults( $term ) {
                global $wgContLang;
 
-               $profile = new ProfileSection( __METHOD__ );
                $search = $this->getSearchEngine();
                $search->setLimitOffset( $this->limit, $this->offset );
                $search->setNamespaces( $this->namespaces );
@@ -564,7 +563,6 @@ class SpecialSearch extends SpecialPage {
        protected function showMatches( &$matches ) {
                global $wgContLang;
 
-               $profile = new ProfileSection( __METHOD__ );
                $terms = $wgContLang->convertForSearchResult( $matches->termMatches() );
 
                $out = "<ul class='mw-search-results'>\n";
@@ -590,7 +588,6 @@ class SpecialSearch extends SpecialPage {
         * @return string
         */
        protected function showHit( $result, $terms ) {
-               $profile = new ProfileSection( __METHOD__ );
 
                if ( $result->isBrokenTitle() ) {
                        return '';
@@ -749,7 +746,6 @@ class SpecialSearch extends SpecialPage {
         */
        protected function showInterwiki( $matches, $query ) {
                global $wgContLang;
-               $profile = new ProfileSection( __METHOD__ );
 
                $out = "<div id='mw-search-interwiki'><div id='mw-search-interwiki-caption'>" .
                        $this->msg( 'search-interwiki-caption' )->text() . "</div>\n";
@@ -800,7 +796,6 @@ class SpecialSearch extends SpecialPage {
         * @return string
         */
        protected function showInterwikiHit( $result, $lastInterwiki, $query, $customCaptions ) {
-               $profile = new ProfileSection( __METHOD__ );
 
                if ( $result->isBrokenTitle() ) {
                        return '';
index d9e3a67..b965b54 100644 (file)
@@ -988,7 +988,7 @@ class UploadForm extends HTMLForm {
                        $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash();
                        try {
                                $file = $stash->getFile( $this->mSessionKey );
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                $file = null;
                        }
                        if ( $file ) {
index c836656..2aa629e 100644 (file)
@@ -252,7 +252,6 @@ class SpecialVersion extends SpecialPage {
         */
        public static function getVersion( $flags = '' ) {
                global $wgVersion, $IP;
-               wfProfileIn( __METHOD__ );
 
                $gitInfo = self::getGitHeadSha1( $IP );
                $svnInfo = self::getSvnInfo( $IP );
@@ -276,8 +275,6 @@ class SpecialVersion extends SpecialPage {
                                )->text();
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $version;
        }
 
@@ -291,7 +288,6 @@ class SpecialVersion extends SpecialPage {
         */
        public static function getVersionLinked() {
                global $wgVersion;
-               wfProfileIn( __METHOD__ );
 
                $gitVersion = self::getVersionLinkedGit();
                if ( $gitVersion ) {
@@ -305,8 +301,6 @@ class SpecialVersion extends SpecialPage {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $v;
        }
 
@@ -734,7 +728,7 @@ class SpecialVersion extends SpecialPage {
                        list( $vcsVersion, $vcsLink, $vcsDate ) = $cache->get( $memcKey );
 
                        if ( !$vcsVersion ) {
-                               wfDebug( "Getting VCS info for extension $extensionName" );
+                               wfDebug( "Getting VCS info for extension {$extension['name']}" );
                                $gitInfo = new GitInfo( $extensionPath );
                                $vcsVersion = $gitInfo->getHeadSHA1();
                                if ( $vcsVersion !== false ) {
@@ -750,7 +744,7 @@ class SpecialVersion extends SpecialPage {
                                }
                                $cache->set( $memcKey, array( $vcsVersion, $vcsLink, $vcsDate ), 60 * 60 * 24 );
                        } else {
-                               wfDebug( "Pulled VCS info for extension $extensionName from cache" );
+                               wfDebug( "Pulled VCS info for extension {$extension['name']} from cache" );
                        }
                }
 
@@ -793,24 +787,23 @@ class SpecialVersion extends SpecialPage {
                // ... and license information; if a license file exists we
                // will link to it
                $licenseLink = '';
-               if ( isset( $extension['license-name'] ) ) {
-                       $licenseLink = Linker::link(
-                               $this->getPageTitle( 'License/' . $extensionName ),
-                               $out->parseInline( $extension['license-name'] ),
-                               array(
-                                       'class' => 'mw-version-ext-license',
-                                       'dir' => 'auto',
-                               )
-                       );
-               } elseif ( $this->getExtLicenseFileName( $extensionPath ) ) {
-                       $licenseLink = Linker::link(
-                               $this->getPageTitle( 'License/' . $extensionName ),
-                               $this->msg( 'version-ext-license' ),
-                               array(
-                                       'class' => 'mw-version-ext-license',
-                                       'dir' => 'auto',
-                               )
-                       );
+               if ( isset( $extension['name'] ) ) {
+                       $licenseName = null;
+                       if ( isset( $extension['license-name'] ) ) {
+                               $licenseName = $out->parseInline( $extension['license-name'] );
+                       } elseif ( $this->getExtLicenseFileName( $extensionPath ) ) {
+                               $licenseName = $this->msg( 'version-ext-license' );
+                       }
+                       if ( $licenseName !== null ) {
+                               $licenseLink = Linker::link(
+                                       $this->getPageTitle( 'License/' . $extension['name'] ),
+                                       $licenseName,
+                                       array(
+                                               'class' => 'mw-version-ext-license',
+                                               'dir' => 'auto',
+                                       )
+                               );
+                       }
                }
 
                // ... and generate the description; which can be a parameterized l10n message
@@ -838,12 +831,12 @@ class SpecialVersion extends SpecialPage {
 
                // ... now get the authors for this extension
                $authors = isset( $extension['author'] ) ? $extension['author'] : array();
-               $authors = $this->listAuthors( $authors, $extensionName, $extensionPath );
+               $authors = $this->listAuthors( $authors, $extension['name'], $extensionPath );
 
                // Finally! Create the table
                $html = Html::openElement( 'tr', array(
                                'class' => 'mw-version-ext',
-                               'id' => "mw-version-ext-{$extensionName}"
+                               'id' => "mw-version-ext-{$extension['name']}"
                        )
                );
 
index 7e7abe5..bbc111f 100644 (file)
@@ -58,6 +58,7 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
                $opts->add( 'hidetrans', false );
                $opts->add( 'hidelinks', false );
                $opts->add( 'hideimages', false );
+               $opts->add( 'invert', false );
 
                $opts->fetchValuesFromRequest( $this->getRequest() );
                $opts->validateIntBounds( 'limit', 0, 5000 );
@@ -125,15 +126,17 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
 
                $useLinkNamespaceDBFields = $this->getConfig()->get( 'UseLinkNamespaceDBFields' );
                $namespace = $this->opts->getValue( 'namespace' );
+               $invert = $this->opts->getValue( 'invert' );
+               $nsComparison = ( $invert ? '!= ' : '= ' ) . $dbr->addQuotes( $namespace );
                if ( is_int( $namespace ) ) {
                        if ( $useLinkNamespaceDBFields ) {
-                               $conds['pagelinks']['pl_from_namespace'] = $namespace;
-                               $conds['templatelinks']['tl_from_namespace'] = $namespace;
-                               $conds['imagelinks']['il_from_namespace'] = $namespace;
+                               $conds['pagelinks'][] = "pl_from_namespace $nsComparison";
+                               $conds['templatelinks'][] = "tl_from_namespace $nsComparison";
+                               $conds['imagelinks'][] = "il_from_namespace $nsComparison";
                        } else {
-                               $conds['pagelinks']['page_namespace'] = $namespace;
-                               $conds['templatelinks']['page_namespace'] = $namespace;
-                               $conds['imagelinks']['page_namespace'] = $namespace;
+                               $conds['pagelinks'][] = "page_namespace $nsComparison";
+                               $conds['templatelinks'][] = "page_namespace $nsComparison";
+                               $conds['imagelinks'][] = "page_namespace $nsComparison";
                        }
                }
 
@@ -419,6 +422,7 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
 
                $target = $this->target ? $this->target->getPrefixedText() : '';
                $namespace = $this->opts->consumeValue( 'namespace' );
+               $nsinvert = $this->opts->consumeValue( 'invert' );
 
                # Build up the form
                $f = Xml::openElement( 'form', array( 'action' => wfScript() ) );
@@ -450,6 +454,15 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
                        )
                );
 
+               $f .= '&#160;' .
+                       Xml::checkLabel(
+                               $this->msg( 'invert' )->text(),
+                               'invert',
+                               'nsinvert',
+                               $nsinvert,
+                               array( 'title' => $this->msg( 'tooltip-whatlinkshere-invert' )->text() )
+                       );
+
                $f .= ' ';
 
                # Submit
diff --git a/includes/title/ForeignTitle.php b/includes/title/ForeignTitle.php
new file mode 100644 (file)
index 0000000..ed96d17
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * A structure to hold the title of a page on a foreign MediaWiki installation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public 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 This, that and the other
+ */
+
+/**
+ * A simple, immutable structure to hold the title of a page on a foreign
+ * MediaWiki installation.
+ */
+class ForeignTitle {
+       /**
+        * @var int|null
+        * Null if we don't know the namespace ID (e.g. interwiki links)
+        */
+       protected $namespaceId;
+       /** @var string */
+       protected $namespaceName;
+       /** @var string */
+       protected $pageName;
+
+       /**
+        * Creates a new ForeignTitle object.
+        *
+        * @param int|null $namespaceId Null if the namespace ID is unknown (e.g.
+        * interwiki links)
+        * @param string $namespaceName
+        * @param string $pageName
+        */
+       public function __construct( $namespaceId, $namespaceName, $pageName ) {
+               if ( is_null( $namespaceId ) ) {
+                       $this->namespaceId = null;
+               } else {
+                       $this->namespaceId = intval( $namespaceId );
+               }
+               $this->namespaceName = str_replace( ' ', '_', $namespaceName );
+               $this->pageName = str_replace( ' ', '_', $pageName );
+       }
+
+       /**
+        * Do we know the namespace ID of the page on the foreign wiki?
+        * @return bool
+        */
+       public function isNamespaceIdKnown() {
+               return !is_null( $this->namespaceId );
+       }
+
+       /**
+        * @return int
+        * @throws MWException If isNamespaceIdKnown() is false, it does not make
+        * sense to call this function.
+        */
+       public function getNamespaceId() {
+               if ( is_null( $this->namespaceId ) ) {
+                       throw new MWException(
+                               "Attempted to call getNamespaceId when the namespace ID is not known" );
+               }
+               return $this->namespaceId;
+       }
+
+       /** @return string */
+       public function getNamespaceName() {
+               return $this->namespaceName;
+       }
+
+       /** @return string */
+       public function getText() {
+               return $this->pageName;
+       }
+
+       /** @return string */
+       public function getFullText() {
+               $result = '';
+               if ( $this->namespaceName ) {
+                       $result .= $this->namespaceName . ':';
+               }
+               $result .= $this->pageName;
+               return $result;
+       }
+
+       /**
+        * Returns a string representation of the title, for logging. This is purely
+        * informative and must not be used programmatically. Use the appropriate
+        * ImportTitleFactory to generate the correct string representation for a
+        * given use.
+        *
+        * @return string
+        */
+       public function __toString() {
+               $name = '';
+               if ( $this->isNamespaceIdKnown() ) {
+                       $name .= '{ns' . $this->namespaceId . '}';
+               } else {
+                       $name .= '{ns??}';
+               }
+               $name .= $this->namespaceName . ':' . $this->pageName;
+
+               return $name;
+       }
+}
diff --git a/includes/title/ForeignTitleFactory.php b/includes/title/ForeignTitleFactory.php
new file mode 100644 (file)
index 0000000..427afdf
--- /dev/null
@@ -0,0 +1,36 @@
+<?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
+ * @license GPL 2+
+ */
+
+/**
+ * A parser that translates page titles into ForeignTitle objects.
+ */
+interface ForeignTitleFactory {
+       /**
+        * Creates a ForeignTitle object based on the page title, and optionally the
+        * namespace ID, of a page on a foreign wiki. These values could be, for
+        * example, the <title> and <ns> attributes found in an XML dump.
+        *
+        * @param string $title The page title
+        * @param int|null $ns The namespace ID, or null if this data is not available
+        * @return ForeignTitle
+        */
+       public function createForeignTitle( $title, $ns = null );
+}
diff --git a/includes/title/ImportTitleFactory.php b/includes/title/ImportTitleFactory.php
new file mode 100644 (file)
index 0000000..629616d
--- /dev/null
@@ -0,0 +1,36 @@
+<?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
+ * @license GPL 2+
+ */
+
+/**
+ * Represents an object that can convert page titles on a foreign wiki
+ * (ForeignTitle objects) into page titles on the local wiki (Title objects).
+ */
+interface ImportTitleFactory {
+       /**
+        * Determines which local title best corresponds to the given foreign title.
+        * If such a title can't be found or would be locally invalid, null is
+        * returned.
+        *
+        * @param ForeignTitle $foreignTitle The ForeignTitle to convert
+        * @return Title|null
+        */
+       public function createTitleFromForeignTitle( ForeignTitle $foreignTitle );
+}
diff --git a/includes/title/NaiveForeignTitleFactory.php b/includes/title/NaiveForeignTitleFactory.php
new file mode 100644 (file)
index 0000000..6c8bcc0
--- /dev/null
@@ -0,0 +1,71 @@
+<?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
+ * @license GPL 2+
+ */
+
+/**
+ * A parser that translates page titles on a foreign wiki into ForeignTitle
+ * objects, with no knowledge of the namespace setup on the foreign site.
+ */
+class NaiveForeignTitleFactory implements ForeignTitleFactory {
+       /**
+        * Creates a ForeignTitle object based on the page title, and optionally the
+        * namespace ID, of a page on a foreign wiki. These values could be, for
+        * example, the <title> and <ns> attributes found in an XML dump.
+        *
+        * Although exported XML dumps have contained a map of namespace IDs to names
+        * since MW 1.5, the importer used to completely ignore the <siteinfo> tag
+        * before MW 1.25.  It is therefore possible that custom XML dumps (i.e. not
+        * generated by Special:Export) have been created without this metadata.
+        * As a result, this code falls back to using namespace data for the local
+        * wiki (similar to buggy pre-1.25 behaviour) if $ns is not supplied.
+        *
+        * @param string $title The page title
+        * @param int|null $ns The namespace ID, or null if this data is not available
+        * @return ForeignTitle
+        */
+       public function createForeignTitle( $title, $ns = null ) {
+               $pieces = explode( ':', $title, 2 );
+
+               global $wgContLang;
+
+               // Can we assume that the part of the page title before the colon is a
+               // namespace name?
+               //
+               // XML export schema version 0.5 and earlier (MW 1.18 and earlier) does not
+               // contain a <ns> tag, so we need to be able to handle that case.
+               //
+               // If we know the namespace ID, we assume a non-zero namespace ID means
+               // the ':' sets off a valid namespace name. If we don't know the namespace
+               // ID, we fall back to using the local wiki's namespace names to resolve
+               // this -- better than nothing, and mimics the old crappy behavior
+               $isNamespacePartValid = is_null( $ns ) ?
+                       ( $wgContLang->getNsIndex( $pieces[0] ) !== false ) :
+                       $ns != 0;
+
+               if ( count( $pieces ) === 2 && $isNamespacePartValid ) {
+                       list( $namespaceName, $pageName ) = $pieces;
+               } else {
+                       $namespaceName = '';
+                       $pageName = $title;
+               }
+
+               return new ForeignTitle( $ns, $namespaceName, $pageName );
+       }
+}
diff --git a/includes/title/NaiveImportTitleFactory.php b/includes/title/NaiveImportTitleFactory.php
new file mode 100644 (file)
index 0000000..43c662e
--- /dev/null
@@ -0,0 +1,65 @@
+<?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
+ * @license GPL 2+
+ */
+
+/**
+ * A class to convert page titles on a foreign wiki (ForeignTitle objects) into
+ * page titles on the local wiki (Title objects), using a default namespace
+ * mapping.
+ *
+ * For built-in namespaces (0 <= ID < 100), we try to find a local namespace
+ * with the same namespace ID as the foreign page. If no such namespace exists,
+ * or the namespace ID is unknown or > 100, we look for a local namespace with
+ * a matching namespace name. If that can't be found, we dump the page in the
+ * main namespace as a last resort.
+ */
+class NaiveImportTitleFactory implements ImportTitleFactory {
+       /**
+        * Determines which local title best corresponds to the given foreign title.
+        * If such a title can't be found or would be locally invalid, null is
+        * returned.
+        *
+        * @param ForeignTitle $foreignTitle The ForeignTitle to convert
+        * @return Title|null
+        */
+       public function createTitleFromForeignTitle( ForeignTitle $foreignTitle ) {
+               global $wgContLang;
+
+               if ( $foreignTitle->isNamespaceIdKnown() ) {
+                       $foreignNs = $foreignTitle->getNamespaceId();
+
+                       // For built-in namespaces (0 <= ID < 100), we try to find a local NS with
+                       // the same namespace ID
+                       if ( $foreignNs < 100 && MWNamespace::exists( $foreignNs ) ) {
+                               return Title::makeTitleSafe( $foreignNs, $foreignTitle->getText() );
+                       }
+               }
+
+               // Do we have a local namespace by the same name as the foreign
+               // namespace?
+               $targetNs = $wgContLang->getNsIndex( $foreignTitle->getNamespaceName() );
+               if ( $targetNs !== false ) {
+                       return Title::makeTitleSafe( $targetNs, $foreignTitle->getText() );
+               }
+
+               // Otherwise, just fall back to main namespace
+               return Title::makeTitleSafe( 0, $foreignTitle->getFullText() );
+       }
+}
diff --git a/includes/title/NamespaceAwareForeignTitleFactory.php b/includes/title/NamespaceAwareForeignTitleFactory.php
new file mode 100644 (file)
index 0000000..bf97e2c
--- /dev/null
@@ -0,0 +1,134 @@
+<?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
+ * @license GPL 2+
+ */
+
+/**
+ * A parser that translates page titles on a foreign wiki into ForeignTitle
+ * objects, using information about the namespace setup on the foreign site.
+ */
+class NamespaceAwareForeignTitleFactory implements ForeignTitleFactory {
+       /**
+        * @var array
+        */
+       protected $foreignNamespaces;
+       /**
+        * @var array
+        */
+       private $foreignNamespacesFlipped;
+
+       /**
+        * Normalizes an array name for $foreignNamespacesFlipped.
+        * @param string $name
+        * @return string
+        */
+       private function normalizeNamespaceName( $name ) {
+               return strtolower( str_replace( ' ', '_', $name ) );
+       }
+
+       /**
+        * @param array|null $foreignNamespaces An array 'id' => 'name' which contains
+        * the complete namespace setup of the foreign wiki. Such data could be
+        * obtained from siteinfo/namespaces in an XML dump file, or by an action API
+        * query such as api.php?action=query&meta=siteinfo&siprop=namespaces. If
+        * this data is unavailable, use NaiveForeignTitleFactory instead.
+        */
+       public function __construct( $foreignNamespaces ) {
+               $this->foreignNamespaces = $foreignNamespaces;
+               if ( !is_null( $foreignNamespaces ) ) {
+                       $this->foreignNamespacesFlipped = array();
+                       foreach ( $foreignNamespaces as $id => $name ) {
+                               $newKey = self::normalizeNamespaceName( $name );
+                               $this->foreignNamespacesFlipped[$newKey] = $id;
+                       }
+               }
+       }
+
+       /**
+        * Creates a ForeignTitle object based on the page title, and optionally the
+        * namespace ID, of a page on a foreign wiki. These values could be, for
+        * example, the <title> and <ns> attributes found in an XML dump.
+        *
+        * @param string $title The page title
+        * @param int|null $ns The namespace ID, or null if this data is not available
+        * @return ForeignTitle
+        */
+       public function createForeignTitle( $title, $ns = null ) {
+               // Export schema version 0.5 and earlier (MW 1.18 and earlier) does not
+               // contain a <ns> tag, so we need to be able to handle that case.
+               if ( is_null( $ns ) ) {
+                       return self::parseTitleNoNs( $title );
+               } else {
+                       return self::parseTitleWithNs( $title, $ns );
+               }
+       }
+
+       /**
+        * Helper function to parse the title when the namespace ID is not specified.
+        *
+        * @param string $title
+        * @return ForeignTitle
+        */
+       protected function parseTitleNoNs( $title ) {
+               $pieces = explode( ':', $title, 2 );
+               $key = self::normalizeNamespaceName( $pieces[0] );
+
+               // Does the part before the colon match a known namespace? Check the
+               // foreign namespaces
+               $isNamespacePartValid = isset( $this->foreignNamespacesFlipped[$key] );
+
+               if ( count( $pieces ) === 2 && $isNamespacePartValid ) {
+                       list( $namespaceName, $pageName ) = $pieces;
+                       $ns = $this->foreignNamespacesFlipped[$key];
+               } else {
+                       $namespaceName = '';
+                       $pageName = $title;
+                       $ns = 0;
+               }
+
+               return new ForeignTitle( $ns, $namespaceName, $pageName );
+       }
+
+       /**
+        * Helper function to parse the title when the namespace value is known.
+        *
+        * @param string $title
+        * @param int $ns
+        * @return ForeignTitle
+        */
+       protected function parseTitleWithNs( $title, $ns ) {
+               $pieces = explode( ':', $title, 2 );
+
+               if ( isset( $this->foreignNamespaces[$ns] ) ) {
+                       $namespaceName = $this->foreignNamespaces[$ns];
+               } else {
+                       $namespaceName = $ns == '0' ? '' : $pieces[0];
+               }
+
+               // We assume that the portion of the page title before the colon is the
+               // namespace name, except in the case of namespace 0
+               if ( $ns != '0' ) {
+                       $pageName = $pieces[1];
+               } else {
+                       $pageName = $title;
+               }
+
+               return new ForeignTitle( $ns, $namespaceName, $pageName );
+       }
+}
diff --git a/includes/title/NamespaceImportTitleFactory.php b/includes/title/NamespaceImportTitleFactory.php
new file mode 100644 (file)
index 0000000..0c1d0c4
--- /dev/null
@@ -0,0 +1,52 @@
+<?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
+ * @license GPL 2+
+ */
+
+/**
+ * A class to convert page titles on a foreign wiki (ForeignTitle objects) into
+ * page titles on the local wiki (Title objects), placing all pages in a fixed
+ * local namespace.
+ */
+class NamespaceImportTitleFactory implements ImportTitleFactory {
+       /** @var int */
+       protected $ns;
+
+       /**
+        * @param int $ns The namespace to use for all pages
+        */
+       public function __construct( $ns ) {
+               if ( !MWNamespace::exists( $ns ) ) {
+                       throw new MWException( "Namespace $ns doesn't exist on this wiki" );
+               }
+               $this->ns = $ns;
+       }
+
+       /**
+        * Determines which local title best corresponds to the given foreign title.
+        * If such a title can't be found or would be locally invalid, null is
+        * returned.
+        *
+        * @param ForeignTitle $foreignTitle The ForeignTitle to convert
+        * @return Title|null
+        */
+       public function createTitleFromForeignTitle( ForeignTitle $foreignTitle ) {
+               return Title::makeTitleSafe( $this->ns, $foreignTitle->getText() );
+       }
+}
diff --git a/includes/title/SubpageImportTitleFactory.php b/includes/title/SubpageImportTitleFactory.php
new file mode 100644 (file)
index 0000000..b0be7af
--- /dev/null
@@ -0,0 +1,55 @@
+<?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
+ * @license GPL 2+
+ */
+
+/**
+ * A class to convert page titles on a foreign wiki (ForeignTitle objects) into
+ * page titles on the local wiki (Title objects), placing all pages as subpages
+ * of a given root page.
+ */
+class SubpageImportTitleFactory implements ImportTitleFactory {
+       /** @var Title */
+       protected $rootPage;
+
+       /**
+        * @param Title $rootPage The root page under which all pages should be
+        * created
+        */
+       public function __construct( Title $rootPage ) {
+               if ( !MWNamespace::hasSubpages( $rootPage->getNamespace() ) ) {
+                       throw new MWException( "The root page you specified, $rootPage, is in a " .
+                               "namespace where subpages are not allowed" );
+               }
+               $this->rootPage = $rootPage;
+       }
+
+       /**
+        * Determines which local title best corresponds to the given foreign title.
+        * If such a title can't be found or would be locally invalid, null is
+        * returned.
+        *
+        * @param ForeignTitle $foreignTitle The ForeignTitle to convert
+        * @return Title|null
+        */
+       public function createTitleFromForeignTitle( ForeignTitle $foreignTitle ) {
+               return Title::newFromText( $this->rootPage->getPrefixedDBkey() . '/' .
+                       $foreignTitle->getFullText() );
+       }
+}
index 4c96dc8..a8a38c7 100644 (file)
@@ -261,7 +261,6 @@ abstract class UploadBase {
         * @return string|bool The real path if it was a virtual URL Returns false on failure
         */
        function getRealPath( $srcPath ) {
-               wfProfileIn( __METHOD__ );
                $repo = RepoGroup::singleton()->getLocalRepo();
                if ( $repo->isVirtualUrl( $srcPath ) ) {
                        /** @todo Just make uploads work with storage paths UploadFromStash
@@ -275,7 +274,6 @@ abstract class UploadBase {
                } else {
                        $path = $srcPath;
                }
-               wfProfileOut( __METHOD__ );
 
                return $path;
        }
@@ -285,13 +283,11 @@ abstract class UploadBase {
         * @return mixed Const self::OK or else an array with error information
         */
        public function verifyUpload() {
-               wfProfileIn( __METHOD__ );
 
                /**
                 * If there was no filename or a zero size given, give up quick.
                 */
                if ( $this->isEmptyFile() ) {
-                       wfProfileOut( __METHOD__ );
 
                        return array( 'status' => self::EMPTY_FILE );
                }
@@ -301,7 +297,6 @@ abstract class UploadBase {
                 */
                $maxSize = self::getMaxUploadSize( $this->getSourceType() );
                if ( $this->mFileSize > $maxSize ) {
-                       wfProfileOut( __METHOD__ );
 
                        return array(
                                'status' => self::FILE_TOO_LARGE,
@@ -316,7 +311,6 @@ abstract class UploadBase {
                 */
                $verification = $this->verifyFile();
                if ( $verification !== true ) {
-                       wfProfileOut( __METHOD__ );
 
                        return array(
                                'status' => self::VERIFICATION_ERROR,
@@ -329,7 +323,6 @@ abstract class UploadBase {
                 */
                $result = $this->validateName();
                if ( $result !== true ) {
-                       wfProfileOut( __METHOD__ );
 
                        return $result;
                }
@@ -338,13 +331,10 @@ abstract class UploadBase {
                if ( !Hooks::run( 'UploadVerification',
                        array( $this->mDestName, $this->mTempPath, &$error ) )
                ) {
-                       wfProfileOut( __METHOD__ );
 
                        return array( 'status' => self::HOOK_ABORTED, 'error' => $error );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return array( 'status' => self::OK );
        }
 
@@ -386,12 +376,10 @@ abstract class UploadBase {
         */
        protected function verifyMimeType( $mime ) {
                global $wgVerifyMimeType;
-               wfProfileIn( __METHOD__ );
                if ( $wgVerifyMimeType ) {
                        wfDebug( "mime: <$mime> extension: <{$this->mFinalExtension}>\n" );
                        global $wgMimeTypeBlacklist;
                        if ( $this->checkFileExtension( $mime, $wgMimeTypeBlacklist ) ) {
-                               wfProfileOut( __METHOD__ );
 
                                return array( 'filetype-badmime', $mime );
                        }
@@ -406,15 +394,12 @@ abstract class UploadBase {
                        $ieTypes = $magic->getIEMimeTypes( $this->mTempPath, $chunk, $extMime );
                        foreach ( $ieTypes as $ieType ) {
                                if ( $this->checkFileExtension( $ieType, $wgMimeTypeBlacklist ) ) {
-                                       wfProfileOut( __METHOD__ );
 
                                        return array( 'filetype-bad-ie-mime', $ieType );
                                }
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-
                return true;
        }
 
@@ -425,11 +410,9 @@ abstract class UploadBase {
         */
        protected function verifyFile() {
                global $wgVerifyMimeType, $wgDisableUploadScriptChecks;
-               wfProfileIn( __METHOD__ );
 
                $status = $this->verifyPartialFile();
                if ( $status !== true ) {
-                       wfProfileOut( __METHOD__ );
 
                        return $status;
                }
@@ -440,7 +423,6 @@ abstract class UploadBase {
                if ( $wgVerifyMimeType ) {
                        # XXX: Missing extension will be caught by validateName() via getTitle()
                        if ( $this->mFinalExtension != '' && !$this->verifyExtension( $mime, $this->mFinalExtension ) ) {
-                               wfProfileOut( __METHOD__ );
 
                                return array( 'filetype-mime-mismatch', $this->mFinalExtension, $mime );
                        }
@@ -451,7 +433,6 @@ abstract class UploadBase {
                        if ( $this->mFinalExtension == 'svg' || $mime == 'image/svg+xml' ) {
                                $svgStatus = $this->detectScriptInSvg( $this->mTempPath, false );
                                if ( $svgStatus !== false ) {
-                                       wfProfileOut( __METHOD__ );
 
                                        return $svgStatus;
                                }
@@ -463,7 +444,6 @@ abstract class UploadBase {
                        $handlerStatus = $handler->verifyUpload( $this->mTempPath );
                        if ( !$handlerStatus->isOK() ) {
                                $errors = $handlerStatus->getErrorsArray();
-                               wfProfileOut( __METHOD__ );
 
                                return reset( $errors );
                        }
@@ -471,13 +451,11 @@ abstract class UploadBase {
 
                Hooks::run( 'UploadVerifyFile', array( $this, $mime, &$status ) );
                if ( $status !== true ) {
-                       wfProfileOut( __METHOD__ );
 
                        return $status;
                }
 
                wfDebug( __METHOD__ . ": all clear; passing.\n" );
-               wfProfileOut( __METHOD__ );
 
                return true;
        }
@@ -492,7 +470,6 @@ abstract class UploadBase {
         */
        protected function verifyPartialFile() {
                global $wgAllowJavaUploads, $wgDisableUploadScriptChecks;
-               wfProfileIn( __METHOD__ );
 
                # getTitle() sets some internal parameters like $this->mFinalExtension
                $this->getTitle();
@@ -503,7 +480,6 @@ abstract class UploadBase {
                $mime = $this->mFileProps['file-mime'];
                $status = $this->verifyMimeType( $mime );
                if ( $status !== true ) {
-                       wfProfileOut( __METHOD__ );
 
                        return $status;
                }
@@ -511,14 +487,12 @@ abstract class UploadBase {
                # check for htmlish code and javascript
                if ( !$wgDisableUploadScriptChecks ) {
                        if ( self::detectScript( $this->mTempPath, $mime, $this->mFinalExtension ) ) {
-                               wfProfileOut( __METHOD__ );
 
                                return array( 'uploadscripted' );
                        }
                        if ( $this->mFinalExtension == 'svg' || $mime == 'image/svg+xml' ) {
                                $svgStatus = $this->detectScriptInSvg( $this->mTempPath, true );
                                if ( $svgStatus !== false ) {
-                                       wfProfileOut( __METHOD__ );
 
                                        return $svgStatus;
                                }
@@ -535,13 +509,11 @@ abstract class UploadBase {
                                $errors = $zipStatus->getErrorsArray();
                                $error = reset( $errors );
                                if ( $error[0] !== 'zip-wrong-format' ) {
-                                       wfProfileOut( __METHOD__ );
 
                                        return $error;
                                }
                        }
                        if ( $this->mJavaDetected ) {
-                               wfProfileOut( __METHOD__ );
 
                                return array( 'uploadjava' );
                        }
@@ -550,13 +522,10 @@ abstract class UploadBase {
                # Scan the uploaded file for viruses
                $virus = $this->detectVirus( $this->mTempPath );
                if ( $virus ) {
-                       wfProfileOut( __METHOD__ );
 
                        return array( 'uploadvirus', $virus );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return true;
        }
 
@@ -649,7 +618,6 @@ abstract class UploadBase {
         */
        public function checkWarnings() {
                global $wgLang;
-               wfProfileIn( __METHOD__ );
 
                $warnings = array();
 
@@ -718,8 +686,6 @@ abstract class UploadBase {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $warnings;
        }
 
@@ -735,7 +701,6 @@ abstract class UploadBase {
         * @return Status Indicating the whether the upload succeeded.
         */
        public function performUpload( $comment, $pageText, $watch, $user ) {
-               wfProfileIn( __METHOD__ );
 
                $status = $this->getLocalFile()->upload(
                        $this->mTempPath,
@@ -760,8 +725,6 @@ abstract class UploadBase {
                        $this->postProcessUpload();
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $status;
        }
 
@@ -952,14 +915,11 @@ abstract class UploadBase {
         */
        public function stashFile( User $user = null ) {
                // was stashSessionFile
-               wfProfileIn( __METHOD__ );
 
                $stash = RepoGroup::singleton()->getLocalRepo()->getUploadStash( $user );
                $file = $stash->stashFile( $this->mTempPath, $this->getSourceType() );
                $this->mLocalFile = $file;
 
-               wfProfileOut( __METHOD__ );
-
                return $file;
        }
 
@@ -1099,7 +1059,6 @@ abstract class UploadBase {
         */
        public static function detectScript( $file, $mime, $extension ) {
                global $wgAllowTitlesInSVG;
-               wfProfileIn( __METHOD__ );
 
                # ugly hack: for text files, always look at the entire file.
                # For binary field, just check the first K.
@@ -1115,7 +1074,6 @@ abstract class UploadBase {
                $chunk = strtolower( $chunk );
 
                if ( !$chunk ) {
-                       wfProfileOut( __METHOD__ );
 
                        return false;
                }
@@ -1140,7 +1098,6 @@ abstract class UploadBase {
 
                # check for HTML doctype
                if ( preg_match( "/<!DOCTYPE *X?HTML/i", $chunk ) ) {
-                       wfProfileOut( __METHOD__ );
 
                        return true;
                }
@@ -1149,7 +1106,6 @@ abstract class UploadBase {
                // PHP/expat will interpret the given encoding in the xml declaration (bug 47304)
                if ( $extension == 'svg' || strpos( $mime, 'image/svg' ) === 0 ) {
                        if ( self::checkXMLEncodingMissmatch( $file ) ) {
-                               wfProfileOut( __METHOD__ );
 
                                return true;
                        }
@@ -1188,7 +1144,6 @@ abstract class UploadBase {
                foreach ( $tags as $tag ) {
                        if ( false !== strpos( $chunk, $tag ) ) {
                                wfDebug( __METHOD__ . ": found something that may make it be mistaken for html: $tag\n" );
-                               wfProfileOut( __METHOD__ );
 
                                return true;
                        }
@@ -1204,7 +1159,6 @@ abstract class UploadBase {
                # look for script-types
                if ( preg_match( '!type\s*=\s*[\'"]?\s*(?:\w*/)?(?:ecma|java)!sim', $chunk ) ) {
                        wfDebug( __METHOD__ . ": found script types\n" );
-                       wfProfileOut( __METHOD__ );
 
                        return true;
                }
@@ -1212,7 +1166,6 @@ abstract class UploadBase {
                # look for html-style script-urls
                if ( preg_match( '!(?:href|src|data)\s*=\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk ) ) {
                        wfDebug( __METHOD__ . ": found html-style script urls\n" );
-                       wfProfileOut( __METHOD__ );
 
                        return true;
                }
@@ -1220,13 +1173,11 @@ abstract class UploadBase {
                # look for css-style script-urls
                if ( preg_match( '!url\s*\(\s*[\'"]?\s*(?:ecma|java)script:!sim', $chunk ) ) {
                        wfDebug( __METHOD__ . ": found css-style script urls\n" );
-                       wfProfileOut( __METHOD__ );
 
                        return true;
                }
 
                wfDebug( __METHOD__ . ": no scripts found\n" );
-               wfProfileOut( __METHOD__ );
 
                return false;
        }
@@ -1650,11 +1601,9 @@ abstract class UploadBase {
         */
        public static function detectVirus( $file ) {
                global $wgAntivirus, $wgAntivirusSetup, $wgAntivirusRequired, $wgOut;
-               wfProfileIn( __METHOD__ );
 
                if ( !$wgAntivirus ) {
                        wfDebug( __METHOD__ . ": virus scanner disabled\n" );
-                       wfProfileOut( __METHOD__ );
 
                        return null;
                }
@@ -1663,7 +1612,6 @@ abstract class UploadBase {
                        wfDebug( __METHOD__ . ": unknown virus scanner: $wgAntivirus\n" );
                        $wgOut->wrapWikiMsg( "<div class=\"error\">\n$1\n</div>",
                                array( 'virus-badscanner', $wgAntivirus ) );
-                       wfProfileOut( __METHOD__ );
 
                        return wfMessage( 'virus-unknownscanner' )->text() . " $wgAntivirus";
                }
@@ -1737,8 +1685,6 @@ abstract class UploadBase {
                        wfDebug( __METHOD__ . ": FOUND VIRUS! scanner feedback: $output \n" );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return $output;
        }
 
index 55a8994..4441236 100644 (file)
@@ -731,7 +731,6 @@ class IP {
        public static function isConfiguredProxy( $ip ) {
                global $wgSquidServers, $wgSquidServersNoPurge;
 
-               wfProfileIn( __METHOD__ );
                // Quick check of known singular proxy servers
                $trusted = in_array( $ip, $wgSquidServers );
 
@@ -742,7 +741,6 @@ class IP {
                        }
                        $trusted = self::$proxyIpSet->match( $ip );
                }
-               wfProfileOut( __METHOD__ );
 
                return $trusted;
        }
index b602f78..e6c0e78 100644 (file)
@@ -294,7 +294,6 @@ class MWCryptRand {
         * @see self::generate()
         */
        public function realGenerate( $bytes, $forceStrong = false ) {
-               wfProfileIn( __METHOD__ );
 
                wfDebug( __METHOD__ . ": Generating cryptographic random bytes for " .
                        wfGetAllCallers( 5 ) . "\n" );
@@ -314,7 +313,6 @@ class MWCryptRand {
                        // entropy so this is also preferable to just trying to read urandom because it may work
                        // on Windows systems as well.
                        if ( function_exists( 'mcrypt_create_iv' ) ) {
-                               wfProfileIn( __METHOD__ . '-mcrypt' );
                                $rem = $bytes - strlen( $buffer );
                                $iv = mcrypt_create_iv( $rem, MCRYPT_DEV_URANDOM );
                                if ( $iv === false ) {
@@ -324,7 +322,6 @@ class MWCryptRand {
                                        wfDebug( __METHOD__ . ": mcrypt_create_iv generated " . strlen( $iv ) .
                                                " bytes of randomness.\n" );
                                }
-                               wfProfileOut( __METHOD__ . '-mcrypt' );
                        }
                }
 
@@ -337,7 +334,6 @@ class MWCryptRand {
                        if ( function_exists( 'openssl_random_pseudo_bytes' )
                                && ( !wfIsWindows() || version_compare( PHP_VERSION, '5.3.4', '>=' ) )
                        ) {
-                               wfProfileIn( __METHOD__ . '-openssl' );
                                $rem = $bytes - strlen( $buffer );
                                $openssl_bytes = openssl_random_pseudo_bytes( $rem, $openssl_strong );
                                if ( $openssl_bytes === false ) {
@@ -353,7 +349,6 @@ class MWCryptRand {
                                        // using it use it's say on whether the randomness is strong
                                        $this->strong = !!$openssl_strong;
                                }
-                               wfProfileOut( __METHOD__ . '-openssl' );
                        }
                }
 
@@ -361,7 +356,6 @@ class MWCryptRand {
                if ( strlen( $buffer ) < $bytes &&
                        ( function_exists( 'stream_set_read_buffer' ) || $forceStrong )
                ) {
-                       wfProfileIn( __METHOD__ . '-fopen-urandom' );
                        $rem = $bytes - strlen( $buffer );
                        if ( !function_exists( 'stream_set_read_buffer' ) && $forceStrong ) {
                                wfDebug( __METHOD__ . ": Was forced to read from /dev/urandom " .
@@ -400,7 +394,6 @@ class MWCryptRand {
                        } else {
                                wfDebug( __METHOD__ . ": /dev/urandom could not be opened.\n" );
                        }
-                       wfProfileOut( __METHOD__ . '-fopen-urandom' );
                }
 
                // If we cannot use or generate enough data from a secure source
@@ -414,12 +407,10 @@ class MWCryptRand {
                                ": Falling back to using a pseudo random state to generate randomness.\n" );
                }
                while ( strlen( $buffer ) < $bytes ) {
-                       wfProfileIn( __METHOD__ . '-fallback' );
                        $buffer .= $this->hmac( $this->randomState(), mt_rand() );
                        // This code is never really cryptographically strong, if we use it
                        // at all, then set strong to false.
                        $this->strong = false;
-                       wfProfileOut( __METHOD__ . '-fallback' );
                }
 
                // Once the buffer has been filled up with enough random data to fulfill
@@ -431,8 +422,6 @@ class MWCryptRand {
                wfDebug( __METHOD__ . ": " . strlen( $buffer ) .
                        " bytes of randomness leftover in the buffer.\n" );
 
-               wfProfileOut( __METHOD__ );
-
                return $generated;
        }
 
index 86f4512..c71e315 100644 (file)
@@ -498,16 +498,12 @@ class ReplacementArray {
         */
        function replace( $subject ) {
                if ( function_exists( 'fss_prep_replace' ) ) {
-                       wfProfileIn( __METHOD__ . '-fss' );
                        if ( $this->fss === false ) {
                                $this->fss = fss_prep_replace( $this->data );
                        }
                        $result = fss_exec_replace( $this->fss, $subject );
-                       wfProfileOut( __METHOD__ . '-fss' );
                } else {
-                       wfProfileIn( __METHOD__ . '-strtr' );
                        $result = strtr( $subject, $this->data );
-                       wfProfileOut( __METHOD__ . '-strtr' );
                }
 
                return $result;
index 33e9116..9241587 100644 (file)
@@ -281,7 +281,7 @@ class UIDGenerator {
                if ( ( $flags & self::QUICK_VOLATILE ) && PHP_SAPI !== 'cli' ) {
                        try {
                                $cache = ObjectCache::newAccelerator( array() );
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                // not supported
                        }
                }
index d46845f..fbd4f6d 100644 (file)
@@ -854,7 +854,6 @@ class Language {
         * @since 1.20
         */
        public static function fetchLanguageNames( $inLanguage = null, $include = 'mw' ) {
-               wfProfileIn( __METHOD__ );
                $cacheKey = $inLanguage === null ? 'null' : $inLanguage;
                $cacheKey .= ":$include";
                if ( self::$languageNameCache === null ) {
@@ -866,7 +865,6 @@ class Language {
                        $ret = self::fetchLanguageNamesUncached( $inLanguage, $include );
                        self::$languageNameCache->set( $cacheKey, $ret );
                }
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -4445,7 +4443,6 @@ class Language {
                        return array( $wikiUpperChars, $wikiLowerChars );
                }
 
-               wfProfileIn( __METHOD__ );
                $arr = wfGetPrecompiledData( 'Utf8Case.ser' );
                if ( $arr === false ) {
                        throw new MWException(
@@ -4453,7 +4450,6 @@ class Language {
                }
                $wikiUpperChars = $arr['wikiUpperChars'];
                $wikiLowerChars = $arr['wikiLowerChars'];
-               wfProfileOut( __METHOD__ );
                return array( $wikiUpperChars, $wikiLowerChars );
        }
 
index eae77fb..43d6063 100644 (file)
@@ -336,20 +336,17 @@ class LanguageConverter {
         * @return string The converted text
         */
        public function autoConvert( $text, $toVariant = false ) {
-               wfProfileIn( __METHOD__ );
 
                $this->loadTables();
 
                if ( !$toVariant ) {
                        $toVariant = $this->getPreferredVariant();
                        if ( !$toVariant ) {
-                               wfProfileOut( __METHOD__ );
                                return $text;
                        }
                }
 
                if ( $this->guessVariant( $text, $toVariant ) ) {
-                       wfProfileOut( __METHOD__ );
                        return $text;
                }
 
@@ -446,7 +443,6 @@ class LanguageConverter {
                        $literalIter->next();
                }
 
-               wfProfileOut( __METHOD__ );
                return $output;
        }
 
@@ -460,14 +456,12 @@ class LanguageConverter {
         * @return string Translated text
         */
        public function translate( $text, $variant ) {
-               wfProfileIn( __METHOD__ );
                // If $text is empty or only includes spaces, do nothing
                // Otherwise translate it
                if ( trim( $text ) ) {
                        $this->loadTables();
                        $text = $this->mTables[$variant]->replace( $text );
                }
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -478,7 +472,6 @@ class LanguageConverter {
         * @return array Variant => converted text
         */
        public function autoConvertToAllVariants( $text ) {
-               wfProfileIn( __METHOD__ );
                $this->loadTables();
 
                $ret = array();
@@ -486,7 +479,6 @@ class LanguageConverter {
                        $ret[$variant] = $this->translate( $text, $variant );
                }
 
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -856,7 +848,6 @@ class LanguageConverter {
                        return;
                }
 
-               wfProfileIn( __METHOD__ );
                $this->mTablesLoaded = true;
                $this->mTables = false;
                if ( $fromCache ) {
@@ -881,7 +872,6 @@ class LanguageConverter {
                        $wgLangConvMemc->set( $this->mCacheKey, $this->mTables, 43200 );
                        wfProfileOut( __METHOD__ . '-recache' );
                }
-               wfProfileOut( __METHOD__ );
        }
 
        /**
index ac59380..56faa4a 100644 (file)
@@ -44,7 +44,6 @@ class LanguageBe_tarask extends Language {
         * @return string
         */
        function normalizeForSearch( $string ) {
-               wfProfileIn( __METHOD__ );
 
                # MySQL fulltext index doesn't grok utf-8, so we
                # need to fold cases and convert to hex
@@ -54,7 +53,6 @@ class LanguageBe_tarask extends Language {
 
                $s = parent::normalizeForSearch( $s );
 
-               wfProfileOut( __METHOD__ );
                return $s;
        }
 
index 39e62f5..b8af885 100644 (file)
@@ -454,7 +454,6 @@ class LanguageKk extends LanguageKk_cyrl {
         * @return string
         */
        function convertGrammar( $word, $case ) {
-               wfProfileIn( __METHOD__ );
 
                $variant = $this->getPreferredVariant();
                switch ( $variant ) {
@@ -473,7 +472,6 @@ class LanguageKk extends LanguageKk_cyrl {
                                $word = parent::convertGrammarKk_cyrl( $word, $case );
                }
 
-               wfProfileOut( __METHOD__ );
                return $word;
        }
 }
index 3293cc6..d5f3e76 100644 (file)
@@ -54,14 +54,12 @@ class LanguageYue extends Language {
         * @return string
         */
        function normalizeForSearch( $string ) {
-               wfProfileIn( __METHOD__ );
 
                // Double-width roman characters
                $s = self::convertDoubleWidth( $string );
                $s = trim( $s );
                $s = parent::normalizeForSearch( $s );
 
-               wfProfileOut( __METHOD__ );
                return $s;
        }
 }
index 67f8769..4271ed3 100644 (file)
@@ -67,23 +67,35 @@ class ZhConverter extends LanguageConverter {
                $this->mTables = array(
                        'zh-hans' => new ReplacementArray( $zh2Hans ),
                        'zh-hant' => new ReplacementArray( $zh2Hant ),
-                       'zh-cn' => new ReplacementArray( array_merge( $zh2Hans, $zh2CN ) ),
-                       'zh-hk' => new ReplacementArray( array_merge( $zh2Hant, $zh2HK ) ),
-                       'zh-mo' => new ReplacementArray( array_merge( $zh2Hant, $zh2HK ) ),
-                       'zh-my' => new ReplacementArray( array_merge( $zh2Hans, $zh2SG ) ),
-                       'zh-sg' => new ReplacementArray( array_merge( $zh2Hans, $zh2SG ) ),
-                       'zh-tw' => new ReplacementArray( array_merge( $zh2Hant, $zh2TW ) ),
+                       'zh-cn' => new ReplacementArray( $zh2CN ),
+                       'zh-hk' => new ReplacementArray( $zh2HK ),
+                       'zh-mo' => new ReplacementArray( $zh2HK ),
+                       'zh-my' => new ReplacementArray( $zh2SG ),
+                       'zh-sg' => new ReplacementArray( $zh2SG ),
+                       'zh-tw' => new ReplacementArray( $zh2TW ),
                        'zh' => new ReplacementArray
                );
        }
 
        function postLoadTables() {
-               $this->mTables['zh-cn']->merge( $this->mTables['zh-hans'] );
-               $this->mTables['zh-hk']->merge( $this->mTables['zh-hant'] );
-               $this->mTables['zh-mo']->merge( $this->mTables['zh-hant'] );
-               $this->mTables['zh-my']->merge( $this->mTables['zh-hans'] );
-               $this->mTables['zh-sg']->merge( $this->mTables['zh-hans'] );
-               $this->mTables['zh-tw']->merge( $this->mTables['zh-hant'] );
+               $this->mTables['zh-cn']->setArray(
+                       $this->mTables['zh-cn']->getArray() + $this->mTables['zh-hans']->getArray()
+               );
+               $this->mTables['zh-hk']->setArray(
+                       $this->mTables['zh-hk']->getArray() + $this->mTables['zh-hant']->getArray()
+               );
+               $this->mTables['zh-mo']->setArray(
+                       $this->mTables['zh-mo']->getArray() + $this->mTables['zh-hant']->getArray()
+               );
+               $this->mTables['zh-my']->setArray(
+                       $this->mTables['zh-my']->getArray() + $this->mTables['zh-hans']->getArray()
+               );
+               $this->mTables['zh-sg']->setArray(
+                       $this->mTables['zh-sg']->getArray() + $this->mTables['zh-hans']->getArray()
+               );
+               $this->mTables['zh-tw']->setArray(
+                       $this->mTables['zh-tw']->getArray() + $this->mTables['zh-hant']->getArray()
+               );
        }
 
        /**
@@ -170,7 +182,6 @@ class LanguageZh extends LanguageZh_hans {
         * @return string
         */
        function normalizeForSearch( $string, $autoVariant = 'zh-hans' ) {
-               wfProfileIn( __METHOD__ );
 
                // always convert to zh-hans before indexing. it should be
                // better to use zh-hans for search, since conversion from
@@ -179,7 +190,6 @@ class LanguageZh extends LanguageZh_hans {
                $s = $this->mConverter->autoConvert( $string, $autoVariant );
                // LanguageZh_hans::normalizeForSearch
                $s = parent::normalizeForSearch( $s );
-               wfProfileOut( __METHOD__ );
                return $s;
 
        }
index 6483d90..75a05fd 100644 (file)
@@ -56,14 +56,12 @@ class LanguageZh_hans extends Language {
         * @return string
         */
        function normalizeForSearch( $s ) {
-               wfProfileIn( __METHOD__ );
 
                // Double-width roman characters
                $s = parent::normalizeForSearch( $s );
                $s = trim( $s );
                $s = $this->segmentByWord( $s );
 
-               wfProfileOut( __METHOD__ );
                return $s;
        }
 
index 4baeb6b..c887abd 100644 (file)
        "import-logentry-interwiki": "importeer $1 via transwiki",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|weergawe|weergawes}} vanaf $2",
        "javascripttest": "JavaScript toetsing",
-       "javascripttest-title": "Voer toetse uit vir $1",
        "javascripttest-pagetext-noframework": "Hierdie bladsy is gereserveer vir die uitvoer van JavaScript-toetse.",
        "javascripttest-pagetext-unknownframework": "Onbekende toetsraamwerk \"$1\".",
        "javascripttest-pagetext-frameworks": "Kies een van die volgende toetsraamwerke: $1",
        "javascripttest-pagetext-skins": "Kies 'n omslag waarmee die toets uitgevoer moet word:",
        "javascripttest-qunit-intro": "Sien die [$1 toetsdokumentasie] op mediawiki.org.",
-       "javascripttest-qunit-heading": "QUnit toetssuite vir MediaWiki JavaScript",
        "tooltip-pt-userpage": "My gebruikerbladsy",
        "tooltip-pt-anonuserpage": "Die gebruikersbladsy vir die IP-adres waaronder u wysigings aanbring",
        "tooltip-pt-mytalk": "My besprekingsbladsy",
index a1e810a..7c62f5f 100644 (file)
        "import-logentry-interwiki": "استورد عبر الويكي $1",
        "import-logentry-interwiki-detail": "تم استيراد {{PLURAL:$1||مراجعة واحدة|مراجعتين|$1 مراجعات|$1 مراجعة}} من $2",
        "javascripttest": "اختبار جافاسكربت",
-       "javascripttest-title": "تشغيل أختبارات $1",
        "javascripttest-pagetext-noframework": "هذه الصفحة محجوزة لإجراء أختبارات الجافا سكريبت.",
        "javascripttest-pagetext-unknownframework": "إطار اختبار غير معروف \"$1\".",
        "javascripttest-pagetext-frameworks": "الرجاء اختيار أحد أطر الاختبارات التالية: $1",
        "javascripttest-pagetext-skins": "قم باختيار الواجهة لإجراء الإحتبارات بها:",
        "javascripttest-qunit-intro": "راجع [$1 وثيقة الاختبار] على mediawiki.org.",
-       "javascripttest-qunit-heading": "جناح اختبار MediaWiki JavaScript QUnit",
        "tooltip-pt-userpage": "صفحة المستخدم الخاصة بك",
        "tooltip-pt-anonuserpage": "صفحة المستخدم للأيبي الذي تقوم بالتحرير من خلاله",
        "tooltip-pt-mytalk": "صفحة نقاشك",
index 7fc69a2..4090ae6 100644 (file)
        "import-logentry-interwiki": "আন্তঃৱিকি-স্থানান্তৰিত $1",
        "import-logentry-interwiki-detail": "$2ৱে কৰা $1 {{PLURAL:$1|টা সংশোধন|টা সংশোধন}}",
        "javascripttest": "জাভাস্ক্ৰিপ্ট পৰীক্ষা।",
-       "javascripttest-title": "$1 পৰীক্ষাসমূহ চলোৱা হৈছে",
        "javascripttest-pagetext-noframework": "এই পৃষ্ঠাটো জাভাস্ক্ৰিপ্ট পৰীক্ষা চলোৱাৰ বাবে সংৰক্ষিত।",
        "javascripttest-pagetext-unknownframework": "অজ্ঞাত সম্পৰীক্ষা ফ্ৰেমৱৰ্ক \"$1\"।",
        "javascripttest-pagetext-frameworks": "অনুগ্ৰহ কৰি তলৰ যিকোনো এটা সম্পৰীক্ষা ফ্ৰেমৱৰ্ক বাছনি কৰক: $1",
        "javascripttest-pagetext-skins": "পৰীক্ষা কৰিবলৈ আৱৰণ এখন বাছনি কৰক:",
        "javascripttest-qunit-intro": "mediawiki.org-ত [$1 পৰীক্ষা নথিকৰণ] চাওক।",
-       "javascripttest-qunit-heading": "মিডিয়াৱিকি জাভাস্ক্ৰিপ্ট QUnit পৰীক্ষা চুট",
        "tooltip-pt-userpage": "আপোনাৰ সদস্য পৃষ্ঠা",
        "tooltip-pt-anonuserpage": "যি আই.পি. ঠিকনাৰ পৰা আপুনি সম্পাদনা কৰিছে তাৰ সদস্য পৃষ্ঠা",
        "tooltip-pt-mytalk": "আপোনাৰ আলোচনা পৃষ্ঠা",
index 9ec689a..73d5d6f 100644 (file)
@@ -5,14 +5,14 @@
                ]
        },
        "tog-underline": "कड़ि अधोरेखन:",
-       "tog-hideminor": "हाल à¤\95य à¤¬à¤¦à¤²à¤¾à¤µà¤®à¥\87à¤\82 à¤\9bà¥\8bà¤\9f à¤¬à¤¦à¤²à¤¾à¤µ à¤²à¥\81à¤\95à¥\81वाà¤\93",
-       "tog-hidepatrolled": "हाल à¤\95य à¤¬à¤¦à¤²à¤¾à¤µà¤®à¥\87à¤\82 à¤ªà¤°à¥\80à¤\95à¥\8dषित à¤¬à¤¦à¤²à¤¾à¤µ à¤²à¥\81à¤\95à¥\81वाà¤\93",
-       "tog-newpageshidepatrolled": "नवा à¤ªà¤¨à¥\8dनन à¤\95य à¤¸à¥\82à¤\9aà¥\80 à¤®à¥\87à¤\82 à¤ªà¤°à¥\80à¤\95à¥\8dषित à¤ªà¤¨à¥\8dना à¤²à¥\81à¤\95à¥\81वाà¤\93",
-       "tog-extendwatchlist": "à¤\96ालà¥\80 à¤¹à¤¾à¤²à¤¿à¤\8f à¤\95य à¤¨à¤¾à¤¹à¥\80à¤\82, à¤¬à¤²à¥\8dà¤\95ि à¤\95à¥\81ल à¤¬à¤¦à¤²à¤¾à¤µ à¤\95य à¤¦à¥\87à¤\96ावà¥\87 à¤\95य à¤²à¤¿à¤\8f à¤§à¥\8dयानसà¥\82à¤\9aà¥\80 à¤\95य à¤µà¤¿à¤¸à¥\8dतारित à¤\95रà¥\8b",
-       "tog-usenewrc": "à¤\85भिन à¤\95य à¤¬à¤¦à¤²à¤¾à¤µ à¤®à¥\87 à¤\85à¤\89र à¤§à¥\8dयानसà¥\82à¤\9aà¥\80 à¤®à¥\87à¤\82 à¤¬à¤¦à¤²à¤¾à¤µ à¤\95य à¤ªà¤¨à¥\8dना à¤\95य à¤\85नà¥\81सार à¤¸à¤®à¥\82ह à¤®à¥\87à¤\82 à¤¬à¤¾à¤\81à¤\9fà¥\8b",
-       "tog-numberheadings": "शà¥\80रà¥\8dषà¤\95 à¤¸à¥\8dव-à¤\95à¥\8dरमाà¤\82à¤\95ित à¤\95रà¥\8b",
+       "tog-hideminor": "à¤\85बहिन à¤\95य à¤¬à¤¦à¤²à¤¾à¤µà¤®à¥\87à¤\82 à¤\9bà¥\8bà¤\9f à¤¬à¤¦à¤²à¤¾à¤µ à¤²à¥\81à¤\95à¥\81à¤\86वा à¤\9cाय",
+       "tog-hidepatrolled": "à¤\85बहिन à¤\95य à¤¬à¤¦à¤²à¤¾à¤µà¤®à¥\87à¤\82 à¤ªà¤°à¥\80à¤\95à¥\8dषित à¤¬à¤¦à¤²à¤¾à¤µ à¤²à¥\81à¤\95à¥\81à¤\86वा à¤\9cाय",
+       "tog-newpageshidepatrolled": "नवा à¤ªà¤¨à¥\8dनन à¤\95य à¤¸à¥\82à¤\9aà¥\80 à¤®à¥\87à¤\82 à¤ªà¤°à¥\80à¤\95à¥\8dषित à¤ªà¤¨à¥\8dना à¤²à¥\81à¤\95à¥\81à¤\86वा à¤\9cाय",
+       "tog-extendwatchlist": "à¤\96ालà¥\80 à¤¹à¤¾à¤²à¤¿à¤\8f à¤\95य à¤¨à¤¾à¤¹à¥\80à¤\82, à¤¬à¤²à¥\8dà¤\95ि à¤\95à¥\81ल à¤¬à¤¦à¤²à¤¾à¤µ à¤\95य à¤¦à¥\87à¤\96ावà¥\87 à¤\95य à¤²à¤¿à¤\8f à¤§à¥\8dयानसà¥\82à¤\9aà¥\80 à¤\95य à¤µà¤¿à¤¸à¥\8dतारित à¤\95रा à¤\9cाय",
+       "tog-usenewrc": "à¤\85भिन à¤\95य à¤¬à¤¦à¤²à¤¾à¤µ à¤®à¥\87 à¤\85à¤\89र à¤§à¥\8dयानसà¥\82à¤\9aà¥\80 à¤®à¥\87à¤\82 à¤¬à¤¦à¤²à¤¾à¤µ à¤\95य à¤ªà¤¨à¥\8dना à¤\95य à¤\85नà¥\81सार à¤¸à¤®à¥\82ह à¤®à¥\87à¤\82 à¤¬à¤¾à¤\81à¤\9fा à¤\9cाय",
+       "tog-numberheadings": "शà¥\80रà¥\8dषà¤\95 à¤¸à¥\8dव-à¤\95à¥\8dरमाà¤\82à¤\95ित à¤\95रा à¤\9cाय",
        "tog-showtoolbar": "सम्पादन औज़ारपट्टी देखावो",
-       "tog-editondblclick": "दà¥\81à¤\88 à¤\95à¥\8dलिà¤\95 à¤¸à¥\87 à¤ªà¤¨à¥\8dना à¤¸à¤\82पादित à¤\95रà¥\8b",
+       "tog-editondblclick": "दà¥\81à¤\88 à¤\95à¥\8dलिà¤\95 à¤¸à¥\87 à¤ªà¤¨à¥\8dना à¤¸à¤\82पादित à¤\95रा à¤\9cाय",
        "tog-editsectiononrightclick": "अनुभाग शीर्षक पे दायाँ क्लिक कई कय अनुभाग सम्पादित कीन जाय",
        "tog-watchcreations": "हमार बनावा पन्ना अव हमार अपलोड करल फाइल कय हमरे ध्यानसूची में जोडो",
        "tog-watchdefault": "हमार सम्पादन करल पन्ना अव फाइल कय ध्यानसूची में जोडो",
        "anontalk": "ई आइ॰पी कय खरतिन बातचीत",
        "navigation": "घुमाई",
        "and": "&#32;अउर",
-       "qbfind": "à¤\96à¥\8bà¤\9cà¥\8b",
+       "qbfind": "à¤\96à¥\8bà¤\9cा à¤\9cाय",
        "qbbrowse": "ब्राउज़",
        "qbedit": "सम्पादन",
        "qbpageoptions": "ई पन्ना",
        "qbmyoptions": "हमार पन्ना",
-       "faq": "बहुत  पूछ जाय वाला प्रश्न",
+       "faq": "बहुत  पूछ जाय वाला प्रश्न",
        "faqpage": "Project:ढेर पूछा जाय वाला सवाल",
        "actions": "काम कुल",
        "namespaces": "नामस्थान",
        "returnto": "$1 मे लौटो।",
        "tagline": "{{SITENAME}} से",
        "help": "मदद",
-       "search": "à¤\96à¥\8bà¤\9cà¥\8b",
-       "searchbutton": "à¤\96à¥\8bà¤\9cà¥\8b",
-       "go": "à¤\9cाà¤\93",
-       "searcharticle": "à¤\9cाà¤\93",
+       "search": "à¤\96à¥\8bà¤\9cा à¤\9cाय",
+       "searchbutton": "à¤\96à¥\8bà¤\9cा à¤\9cाय",
+       "go": "à¤\9cावा à¤\9cाय",
+       "searcharticle": "à¤\9cावा à¤\9cाय",
        "history": "पन्ना कय इतिहास",
        "history_short": "इतिहास",
        "updatedmarker": "हमरे अन्तिम दाँइ आवे कय बाद कय अपडेट",
        "edit-local": "स्थानीय विवरण सम्पादन",
        "create": "बनावो",
        "create-local": "स्थानीय विवरण जोडो",
-       "editthispage": "à¤\88 à¤ªà¤¨à¥\8dना à¤\95य à¤¸à¤®à¥\8dपादन à¤\95रà¥\8b",
-       "create-this-page": "à¤\88 à¤ªà¤¨à¥\8dना à¤¬à¤¨à¤¾à¤\93",
-       "delete": "मिà¤\9fाà¤\93",
-       "deletethispage": "à¤\88 à¤ªà¤¨à¥\8dना à¤®à¤¿à¤\9fाà¤\93",
-       "undeletethispage": "à¤\88 à¤ªà¤¨à¥\8dना à¤\95य à¤ªà¥\81नरà¥\8dसà¥\8dथापित à¤\95रà¥\8b।",
-       "undelete_short": "{{PLURAL:$1|à¤\8fà¤\95 à¤®à¥\87à¤\9fाà¤\88 à¤\97à¤\8f|$1 à¤®à¥\87à¤\9fाà¤\88 à¤\97à¤\8f}} बदलाव वापिस लाओ",
+       "editthispage": "à¤\88 à¤ªà¤¨à¥\8dना à¤\95य à¤¸à¤®à¥\8dपादन à¤\95रा à¤\9cाय",
+       "create-this-page": "à¤\88 à¤ªà¤¨à¥\8dना à¤¬à¤¨à¤¾à¤µà¤¾ à¤\9cाय",
+       "delete": "मिà¤\9fावा à¤\9cाय",
+       "deletethispage": "à¤\88 à¤ªà¤¨à¥\8dना à¤®à¥\87à¤\9fावा à¤\9cाय",
+       "undeletethispage": "à¤\88 à¤ªà¤¨à¥\8dना à¤\95य à¤ªà¥\81नरà¥\8dसà¥\8dथापित à¤\95रा à¤\9cाय।",
+       "undelete_short": "{{PLURAL:$1|à¤\8fà¤\95 à¤®à¥\87à¤\9fाà¤\88 à¤\97य}} बदलाव वापिस लाओ",
        "viewdeleted_short": "देखा जाय {{PLURAL:$1|एक मेटावल सम्पादन|$1 मेटावल सम्पादन}}",
-       "protect": "सà¥\81रà¤\95à¥\8dषित à¤\95रà¥\8b",
-       "protect_change": "बदलà¥\8b",
-       "protectthispage": "à¤\87 à¤ªà¤¨à¥\8dना à¤\95य à¤¸à¥\81रà¤\95à¥\8dषित à¤\95रà¥\8b",
+       "protect": "सà¥\81रà¤\95à¥\8dषित à¤\95रा à¤\9cाय",
+       "protect_change": "बदला à¤\9cाय",
+       "protectthispage": "à¤\87 à¤ªà¤¨à¥\8dना à¤\95य à¤¸à¥\81रà¤\95à¥\8dषित à¤\95रा à¤\9cाय",
        "unprotect": "असुरक्षित",
-       "unprotectthispage": "à¤\88 à¤ªà¤¨à¥\8dना à¤\95य à¤¸à¥\81रà¤\95à¥\8dषा à¤¸à¥\8dतर à¤¬à¤¦à¤²à¥\8b",
-       "newpage": "नवाà¤\81 पन्ना",
-       "talkpage": "à¤\88 à¤ªà¤¨à¥\8dना à¤\95य à¤¬à¤¾à¤°à¥\87 à¤®à¥\87 à¤\9aरà¥\8dà¤\9aा à¤\95रà¥\8b",
+       "unprotectthispage": "à¤\88 à¤ªà¤¨à¥\8dना à¤\95य à¤¸à¥\81रà¤\95à¥\8dषा à¤¸à¥\8dतर à¤¬à¤¦à¤²à¤¾ à¤\9cाय",
+       "newpage": "नà¤\81वा पन्ना",
+       "talkpage": "à¤\88 à¤ªà¤¨à¥\8dना à¤\95य à¤¬à¤¾à¤°à¥\87 à¤®à¥\87 à¤\9aरà¥\8dà¤\9aा à¤\95रा à¤\9cाय",
        "talkpagelinktext": "बातचीत",
        "specialpage": "विशेष पन्ना",
        "personaltools": "वैयक्तिक औज़ार",
-       "articlepage": "सामà¤\97à¥\8dरà¥\80 à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\8b",
+       "articlepage": "सामà¤\97à¥\8dरà¥\80 à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96ा à¤\9cाय",
        "talk": "चर्चा",
        "views": "दर्शाव",
        "toolbox": "साधन पेटी",
        "userpage": "सदस्य पन्ना देखो",
-       "projectpage": "परियà¥\8bà¤\9cना à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\8b",
-       "imagepage": "फ़ाà¤\87ल à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\8b",
-       "mediawikipage": "सनà¥\87शा à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\8b",
-       "templatepage": "साà¤\81à¤\9aा à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\8b",
-       "viewhelppage": "मदद à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96à¥\8b",
-       "categorypage": "शà¥\8dरà¥\87णà¥\80 à¤ªà¤¨à¥\8dना  à¤¦à¥\87à¤\96à¥\8b",
-       "viewtalkpage": "à¤\9aरà¥\8dà¤\9aा à¤¦à¥\87à¤\96à¥\8b",
+       "projectpage": "परियà¥\8bà¤\9cना à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96ा à¤\9cाय",
+       "imagepage": "फ़ाà¤\87ल à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96ा à¤\9cाय",
+       "mediawikipage": "सनà¥\87शा à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96ा à¤\9cाय",
+       "templatepage": "साà¤\81à¤\9aा à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96ा à¤\9cाय",
+       "viewhelppage": "मदद à¤ªà¤¨à¥\8dना à¤¦à¥\87à¤\96ा à¤\9cाय",
+       "categorypage": "शà¥\8dरà¥\87णà¥\80 à¤ªà¤¨à¥\8dना  à¤¦à¥\87à¤\96ा à¤\9cाय",
+       "viewtalkpage": "à¤\9aरà¥\8dà¤\9aा à¤¦à¥\87à¤\96ा à¤\9cाय",
        "otherlanguages": "अउर भाषा सब",
        "redirectedfrom": "($1 से पुनर्निर्देशित)",
        "redirectpagesub": "पुनर्निर्देश पन्ना",
        "redirectto": "पुनर्निर्देश करो:",
        "lastmodifiedat": "इ पन्ना कय पिछला बदलाव $1 कय $2 बजे भवा रहा।",
+       "viewcount": "ई पन्ना {{PLURAL:$1|एक|$1}} दाइँ देख़ गा है।",
        "protectedpage": "सुरक्षित पन्ना",
-       "jumpto": "यहà¤\81 à¤\9cाà¤\93:",
+       "jumpto": "यहà¤\81 à¤\9cावा à¤\9cाय:",
        "jumptonavigation": "घुमाई",
-       "jumptosearch": "à¤\96à¥\8bà¤\9cà¥\8b",
+       "jumptosearch": "à¤\96à¥\8bà¤\9cा à¤\9cाय",
        "view-pool-error": "क्षमा करा जाय, यह समय सर्वर पे ढेर बोझ है।\nबहुत ढेर प्रयोक्ता लोग इ पन्ना कय देखेक प्रयास करत हँय।\nतनी कुछ समय अगोरिकय फिर से इ पन्ना कय देखेक प्रयास करा जाय।\n\n$1",
        "generic-pool-error": "क्षमा करा जाय, यह समय सर्वर पे ढेर बोझ है।\nबहुत ढेर प्रयोक्ता लोग इ चिज कय देखेक प्रयास करत हँय।\nतनी कुछ समय अगोरिकय फिर से इ चिज कय देखेक प्रयास करा जाय।\n\n$1",
        "pool-timeout": "तालाबन्दी कय लिए अगोरे कय समय खतम",
        "youhavenewmessagesmulti": "$1 पे आप कय खरतिन नवाँ सनेशा है",
        "editsection": "सम्पादन",
        "editold": "सम्पादन",
-       "viewsourceold": "सà¥\8dरà¥\8bत à¤¦à¥\87à¤\96à¥\8b",
+       "viewsourceold": "सà¥\8dरà¥\8bत à¤¦à¥\87à¤\96ा à¤\9cाय",
        "editlink": "सम्पादन",
-       "viewsourcelink": "सà¥\8dरà¥\8bत à¤¦à¥\87à¤\96à¥\8b",
+       "viewsourcelink": "सà¥\8dरà¥\8bत à¤¦à¥\87à¤\96ा à¤\9cाय",
        "editsectionhint": "अनुभाग सम्पादन: $1",
        "toc": "विषय सूची",
        "showtoc": "देखाओ",
        "nosuchaction": "अईसन कवनो काम नाई है",
        "nosuchactiontext": "इ यू॰आर॰एल से निर्दिष्ट काम अवैध है।\nआप यू॰आर॰एल गलत लिखा गा है, या कवनो गलत कड़ी कय प्रयोग करा गा है।\nई {{SITENAME}} कय सॉफ़्टवेयर में त्रुटि भी होई सकत है।",
        "nosuchspecialpage": "अईसन कौनो विशेष पन्ना नाई है",
+       "nospecialpagetext": "<strong>आप  अवैध विशेष पन्ना माँगा गा है।</strong>\nवैध विशेष पन्नन कय सूची [[Special:SpecialPages|{{int:specialpages}}]] पे देखी सका जात है।",
        "error": "त्रुटि",
        "databaseerror": "डाटाबेस त्रुटि",
        "databaseerror-text": "डाटाबेस अनुरोध त्रुटि हुई है।\nसंभवतः सॉफ़्टवेयर में गड़बड़ी है।",
        "perfcached": "नीचे दिया हुआ डेटा कैशे मेमोरी से लिया हुआ है, अतः हो सकता है कि इसका पूर्ण अद्यतन न हुआ हो। कैशे मेमोरी में अधिकतम {{PLURAL:$1|एक  नतीजा|$1 नतीजे}} उपलब्ध हैं।",
        "perfcachedts": "नीचे दिया हुआ डेटा कैशे मेमोरी से है, और इसका अंतिम अद्यतन $1 को हुआ था। कैशे मेमोरी में अधिकतम {{PLURAL:$4|एक  नतीजा|$4 नतीजे}} उपलब्ध हैं।",
        "querypage-no-updates": "इस पृष्ठ का नवीनीकरण करना मना है। अभी यहाँ के डाटा को ताज़ा नहीं कर सकते।",
-       "viewsource": "सà¥\8dरà¥\8bत à¤¦à¥\87à¤\96à¥\8b",
-       "viewsource-title": "$1 à¤\95य à¤²à¤¿à¤\8f à¤¸à¥\8dरà¥\8bत à¤¦à¥\87à¤\96à¥\8b",
+       "viewsource": "सà¥\8dरà¥\8bत à¤¦à¥\87à¤\96ा à¤\9cाय",
+       "viewsource-title": "$1 à¤\95य à¤²à¤¿à¤\8f à¤¸à¥\8dरà¥\8bत à¤¦à¥\87à¤\96ा à¤\9cाय",
        "actionthrottled": "काम खतम कई दिहा है",
+       "actionthrottledtext": "स्पैम कय रोकेक् लिये, इ काम एतना कम समय में एकठु सीमा से ढेर दाँइ करे कय मिनाही है, अव आप इ सीमा कय पार कई चुका गा है।\nकृपया कुछ समय बाद फिर से प्रयास करा जाय।",
        "protectedpagetext": "ई पन्ना संपादन अव अउर काम से सुरक्षित किहा है।",
        "viewsourcetext": "आप इ पन्ना कय स्रोत देखी सका जात है औ ओकर नकल उतार सका जात है:",
        "viewyourtext": "आप ई पन्ना में ''आपन सम्पादन'' कय स्रोत देखी सका जात है औ ओकर नकल उतार सका जात है:",
+       "protectedinterface": "इ पन्ना  विकी कय सॉफ़्टवेयर कय इंटरफ़ेस पाठ देत है,अव एकर गलत प्रयोग से बचावेक लिये सुरक्षित करा है।\nकुल विकिन् कय लिए अनुवाद जोड़य या बदलय कय लिए कृपया मीडियाविकि कय क्षेत्रीयकरण प्रकल्प [//translatewiki.net/ translatewiki.net] कय प्रयोग करा जाय।",
        "namespaceprotected": "आप कय '''$1''' नामस्थान में रहल पन्नन कय बदलै कय अनुमति नाइ है।",
        "customcssprotected": "आप कय इ CSS पन्ना कय संपादन करेक अनुमति नाई है, काहे से एहमा अउर सदस्य कय व्यक्तिगत सेटिंग्स शामिल है।",
        "customjsprotected": "आप कय इ जावास्क्रिप्ट पन्ना कय संपादन करेक अनुमति नाई है, काहे से एहमा अउर सदस्य कय व्यक्तिगत सेटिंग्स शामिल है।",
        "userloginnocreate": "लॉग इन",
        "logout": "बहरे निकरो",
        "userlogout": "बहरे निकरो",
-       "notloggedin": "लà¥\89à¤\97 à¤\87न à¤¨à¤¾à¤\87 à¤\95रà¥\87 à¤¹à¤µ",
+       "notloggedin": "लà¥\89à¤\97 à¤\87न à¤¨à¤¾à¤\87 à¤\95रा à¤\97ा à¤¹à¥\88",
        "userlogin-noaccount": "खाता नाइ है?",
        "userlogin-joinproject": "{{SITENAME}} से जुडव",
        "nologin": "का आप सदस्यता नाई लीहे हव? '''$1'''।",
        "createacct-emailoptional": "ई-मेल ठाँव (वैकल्पिक)",
        "createacct-email-ph": "आपन ई-मेल ठाँव लिखा जाय",
        "createacct-another-email-ph": "ईमेल ठाँव दिहा जाय",
+       "createaccountmail": "एकठु अस्थायी मनलागा (रैंडम) गुप्त कुंजी चुना जाय अउर ओका निर्दिष्ट ई-मेल ठहर पे भेजा जाय",
        "createacct-realname": "असली नावँ (वैकल्पिक)",
        "createaccountreason": "कारण:",
        "createacct-reason": "कारण",
        "wrongpasswordempty": "गुप्त कुंजी खाली है।\nफिरसे लिखो।",
        "passwordtooshort": "आप कय गुप्त कुंजी  कम से कम {{PLURAL:$1|1 अक्षर|$1 अक्षरन्}} कय होएक चाहि।",
        "password-name-match": "आप कय गुप्त कुंजी आप कय सदस्यनावँ से फरक होएक चाहि।",
+       "password-login-forbidden": "इ सदस्यनाँव अउर गुप्त कुंजी कय उपयोग नाई कै सका जात अहै।",
        "mailmypassword": "गुप्त कुंजी पुनःस्थापित करा जाय",
        "passwordremindertitle": "{{SITENAME}} कय लिए नवाँ अस्थाई गुप्त कुंजी",
        "noemail": "\"$1\" सदस्य कय लिये कवनो भी ई-मेल पता दर्ज नाइ कई गा है।",
        "noemailcreate": "आप कय असली ई-मेल ठाँव देक परि।",
        "passwordsent": "\"$1\" कय ई-मेल ठाँव पे एक नवाँ गुप्त कुंजी भेजि गा है।\nई-मेल पावेक बाद कृपया दुबारा लॉग इन करा जाई।",
        "blocked-mailpassword": "आप कय आइ॰पी ठाँव कय सम्पादन करे से अवरुद्ध कई गा है, अउर गलत इस्तेमाल रोकेक लिये गुप्त कुंजी फिरसे पावे कय सुविधा इ आइ॰पी पे बंद कई गा है।",
+       "eauthentsent": "दर्ज करल ई-मेल ठहर पे एकठु फुरवासाखी ई-मेल भेज दिहा गा है।\nआप का उ ई-मेल में दिहा निर्देशन् कय अनुसार ई-मेल ठहर कय सत्यापन करेक परि,ओकरे बादय ही हिँया से कवनो दूसर ई-मेल भेज जाई।",
+       "mailerror": "ई-मेल भेजय में त्रुटि: $1",
+       "acct_creation_throttle_hit": "आप कय आइ॰पी ठहर से आवे वाले मनई लोग पिछला चौबीस घंटन् में इ विकि पे {{PLURAL:$1|एक खाता|$1 खाता}} बनाई चुका हैं, इ समयावधि में ई अधिकतम सीमा होय।\n यह समय इ आइ॰पी  कय प्रयोग करय वाले आगंतुक अउर खाता नाइ खोल सकत हैं।",
+       "emailauthenticated": "आप कय ई-मेल ठहर $2 कय $3 बजे सत्यापित कै गय।",
+       "emailconfirmlink": "आपन ई-मेल ठहर निश्चित करा जाय",
+       "invalidemailaddress": "ई-मेल ठहर नाई मानी जाई काहे से ई कवनो अवैध स्वरूप में है।\nकृपया एक सही तरीका से स्वरूपित ई-मेल ठहर दिहा जाय या उ कोष्ठक कय खालीय छोड दिहा जाय।",
+       "cannotchangeemail": "इस विकी पे सदस्य खाता कय ई-मेल ठहर नाइ बदल सका जात अहै।",
+       "emaildisabled": "ई साइट ई-मेल नाइ भेज सकत अहै।",
+       "accountcreated": "खाता बनी गवा है",
+       "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|बातचीत]]) कय लिये खाता बनाइ दिहा है।",
+       "createaccount-title": "{{SITENAME}} के लिये खाता बनावा जाय",
+       "login-throttled": "आप अबहिनय में कयु दाँइ लॉग इन करेक प्रयास किहा गा है।\nफिरसे प्रयास करय से पहीले तनी $1 रुका जाय।",
+       "login-abort-generic": "आप कय लाग-इन असफल रहा - निष्फलित",
        "loginlanguagelabel": "भाषा: $1",
        "createacct-another-realname-tip": "असली नाँव देब आवश्यक नाई है।\nयदि आप देवा जाई तव एकर प्रयोग सदस्यन् कय योगदान कय लिये श्रेय (attribution) देक लिये कई जाई।",
        "pt-login": "लॉग इन",
        "pt-createaccount": "खाता बनावा जाय",
        "pt-userlogout": "बहरे निकरा जाय",
        "php-mail-error-unknown": "PHP कय mail() फ़ंक्शन में अज्ञात त्रुटि होई गवा।",
+       "user-mail-no-addy": "ई-मेल ठहर कय बिना ई-मेल भेजय कय कोशिश कीहा गय।",
+       "user-mail-no-body": "एकठु खाली या बहुत छोट ई-मेल भेजय कय कोशिश कई गा है।",
        "changepassword": "गुप्त कुंजी बदला जाय",
        "resetpass_announce": "लॉग इन पुरा करेक लिये आप कय एक नँवा गुप्त कुंजी (पासवर्ड) देक परि।",
        "resetpass_header": "खाता कय गुप्त कुंजी बदला जाय",
        "retypenew": "गुप्तकुंजी एक दाँइ अउर लिखा जाय:",
        "resetpass_submit": "गुप्तकुंजी लिखा जाए अव लॉग इन करा जाय",
        "changepassword-success": "आप कय गुप्तकुंजी बदल़ी गय!",
+       "changepassword-throttled": "आप अबहिनय में कयु दाँइ लॉग इन करेक प्रयास किहा गा है।\nफिरसे प्रयास करय से पहीले तनी $1 रुका जाय।",
        "resetpass_forbidden": "गुप्तकुंजी नाइ बदल़ सका जात है",
        "resetpass-no-info": "इ पन्ना कय सीधय प्रयोग करेक लिए आप कय लॉग इन करेक परि।",
        "resetpass-submit-loggedin": "गुप्तकुंजी बदला जाय",
        "resetpass-submit-cancel": "रद्द करा जाय",
        "resetpass-wrong-oldpass": "अवैध अस्थायी या वर्तमान गुप्तकुंजी।\nसंभव है कि या तो आप पहिलवे सफलतापूर्वक आपन कूटशब्द बदल लिहा गा है , या आपन एक नवा अस्थायी गुप्तकुंजी कय अनुरोध किहा गा है।",
        "resetpass-recycled": "रीसेट करेक लिए नवा पासवर्ड में कृपया आपन वर्तमान पासवर्ड कय अलावा कवनो दुस़र पासवर्ड कय प्रयोग करा जाय।",
+       "resetpass-temp-emailed": "आप एकठु अस्थायी ईमेल करल कोड कय साथे लॉग इन किहा गय।\nलॉग इन पुरा करेक लिए आप कय हिँया एकठु नँवा पासवर्ड सेट करेक परि:",
        "resetpass-temp-password": "अस्थायी गुप्तकुंजी:",
        "resetpass-abort-generic": "गुप्तकुंजी में बदलाव कवनो एक्सटेंशन से रुकि गवा है।",
+       "resetpass-expired": "आप कय पासवर्ड कय वैधता अवधि खतम होई चुका है। कृपया लॉग इन करेक लिए एकठु नँवा पासवर्ड सेट करा जाय।",
+       "resetpass-expired-soft": "आप कय पासवर्ड कय वैधता समय होइ गवा है अव ओका रीसेट करेक ज़रूरत है। कृपया एकठु नँवा पासवर्ड चुना जाय, या बाद में रीसेट करेक लिए \"{{int:resetpass-submit-cancel}}\" पे क्लिक करा जाय।",
        "resetpass-validity-soft": "आप कय पासवर्ड मान्य नाई है: $1 \n\nकृपया अब एक नवा पासवर्ड चुना जाय, या ओका बाद में पुनर्स्थापित करेक लिए \"{{int:resetpass-submit-cancel}}\" पे क्लिक करा जाय।",
        "passwordreset": "गुप्त कुंजी पुनःस्थापित(रीसेट) करा जाय",
        "passwordreset-text-one": "आपन गुप्तकुंजी रीसेट करेक लिए ई फ़ॉर्म भरा जाय।",
        "resettokens-token-label": "$1 (वर्तमान मूल्य: $2)",
        "resettokens-watchlist-token": "[[Special:Watchlist|आप कय ध्यानसूची कय पन्नन् में बदलाव]] कय वेब फ़ीड (Atom/RSS)कय नाते टोकन",
        "resettokens-done": "टोकन रीसेट कई गय।",
+       "resettokens-resetbutton": "चुनल टोकन रीसेट करा जाय",
        "bold_sample": "मोट लेख",
        "bold_tip": "मोट लेख",
        "italic_sample": "तिरछा लेख",
        "headline_sample": "शीर्षक लेख",
        "headline_tip": "द्वितीय-स्तर शीर्षक",
        "nowiki_sample": "अप्रारूपित लेख यहँ डारा जाय",
+       "nowiki_tip": "विकि प्रारूपण नज़रंदाज़ करा जाय",
+       "image_tip": "एम्बेड करल फ़ाइल",
        "media_tip": "फ़ाइल कय कड़ी",
        "sig_tip": "आप कय हस्ताक्षर अव समय",
        "hr_tip": "सिधा लाइन (कम इस्तेमाल करा जाई)",
        "whitelistedittext": "पन्ना संपादन करेक लिये आप कय $1 करेक परि।",
        "confirmedittext": "संपादन करय से पहिले आपन ई-मेल प्रमाणित करब आवश्यक है।\nकृपया आपन [[Special:Preferences|सदस्य वरीयता]] में जाईकय आपन ई-मेल ठाँव दिहा जाय अव ओका प्रमाणित करा जाय।",
        "nosuchsectiontitle": "अईसन कवनो अनुभाग शीर्षक नाई है",
+       "nosuchsectiontext": "आप अईसन अनुभाग कय सम्पादन करेक प्रयास करा जात है जवन अस्तित्व में नाई है।\nसंभव है कि जब आप पन्ना पढ़ा जात रहा तब ओका अपने जगह से हिलावा रहा गय या तो हटाई दिहा गा है।",
        "loginreqtitle": "लॉग इन आवश्यक है",
        "loginreqlink": "लॉग इन",
        "loginreqpagetext": "अउर पन्ना देखेक लिये आप कय $1 करब आवश्यक है।",
        "accmailtitle": "गुप्तकुंजी भेजी गय।",
+       "accmailtext": "[[User talk:$1|$1]] कय लिए एक यंत्र जनित गुप्त कुंजी $2 कय भेज दिहा गा है। लॉगिन करेक बाद एका '''[[Special:ChangePassword|गुप्त कुंजी बदला जाय]]'' वाला पन्नन् पे बदल सका जात है।",
        "newarticle": "(नँवा)",
+       "newarticletext": "आप अईसन पन्ना पे आवा गा है जवन अभीन तक नाई बनावा है।\nपन्ना बनावेक लिये नीचे कय बौक्स में पाठ लिखा जाय। ढेर जानकारी कय लिये [$1 सहायता पन्ना] देखा जाय।\nअगर आप हिँया गलती से आवा गा हैं तव आपन ब्राउज़र कय बैक ('''back''') बटन पे क्लिक करा जाय।",
+       "noarticletext": "अभीन इ पन्ना पे कवनो सामग्री नाई है।\nआप अउर पन्नन् में [[Special:Search/{{PAGENAME}}|इ शीर्षक कय खोज]] कई सका जात है,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} सम्बन्धित लॉग खोज सका जात है],\nया इस पृष्ठ को [{{fullurl:{{FULLPAGENAME}}|action=edit}} सम्पादित] कर सकते हैं</span>।",
+       "userpage-userdoesnotexist": "सदस्य खाता \"$1\" पंजीकृत नाई है।\nकृपया जाँच लिहा जाय कि आप ई पन्ना संपादन करय या बनावे चाहा जात है या नाहीं।",
        "userpage-userdoesnotexist-view": "सदस्य \"$1\" पंजीकृत नाइ है।",
+       "blocked-notice-logextract": "ई सदस्य अभीन अवरोधित है।\nसदंर्भ कय लिए ताज़ातरीन अवरोध लॉग प्रविष्टि नीचा दीहा है:",
        "updated": "(अपडेट करल)",
        "note": "'''सूचना:'''",
        "previewnote": "'''याद रख्खा जाय, ई खाली एक झलक होय।'''\nआप कय बदलाव अभीन तक नाई सहेजा हैं!",
        "content-model-javascript": "जावास्क्रिप्ट",
        "content-json-empty-object": "खाली चिज",
        "content-json-empty-array": "खाली एरे",
+       "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|बातचीत]]) कय करल बदलाव $1 कय पहिले जईसन कई गय",
+       "undo-summary-username-hidden": "लुकुआवल सदस्यन् कय करल बदलाव $1 कय पहिले जईसन कई गय",
        "cantcreateaccounttitle": "खाता नाई खोली सका जात है",
+       "cantcreateaccount-range-text": "'''$1''' कय श्रेणी में आवे वाला आई॰पी ठहर से, जवनेमें आप कय आई॰पी ठहर ('''$4''') शामिल है, नँवा खाता बनावे कय लिए [[User:$3|$3]] अवरोधित कई गा है। \n\n$3 द्वारा दिया गया कारण है: \"$2\"",
        "viewpagelogs": "इस पन्ना कय लॉग देखा जाय",
        "nohistory": "इ पन्ना कय कवनो इतिहास नाई है।",
        "currentrev": "अभिनै कय अवतरण",
        "history-feed-title": "अवतरण इतिहास",
        "history-feed-description": "विकि मे उपलब्ध इ पन्ना कय अवतरण इतिहास",
        "history-feed-item-nocomment": "$1 $3 कय $4 बजे",
+       "history-feed-empty": "अनुरोधित करल पन्ना  अस्तित्व में नाई है।\nई पन्ना या तो मेटावा है या फिर एकर नाँव बदल दिहा है।\n[[Special:Search|विकि पे खोजा जाय]] कय प्रयोग करा जाय।",
        "rev-deleted-comment": "(सम्पादन सारांश हटाई गय)",
        "rev-deleted-user": "(सदस्यनाँव हटाई गय)",
+       "rev-deleted-user-contribs": "[सदस्यनाँव या आइ॰पी ठहर लुकुआई गय- सम्पादन योगदान में से लुकुआई गय]",
+       "rev-deleted-text-permission": "ई पन्ना अवतरण हटाई गा है।\nएकर ढेर जानकारी [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} हटावे कय लॉग] में मिली सकत है।",
+       "rev-deleted-text-unhide": "ई पन्ना अवतरण हटाई गा है।\nएकर ढेर जानकारी [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} हटावे कय लॉग] में मिली सकत है।\nयदि आप चाहा जाय तव ई अवतरण कय [$1 देख सका जात है] ।",
+       "rev-suppressed-text-unhide": "ई पन्ना अवतरण लुकुआइ गा है।\nएकर ढेर जानकारी [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} लुकुआवे कय लॉग] में मिली सकत है।\nयदि आप चाहा जाय तव ई अवतरण कय [$1 देख सका जात है] ।",
+       "rev-deleted-text-view": "ई पन्ना कय अवतरण हटाई गा है।\nएकर ढेर जानकारी [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} हटावे कय लॉग] में मिली सकत है।",
+       "rev-suppressed-text-view": "ई पन्ना अवतरण लुकुआइ गा है।\nएकर ढेर जानकारी [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} हटावे कय लॉग] में मिली सकत है।",
+       "rev-deleted-no-diff": "आप ई अंतर कय नाइ देख सका जात है काहे से एहमा से एकठु अवतरण '''लुकुआवा है'''।\nविवरण [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} हटावे कय लॉग] में मिली सकत है।",
        "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-deleted-diff-view": "ई अंतर मे से एकठु अवतरण हटावा है।\nएकर ढेर जानकारी [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} हटावे कय लॉग] में मिली सकत है।",
+       "rev-suppressed-diff-view": "ई अंतर मे से एक्ठु अवतरण लुकुआवा है।\nएकर ढेर जानकारी [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} हटावे कय लॉग] में मिली सकत है।",
        "rev-delundel": "देखावा जाय/लुकुआवा जाय",
        "rev-showdeleted": "देखावा जाय",
        "revisiondelete": "अवतरण हटावा जाय/पुनर्स्थापित करा जाय",
        "revdelete-nooldid-title": "अमान्य लक्ष्य अवतरण",
+       "revdelete-nooldid-text": "इस क्रिया को करने के लिये आपने लक्ष्य अवतरण नहीं दिये हैं, या फिर आपने दिया हुआ अवतरण अस्तित्व में नहीं हैं या फिर आप सद्य अवतरण को छुपाने का प्रयत्न कर रहे हैं।",
        "revdelete-no-file": "निर्दिष्ट फ़ाइल मौजूद नाई है।",
+       "revdelete-show-file-confirm": "का आप सही में फ़ाइल \"<nowiki>$1</nowiki>\" कय $2 कय $3 बजे बना, हटावल अवतरण कय देखय चाहा जात है?",
        "revdelete-show-file-submit": "हाँ",
        "revdelete-selected-text": "[[:$2]] {{PLURAL:$1|कय}} चयनित अवतरण:",
        "revdelete-selected-file": "[[:$2]] {{PLURAL:$1|कय}} चयनित फ़ाइल अवतरण:",
        "revdelete-unsuppress": "पुनर्स्थापित अवतरणन् पे से प्रतिबन्ध हटावा जाय",
        "revdelete-log": "कारण:",
        "revdelete-submit": "चयनित {{PLURAL:$1|अवतरण}} पे लागू करा जाय",
+       "logdelete-success": "'''लॉग दृष्यता बदलि गय।'''",
+       "logdelete-failure": "'''लॉग दृश्यता कय जमाव नाई भय:'''\n$1",
        "revdel-restore": "देखावा जाय/लुकुआवा जाय",
        "pagehist": "पन्ना कय इतिहास",
        "deletedhist": "मेटावल इतिहास",
+       "revdelete-hide-current": "$2 कय, $1 बजे वाला मद नाई लुकुवाई गय: ई सबसे ताज़ा अवतरण होय।\nई नाइ लुकुआई सका जात है।",
        "revdelete-otherreason": "अउर/दुसर कारण:",
        "revdelete-reasonotherlist": "दुसर कारण",
        "revdelete-edit-reasonlist": "हटावेक कारण बदला जाय",
        "mergehistory-reason": "कारण:",
        "mergelog": "मिलावेक लॉग",
        "revertmerge": "अलग करा जाअ",
+       "history-title": "\"$1\" कय अवतरण इतिहास",
+       "difference-title": "\"$1\" कय अवतरण में अंतर",
+       "difference-title-multipage": "\"$1\" अव \"$2\" पन्नन में अंतर",
+       "difference-multipage": "(पन्नन कय बीच अन्तर)",
+       "lineno": "पंक्ति $1:",
+       "compareselectedversions": "चुनल अवतरणन् कय तुलना करा जाय",
+       "showhideselectedversions": "चुनल अवतरण देखावा जाय/लुकुआवा जाय",
+       "editundo": "पहिले जैसन करा जाय",
+       "diff-empty": "(कवनो अंतर नाइ है)",
+       "diff-multi-sameuser": "(इ सदस्य कय {{PLURAL:$1|करल बीच कय एक अवतरण नाई देखाई गय |करल बीच कय कुल $1 अवतरण नाइ देखाइ गय}})",
+       "diff-multi-otherusers": "({{PLURAL:$2|एकठु दुसर सदस्य|$2 सदस्यन्}} कय {{PLURAL:$1|करल  बीच कय एकठु अवतरण नाई देखाइ गय|करल बीच कय कुल $1 अवतरण नाइ देखाइ गय}})",
+       "diff-multi-manyusers": "({{PLURAL:$2|एकठु योगदानकर्ता|$2 योगदानकर्तन्}} कय {{PLURAL:$1|करल बीच कय एकठु|करल बीच कय $1}} अवतरण नाई देखाइ गय।)",
+       "difference-missing-revision": "इ अंतर {{PLURAL:$2|कय एकठु अवतरण|कय $2 अवतरण}} ($1) नाइ {{PLURAL:$2|मिला}}।\n\nई आम तौर पे एकठु हटावल पन्ना कय अवतरण में अंतर खोजय पे होत है।ढेर जानकारी [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} हटावे कय लॉग] में मिली।",
+       "searchresults": "खोज परिणाम",
+       "searchresults-title": "\"$1\" कय खरतीन खोज परिणाम",
+       "titlematches": "पन्ना शीर्षक मिलान",
+       "textmatches": "पन्ना पाठ मिलान",
+       "notextmatches": "कवनो भी पन्ना में ई सामान नाई मिला",
+       "prevn": "पहिलका {{PLURAL:$1|$1}}",
+       "nextn": "अगला {{PLURAL:$1|$1}}",
+       "prevn-title": "{{PLURAL:$1|पहिलका|}} $1 परिणाम",
+       "nextn-title": "{{PLURAL:$1|अगला}} $1 परिणाम",
+       "shown-title": "हर पन्ना पे $1 {{PLURAL:$1|परिणाम}} देखावा जाय",
+       "viewprevnext": "देखा जाय ($1 {{int:pipe-separator}} $2) ($3)",
+       "searchmenu-exists": "'''इ विकि पे \"[[:$1]]\" नाँव कय एकठु पन्ना है'''",
+       "searchmenu-new": "<strong>इ विकि पे \"[[:$1]]\" नाँव कय पन्ना बनावा जाय!</strong>{{PLURAL:$2|0=|आप कय खोज से मिला पन्नओ देखा जाय।|खोज परिणाम भी देखा जाय।}}",
+       "searchprofile-articles": "सामग्री पन्ना",
+       "searchprofile-images": "मल्टीमीडिया",
+       "searchprofile-everything": "कुल चिज",
+       "searchprofile-advanced": "उन्नत",
+       "searchprofile-articles-tooltip": "$1 में खोजा जाय",
+       "searchprofile-images-tooltip": "फ़ाइल खोजा जाय",
+       "searchprofile-everything-tooltip": "(बातचीत पन्नन सहित) सारा सामग्री में खोजा जाय",
+       "searchprofile-advanced-tooltip": "विशेष नामस्थानन् में खोजा जाय",
+       "powersearch-ns": "नामस्थानन् में खोजा जाय:",
+       "powersearch-togglelabel": "चुना जाय:",
+       "powersearch-toggleall": "कुल",
+       "powersearch-togglenone": "केहु नाई",
+       "search-external": "बाहरी खोज",
+       "preferences": "प्राथमिकता",
+       "mypreferences": "प्राथमिकता",
+       "prefs-edits": "सम्पादन गिन्ती",
+       "prefs-skin": "स्कीन",
+       "skin-preview": "झलक",
+       "datedefault": "खा़स प्राथमिकता नाँइ है",
+       "prefs-labs": "लैब विशेषता",
+       "prefs-user-pages": "सदस्य पन्ना",
+       "prefs-personal": "सदस्य व्यक्तिरेखा",
+       "prefs-rc": "अबहिन कय बदलाव",
+       "prefs-watchlist": "अवलोकन सुची",
+       "prefs-watchlist-days": "ध्यानसूची में दिखावै कय दिन:",
+       "prefs-watchlist-days-max": "अधिकतम $1 {{PLURAL:$1|दिन}}",
+       "prefs-watchlist-edits-max": "अधिकतम संख्या: एक हज़ार",
+       "prefs-watchlist-token": "ध्यानसूची टोकन",
+       "prefs-misc": "अउर",
+       "prefs-resetpass": "गुप्त कुंजी बदला जाय",
+       "prefs-changeemail": "ईमेल ठाँव बदला जाय",
+       "prefs-setemail": "ईमेल ठाँव दिहा जाय",
+       "prefs-email": "ई-मेल वरीयता",
+       "prefs-rendering": "शकलसूरत",
+       "saveprefs": "सहेजा जाय",
+       "prefs-editing": "संपादन होत है",
+       "rows": "कताँर:",
+       "columns": "कॉलम:",
+       "searchresultshead": "खोजा जाय",
+       "stub-threshold-disabled": "अक्षम करा है",
+       "timezonelegend": "समयमंडल:",
+       "localtime": "स्थानीय समय:",
+       "servertime": "सर्वर कय समय:",
+       "timezoneregion-africa": "अफ्रिका",
+       "timezoneregion-america": "अमेरिका",
+       "timezoneregion-antarctica": "अंटार्कटिका",
+       "timezoneregion-arctic": "आर्कटिक",
+       "timezoneregion-asia": "एशिया",
+       "timezoneregion-atlantic": "एटलांटिक महासागर",
+       "timezoneregion-australia": "ऑस्ट्रेलिया",
+       "timezoneregion-europe": "यूरोप",
+       "timezoneregion-indian": "हिंद महासागर",
+       "timezoneregion-pacific": "प्रशांत महासागर",
+       "prefs-searchoptions": "खोजा जाय",
+       "prefs-namespaces": "नामस्थान",
+       "default": "डिफ़ॉल्ट",
+       "prefs-files": "फ़ाइल",
+       "prefs-custom-css": "खासमखास सी॰एस॰एस",
+       "prefs-custom-js": "खासमखास जावास्क्रिप्ट",
+       "prefs-common-css-js": "कुल स्किन कय लिए साझा सी॰एस॰एस/जावास्क्रिप्ट:",
+       "youremail": "ई-मेल:",
+       "username": "{{GENDER:$1|सदस्यनाँव}}:",
+       "prefs-registration": "रजिष्ट्रेसन समय:",
+       "yourrealname": "वास्तविक नाँव:",
+       "yourlanguage": "भाषा",
+       "yourvariant": "सामग्री भाषा संस्करण:",
+       "yournick": "नँवा हस्ताक्षर:",
+       "prefs-help-signature": "बातचीत पन्नन पे करल टिप्पणिन् पे \"<nowiki>~~~~</nowiki>\" से हस्ताक्षर करेक परि, इ आप कय हस्ताक्षर अव समय में परिवर्तित होई जाइ।",
+       "badsig": "गलत कच्चा हस्ताक्षर।\nHTML टैग कय जाँच करा जाय।",
+       "badsiglength": "ई हस्ताक्षर बहुत बड़ा है।\nई $1 {{PLURAL:$1|कैरैक्टर}} से ढेर कय नाई होएक चाहि।",
+       "yourgender": "आप अपने आप कय कैसन बतावे चाहा जाइ?",
+       "gender-unknown": "हम कुछ नाई कहय चाहित अहन",
+       "gender-male": "एन सम्पादन करत हँय।",
+       "gender-female": "एन सम्पादन करत अहिन।",
+       "prefs-help-gender": "ई जानकारी देब वैकल्पिक होय।\nई सॉफ़्टवेयर में लिंग कय आधार पे आप कय लिए सही संबोधन कय नाते प्रयुक्त होत है।\nई जानकारी सार्वजनिक होइ।",
+       "email": "ई-मेल",
+       "prefs-help-email": "ई-मेल ठहर वैकल्पिक होय, लेकिन यदि आप आपन गुप्तकुंजी भूलाई गवा गय तव एकरे माध्यम से रीसेट कई सका जात है।",
+       "prefs-help-email-required": "ई-मेल ठहर जरुरी है।",
+       "prefs-info": "मूलभूत जानकारी",
+       "prefs-i18n": "अंतर्राष्ट्रीयकरण",
+       "prefs-signature": "हस्ताक्षर",
+       "prefs-dateformat": "तिथि प्रारूप",
+       "prefs-timeoffset": "समयांतर",
+       "prefs-advancedediting": "सामान्य विकल्प",
+       "prefs-editor": "सम्पादक",
+       "prefs-preview": "झलक",
+       "prefs-advancedrc": "उन्नत विकल्प",
+       "prefs-advancedrendering": "उन्नत विकल्प",
+       "prefs-advancedsearchoptions": "उन्नत विकल्प",
+       "prefs-advancedwatchlist": "उन्नत विकल्प",
+       "prefs-displayrc": "प्रदर्शन विकल्प",
+       "prefs-displaywatchlist": "प्रदर्शन विकल्प",
+       "prefs-tokenwatchlist": "टोकन",
+       "prefs-diffs": "अंतर",
+       "prefs-help-prefershttps": "ई प्राथमिकता आप कय अगला लॉगिन मे प्रभावी होई।",
+       "email-address-validity-invalid": "एकठु वैध ई-मेल ठहर दिहा जाय",
+       "userrights": "सदस्य अधिकार व्यवस्थापन",
+       "userrights-lookup-user": "सदस्य समूहन् कय व्यवस्थापन करा जाय",
+       "userrights-user-editname": "सदस्यनावँ दिहा जाय:",
+       "editusergroup": "सदस्य समूहन् कय संपादन करा जाय",
+       "editinguser": "सदस्य '''[[User:$1|$1]]''' $2 कय अधिकार बदला जाय",
+       "userrights-editusergroup": "सदस्य समूहन् कय संपादन करा जाय",
+       "saveusergroups": "सदस्य समूहन् कय व्यवस्थापन सहेजा जाय",
+       "userrights-groupsmember": "निचे कय {{PLURAL:$1|समूह|समूहन्}} कय सदस्य:",
+       "userrights-groupsmember-auto": "निचे कय {{PLURAL:$1|समूह|समूहन्}} कय अंतर्निहित सदस्य:",
+       "userrights-reason": "कारण:",
        "watchlist": "अवलोकन सुची"
 }
index da01d45..97addac 100644 (file)
@@ -53,7 +53,7 @@
        "tog-shownumberswatching": "İzləyən istifadəçilərin sayını göstər",
        "tog-oldsig": "İndiki imza:",
        "tog-fancysig": "Vikimətn şəklində imza (avtomatik keçid yaratmadan)",
-       "tog-uselivepreview": "Canlı sınaq baxışı xüsusiyyətindən istifadə et (JavaScript tələb edir, sınaq mərhələsindədir)",
+       "tog-uselivepreview": "Canlı sınaq baxışını istifadə et",
        "tog-forceeditsummary": "Qısa məzmunu boş saxladıqda mənə bildir",
        "tog-watchlisthideown": "Mənim redaktələrimi izləmə siyahısında gizlət",
        "tog-watchlisthidebots": "Bot redaktələrini izləmə siyahısında gizlət",
        "viewsourcetext": "Siz bu səhifənin məzmununu görə və köçürə bilərsiniz:",
        "viewyourtext": "Bu səhifəyə '''etdiyiniz dəyişikliklərin''' mənbəyini görüntüləyib köçürə bilərsiniz:",
        "protectedinterface": "Bu səhifədə proqram təminatı üçün sistem məlumatları var və sui-istifadənin qarşısını almaq üçün mühafizə olunmalıdır.",
-       "editinginterface": "'''Diqqət!''' Siz proqram təminatı interfeysinin mətn olan səhifəsini redaktə edirsiniz.\nOnun dəyişdirilməsi digər istifadəçilərin interfeysinin xarici görünüşünə təsir göstərir.\nTərcümə üçün daha yaxşı olar ki, MediaWiki-nin lokallaşması üçün olan [//translatewiki.net/wiki/Main_Page?setlang=az translatewiki.net]  layihəsindən istifadə edəsiniz.",
+       "editinginterface": "<strong>Diqqət:</strong> Siz proqram təminatı üçün interfeys mətni olan səhifəni redaktə edirsiniz.\nOnun dəyişdirilməsi digər istifadəçilərin interfeysinin xarici görünüşünə təsir göstərəcək.",
        "cascadeprotected": "Səhifə mühafizə olunub, çünki o kaskad mühafizə olunan {{PLURAL:$1|növbəti səhifəyə|növbəti səhifələrə}} qoşulub:\n$2",
        "namespaceprotected": "Sizin adlarında $1 olan məqalələrdə redaktə etməyə icazəniz yoxdur.",
        "customcssprotected": "Bu səhifəni redaktə etmə izniniz yoxdur, çünki bu səhifə başqa bir istifadəçinin fərdi parametrlərinə sahibdir.",
        "invalidtitle-knownnamespace": "\"$2\" sahə adı üçün \"$3\" mətni keçərsiz bir başlıq",
        "invalidtitle-unknownnamespace": "Naməlum $1 ad sahəsi miqdarı və keçərsiz \"$2\" başlıq",
        "exception-nologin": "Giriş edilməmişdir",
-       "exception-nologin-text": "Bu səhifəyə daxi olmaq üçün [[Special:Userlogin|özünüzü təqdim]], edin.",
+       "exception-nologin-text": "Bu səhifəyə daxil olmaq və ya fəaliyyəti icra etmək üçün özünüzü sistemə təqdim edin.",
        "exception-nologin-text-manual": " bu səhifəyə və ya hərəkətə daxil olmaq üçün $1 lazımdır.",
        "virus-badscanner": "Düzgün olmayan konfiqurasiya: naməlum ''$1'' virus yoxlayanı",
        "virus-scanfailed": "Yoxlama başa çatmadı (kod $1)",
        "virus-unknownscanner": "naməlum antivirus",
-       "logouttext": "'''Sistemdən çıxdınız.'''\n\nSiz {{SITENAME}} saytını anonim olaraq istifadə etməyə davam edə bilər və ya eyni, yaxud başqa istifadəçi adı ilə <span class='plainlinks'>[$1 yenidən daxil ola]</span> bilərsiniz. Veb-brauzerin keş yaddaşını təmizləyənədək bəzi səhifələr hələ də sistemdə imişsiniz kimi görünə bilər.",
+       "logouttext": "<strong>Sistemdən çıxdınız.</strong>\n\nVeb-brauzerin keş yaddaşını təmizləyənədək bəzi səhifələr hələ də sistemdəymişsiniz kimi görünə bilər.",
        "welcomeuser": "Xoş gəldin $1!",
        "welcomecreation-msg": "Hesabınız yaradıldı.\n[[Special:Preferences|{{SITENAME}} nizamlamalarınızı]] dəyişdirməyi unutmayın.",
        "yourname": "İstifadəçi adı",
        "userlogin-noaccount": "İstifadəçi hesabınız yoxdur?",
        "userlogin-joinproject": "{{SITENAME}} qoşulun",
        "nologin": "İstifadəçi hesabınız yoxdur? $1.",
-       "nologinlink": "Hesab yaradın",
-       "createaccount": "Hesab ",
+       "nologinlink": "Hesab yarat",
+       "createaccount": "Hesab yarat",
        "gotaccount": "İstifadəçi hesabınız varmı? '''$1'''.",
        "gotaccountlink": "Daxil olun",
        "userlogin-resetlink": "Daxilolma məlumatlarınızı unutmusunuz?",
        "cannotchangeemail": "Hesabın e-poçt ünvanı bu wiki üzərindən dəyişdirilə bilməz.",
        "emaildisabled": "Bu saytdan e-poçt göndərə bilməzsiniz.",
        "accountcreated": "Hesab yaradıldı",
-       "accountcreatedtext": "$1 üçün istifadəçi hesabı yaradıldı.",
+       "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|talk]]) üçün istifadəçi hesabı yaradıldı.",
        "createaccount-title": "{{SITENAME}} hesabın yaradılması",
        "createaccount-text": "Biriləri {{SITENAME}} saytında ($4) sizin e-poçt ünvanınızdan istifadə edərək, parolu \"$3\" olan, \"$2\" adlı bir hesab yaratdı.\n\nSayta daxil olmalı və parolunuzu dəyişdirməlisiniz.\n\nƏgər istifadəçi hesabını səhvən yaratmısınızsa, bu mesajı gözardı edə bilərsiniz.",
-       "login-throttled": "Sistemə daxil olmaq üçün həddən artıq cəhd etmisiniz.\nYeni cəhd etməzdən əvvəl bir qədər gözləyin.",
+       "login-throttled": "Sistemə daxil olmaq üçün həddən artıq cəhd etmisiniz.\nYeni cəhd etməzdən əvvəl $1 gözləyin.",
        "login-abort-generic": "Giriş uğursuz alındı - Rədd",
        "loginlanguagelabel": "Dil: $1",
        "suspicious-userlogout": "Sizin çıxış üçün cəhdiniz uğursuz alındı. Bu, brouzerin yaxud proksi-keşləmənin düzgün işləməməsindən qaynaqlanır.",
        "createacct-another-realname-tip": "Gərçək adınız istəyə bağlıdır.\nƏgər gərçək adınızı göstərsəniz, çalışmalarınıza müraciət etmək üçün istifadə ediləcəkdir.",
        "pt-login": "Daxil ol",
        "pt-login-button": "Daxil ol",
-       "pt-createaccount": "İstifadəçi hesabı yarat",
+       "pt-createaccount": "Hesab yarat",
        "pt-userlogout": "Çıxış",
        "php-mail-error-unknown": "PHP-nin mail() funksiyasında naməlum xəta",
        "user-mail-no-addy": "Bir e-poçt ünvanı olmadan e-poçt göndərməyə çalışdı.",
        "preview": "Sınaq görüntüsü",
        "showpreview": "Sınaq göstərişi",
        "showdiff": "Dəyişiklikləri göstər",
-       "anoneditwarning": "'''DİQQƏT!''' Siz özünüzü sistemə təqdim etməmisiniz. Sizin IP ünvanınız bu səhifənin tarixçəsinə qeyd olunacaq.",
+       "anoneditwarning": "<strong>Diqqət:</strong> Siz sistemə daxil olmamısınız. Hər hansı dəyişiklik etsəniz, sizin IP-ünvanınız hamıya görünəcək. Əgər <strong>[$1 daxil olsanız]</strong> və ya <strong>[$2 hesab yaratsanız]</strong>, redaktələriniz sizin istifadəçi adınıza yazılacaq və digər üstünlüklər də qazanacaqsınız.",
        "anonpreviewwarning": "Sistemə daxil olmamısınız. \"Səhifəni qeyd et\" düyməsini bassanız IP ünvanınız səhifənin tarixçəsində qeyd olunacaq.",
        "missingsummary": "'''Xatırlatma.''' Siz dəyişikliklərin qısa şərhini verməmisiniz. \"Səhifəni qeyd et\" düyməsinə təkrar basandan sonra sizin dəyişiklikləriniz şərhsiz qeyd olunacaq.",
        "missingcommenttext": "Zəhmət olmasa, aşağıda şərhinizi yazın.",
        "currentrev": "Hal-hazırkı versiya",
        "currentrev-asof": "Səhifəsinin $1 tarixinə olan son halı",
        "revisionasof": "$1 versiyası",
-       "revision-info": "$2 tərəfindən yaradılmış $1 tarixli dəyişiklik",
+       "revision-info": "$2$7 tərəfindən edilmiş $1 tarixli dəyişiklik",
        "previousrevision": "←Əvvəlki versiya",
        "nextrevision": "Sonrakı versiya→",
        "currentrevisionlink": "Hal-hazırkı versiya",
        "history-feed-empty": "Axtardığınız səhifə mövcud deyil.\nÇox guman ki, bu səhifə silinib və ya onun adı dəyişdirilib.\nVikidə buna bənzər səhifələri [[Special:Search|axtarmağa]] cəhd edin.",
        "rev-deleted-comment": "(şərhlər silindi)",
        "rev-deleted-user": "(İstifadəçi adı silindi)",
-       "rev-deleted-event": "(qeyd silindi)",
+       "rev-deleted-event": "(qeydiyyat detalları silindi)",
        "rev-deleted-user-contribs": "[istifadəçi adı və ya IP ünvanı silindi - dəyişiklik fəaliyyətlərdən çıxarıldı]",
        "rev-deleted-text-permission": "Səhifənin bu versiyası''' silinib'''.\nMümkündür ki, bunun səbəbi [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} silmə qeydlərində] göstərilmişdir.",
        "rev-suppressed-text-unhide": "Səhifənin bu versiyası''' silinib'''.\nMümkündür ki, bunun səbəbi [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} silmə qeydlərində] göstərilmişdir.\nSiz idarəçi olduğunuza görə silinən [$1 bu versiyanı] nəzərdən keçirə bilərsiniz.",
        "revdelete-show-file-submit": "Bəli",
        "logdelete-selected": "Jurnalın {{PLURAL:$1|seçilmiş qeydi|seçilmiş qeydləri}}:",
        "revdelete-legend": "Məhdudiyyətləri müəyyənləşdir:",
-       "revdelete-hide-text": "Səhifənin bu versiyasının mətnini gizlə",
+       "revdelete-hide-text": "Dəyişikliyin mətni",
        "revdelete-hide-image": "Faylın məzmununu gizlə",
-       "revdelete-hide-name": "Hərəkəti və məqsədi gizləmək",
-       "revdelete-hide-comment": "Dəyişikliklərin şərhini gizlə",
-       "revdelete-hide-user": "Redaktə müəllifinin istifadəçi adını/IP ünvanını gizlə",
+       "revdelete-hide-name": "Məqsədi və parametrləri gizlə",
+       "revdelete-hide-comment": "Dəyişikliklərin təsviri",
+       "revdelete-hide-user": "Redaktə müəllifinin istifadəçi adı/IP-ünvanı",
        "revdelete-hide-restricted": "Məlumatları idarəçilərdən də gizlə",
        "revdelete-radio-same": "(dəyişdirmə)",
        "revdelete-radio-set": "Gizli",
        "revdel-restore": "Görünüşü dəyiş",
        "pagehist": "Səhifənin tarixçəsi",
        "deletedhist": "Silmə qeydləri",
-       "revdelete-reason-dropdown": "*Ümumi silmə səbəbləri\n** Müəllif hüquqları pozuntusu\n** Uyğunsuz şəxsi məlumat",
+       "revdelete-reason-dropdown": "*Əsas silmə səbəbləri\n** Müəllif hüquqları pozuntusu\n** Uyğun olmayan şəxsi məlumat\n** Uyğun olmayan istifadəçi adı\n** Potensial böhtan xarakterli məlumat",
        "revdelete-otherreason": "Digər/əlavə səbəb:",
        "revdelete-reasonotherlist": "Digər səbəb",
        "revdelete-edit-reasonlist": "Silmə səbəblərini redaktə et",
        "search-section": "(bölmə $1)",
        "search-suggest": "Bəlkə, bunu nəzərdə tuturdunuz: $1",
        "search-interwiki-caption": "Qardaş layihələr",
-       "search-interwiki-default": "$1 nəticə:",
+       "search-interwiki-default": "$1 nəticələri:",
        "search-interwiki-more": "(yenə)",
        "search-relatedarticle": "əlaqədar",
        "searchrelated": "əlaqəli",
        "timezoneregion-indian": "Hind Okeanı",
        "timezoneregion-pacific": "Sakit Okean",
        "allowemail": "Digər istifadəçilər mənə e-məktub göndərə bilər",
-       "prefs-searchoptions": "Axtarış kriteriyaları",
+       "prefs-searchoptions": "Axtar",
        "prefs-namespaces": "Adlar fəzası",
        "default": "boş",
        "prefs-files": "Fayllar",
        "prefs-common-css-js": "Bütün skinlər üçün ümumi CSS/JavaScript:",
        "prefs-emailconfirm-label": "E-poçtun təsdiqlənməsi:",
        "youremail": "E-məktub:",
-       "username": "İstifadəçi adı:",
-       "prefs-memberingroups": "Üzvü olduğu {{PLURAL:$1|qrup|qrup}}:",
+       "username": "{{GENDER:$1|İstifadəçi adı}}:",
+       "prefs-memberingroups": "{{GENDER:$2|Üzv}} olduğu {{PLURAL:$1|qrup}}:",
        "prefs-memberingroups-type": "$1",
        "prefs-registration": "Qeydiyyat vaxtı:",
        "prefs-registration-date-time": "$1",
        "yournick": "Ləqəb:",
        "badsig": "Səhv xam imza.\nHTML kodu yoxla.",
        "badsiglength": "İmzanız çox uzundur. İmza $1 {{PLURAL:$1|simvoldan|simvoldan}} uzun olmamalıdır.",
-       "yourgender": "Cins:",
-       "gender-unknown": "göstərmə",
-       "gender-male": "kişi",
-       "gender-female": "qadın",
+       "yourgender": "Hansı təsvir sizə daha uyğundur?",
+       "gender-unknown": "Bildirmək istəmirəm",
+       "gender-male": "Bu kişi istifadəçi viki-səhifələri redaktə edir",
+       "gender-female": "Bu qadın istifadəçi viki-səhifələri redaktə edir",
        "email": "E-məktub",
-       "prefs-help-realname": "Həqiqi adınızı daxil etmək məcburi deyil.\nBu seçimi etdiyiniz halda, adınız redaktələrinizə görə müəlliflik hüququnuzun tanınması üçün istifadə ediləcək.",
+       "prefs-help-realname": "Həqiqi adınızı daxil etmək məcburi deyil.\nDaxil etsəniz, adınız redaktələrinizin müəllifliyinin təyin edilməsi üçün istifadə edilə bilər.",
        "prefs-help-email": "E-poçt ünvanınızı daxil etmək məcburi deyil.\nBu, parolunuzu unutduğunuz halda, sizə yeni parol göndərməyə imkan verir.",
        "prefs-help-email-others": "Həmçinin, istifadəçi və ya müzakirə səhifənizdəki link vasitəsilə başqa istifadəçilərin sizinlə əlaqə yaratmasını seçə bilərsiniz. Bu halda sizin e-poçt ünvanınız heç kimə görünməyəcək.",
        "prefs-help-email-required": "Elektron ünvan tələb olunur.",
        "prefs-signature": "İmza",
        "prefs-dateformat": "Tarix formatı",
        "prefs-timeoffset": "Saat qurşağının fərqi",
-       "prefs-advancedediting": "Ətraflı variantlar",
+       "prefs-advancedediting": "Ümumi parametrlər",
        "prefs-advancedrc": "Ətraflı variantlar",
        "prefs-advancedrendering": "Ətraflı variantlar",
        "prefs-advancedsearchoptions": "Ətraflı variantlar",
        "userrights-no-interwiki": "Sizə başqa vikilayihələrdəki istifadəçilərin statusunu dəyişməyə icazə verilməyib",
        "userrights-nodatabase": "$1 verilənlər bazası ya mövcud deyil, ya da lokal deyil.",
        "userrights-nologin": "Siz istifadəçilərin hüquqlarını dəyişmək üçün sistemə idarəçi olaraq [[Special:UserLogin|daxil olmalısınız]].",
-       "userrights-notallowed": "Sizin istifadəçi hesabınıza digər istifadəçilərə hüquqlar vermək və ya almağa icazə verilməyib.",
+       "userrights-notallowed": "Sizin digər istifadəçilərə hüquqlar vermək və ya almaq icazəniz yoxdur.",
        "userrights-changeable-col": "Dəyişdirə bildiyiniz qruplar",
        "userrights-unchangeable-col": "Dəyişdirə bilmədiyiniz qruplar",
        "userrights-irreversible-marker": "$1*",
        "right-reupload-own": "Mövcud faylın yeni versiyasının həmin istifadəçi tərəfindən yüklənməsi",
        "right-reupload-shared": "ümumi anbarda olan faylın adının lokal adla dəyişdirilməsi",
        "right-upload_by_url": "URL-dən fayl yüklə",
-       "right-autoconfirmed": "Yarım mühafizə edilmiş səhifənin redaktəsi",
+       "right-autoconfirmed": "IP-ünvana görə sürət məhdudiyyəti yoxdur",
        "right-bot": "Avtomatik proses hesab edilir",
        "right-apihighlimits": "API sorğularında yüksək həddən istifadə et",
        "right-writeapi": "Redaktələrdən zamanı API-dən (İnterfeys proqramlaşdıran proqram) istifadə",
        "right-hideuser": "İstifadəçi adına qadağa qoy və adın görünməsinin qarşısını al",
        "right-ipblock-exempt": "IP bloklanmalarını, avtobloklanmalarını və diapazon bloklanmalarını keç",
        "right-proxyunbannable": "Proksilərin avtomatik bloklanmalarını keç",
-       "right-unblockself": "Özünün blokunun qaldırılması",
-       "right-protect": "Mühafizə səviyyəsi dəyiş və mühafizə altında olan səhifəni redaktə et",
-       "right-editprotected": "Mühafizə olunmuş səhifələri redaktə (kaskad mühafizə daxil olmaqla)",
+       "right-unblockself": "Öz blokunuzun açılması",
+       "right-protect": "Mühafizə səviyyəsinin dəyişilməsi və kaskad mühafizə olunan səhifələrin redaktə edilməsi",
+       "right-editprotected": "\"{{int:protect-level-sysop}}\" mühafizə səviyyəsinə malik səhifələrin redaktə edilməsi",
        "right-editinterface": "İstifadəçi interfeysini dəyişmək",
        "right-editusercssjs": "Digər istifadəçilərin CSS və JavaScript fayllarını redaktə",
        "right-editusercss": "Digər istifadəçilərin CSS faylını redaktə",
        "recentchanges-label-bot": "Bu redaktə bot tərəfindən edilmişdir",
        "recentchanges-label-unpatrolled": "Bu redaktə hələ nəzərdən keçirilməmişdir",
        "recentchanges-label-plusminus": "Səhifənin ölçüsü bayt miqdarı ilə təyin edilir",
-       "recentchanges-legend-newpage": "$1 - yeni səhifə",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (həmçinin bax: [[Special:NewPages|yeni səhifələrin siyahısı]])",
        "rcnotefrom": "Aşağıda <strong>$2</strong>-dən bu yana olan dəyişikliklər göstərilib (<strong>$1</strong>-dən çox olmayaraq).",
        "rclistfrom": "$3 $2 vaxtından başlayaraq yeni dəyişiklikləri göstər",
        "rcshowhideminor": "Kiçik redaktələri $1",
        "backend-fail-delete": "\"$1\" faylı sililmədi.",
        "backend-fail-copy": "\"$1\" faylı \"$2\" faylına kopyalanmır.",
        "backend-fail-read": "\"$1\" faylı oxunmadı.",
-       "backend-fail-create": "\"$1\" faylı yaranmadı.",
+       "backend-fail-create": "\"$1\" faylı yazıla bilmədi.",
        "uploadstash": "Gizli yükləmə",
        "uploadstash-clear": "Müvəqqəti faylları təmizlə",
        "uploadstash-refresh": "Fayl siyahısını yenilə",
        "license": "Lisenziya",
        "license-header": "Lisenziya",
        "nolicense": "Heç biri seçilməmişdir",
-       "upload_source_url": " (keçərli, hər kəsin daxil ola biləcəyi bir URL)",
-       "upload_source_file": " (kompyuterinizdəki bir fayl)",
+       "upload_source_url": "(siz düzgün, hər kəsin daxil ola biləcəyi URL seçdiniz)",
+       "upload_source_file": "(siz kompüterinizdəki faylı seçdiniz)",
        "listfiles_search_for": "Media adı üçün axtar:",
        "imgfile": "fayl",
        "listfiles": "Fayl siyahısı",
        "statistics-users-active": "Aktiv istifadəçilər",
        "statistics-users-active-desc": "Son {{PLURAL:$1|gün|$1 gündə}} iş görən istifadəçilər",
        "doubleredirects": "İkiqat istiqamətləndirmələr",
-       "double-redirect-fixed-move": "[[$1]] dəyişdirilib.\nHazırda [[$2]]-yə istiqamətlənib.",
-       "double-redirect-fixed-maintenance": "[[$1]]-dən [[$2]]-yə ikiqat istiqamətlənmə düzəldilir.",
+       "double-redirect-fixed-move": "[[$1]] səhifəsinin yeri dəyişdirilib.\nO avtomatik yenilənib və [[$2]] səhifəsinə yönləndirilib.",
+       "double-redirect-fixed-maintenance": "[[$1]] səhifəsindən [[$2]] səhifəsinə ikiqat yönləndirmə avtomatik düzəldilir.",
        "double-redirect-fixer": "Yönləndirmə səhvdir",
        "brokenredirects": "Xətalı istiqamətləndirmə",
        "brokenredirectstext": "Aşağıdakı istiqamətləndirmələr mövcud olmayan səhifələrə keçid verir:",
        "wantedtemplates": "Tələb olunan şablonlar",
        "mostlinked": "Ən çox keçidlənən səhifələr",
        "mostlinkedcategories": "Ən çox məqaləsi olan kateqoriyalar",
-       "mostlinkedtemplates": "Ən çox istifadə olunan şablonlar",
+       "mostlinkedtemplates": "Ən çox istifadə olunan səhifələr",
        "mostcategories": "Kateqoriyası ən çox olan məqalələr",
        "mostimages": "Ən çox istifadə edilmiş şəkillər",
        "mostrevisions": "Ən çox nəzərdən keçirilmiş (versiyalı) məqalələr",
        "listusers-noresult": "İstifadəçi tapılmadı.",
        "listusers-blocked": "(bloklandı)",
        "activeusers": "Aktiv istifadəçilərin siyahısı",
-       "activeusers-count": "$1 {{PLURAL:$1|edit|redaktə}} son {{PLURAL:$3|day|$3 gün}}",
+       "activeusers-count": "Son {{PLURAL:$3|gündə|$3 gündə}} $1 {{PLURAL:$1|redaktə|redaktə}}",
        "activeusers-hidebots": "Botları gizlə",
        "activeusers-hidesysops": "İdarəçiləri gizlə",
        "activeusers-noresult": "İstifadəçi tapılmadı.",
        "listgrouprights": "İstifadəçi qruplarının hüquqları",
        "listgrouprights-summary": "Bu vikidə olan istifadəçi siyahıları və onların hüquqları aşağıda göstərilmişdir.\nFərdi hüquqlar haqqında əlavə məlumatı [[{{MediaWiki:Listgrouprights-helppage}}]] səhifəsində tapa bilərsiniz",
-       "listgrouprights-key": "* <span class=\"listgrouprights-granted\">Verilmiş hüquqlar</span>\n* <span class=\"listgrouprights-revoked\">Ləğv edilmiş hüquqlar</span>",
+       "listgrouprights-key": "İzah:\n* <span class=\"listgrouprights-granted\">Verilmiş hüquqlar</span>\n* <span class=\"listgrouprights-revoked\">Geri alınmış hüquqlar</span>",
        "listgrouprights-group": "Qrup",
        "listgrouprights-rights": "Hüquqlar",
        "listgrouprights-helppage": "Help:Qrup hüquqları",
        "mywatchlist": "İzləmə siyahısı",
        "watchlistfor2": "$1 $2 üçün",
        "nowatchlist": "İzləmə siyahınız böşdur.",
-       "watchlistanontext": "Lütfən, izlədiyiniz səhifələri görmək və ya redaktə etmək üçün $1.",
+       "watchlistanontext": "Lütfən, izlədiyiniz səhifələri görmək və ya redaktə etmək üçün sistemə daxil olun.",
        "watchnologin": "Daxil olmamısınız",
        "addwatch": "İzləmə siyahısına əlavə et",
        "addedwatchtext": "\"[[:$1]]\" səhifəsi [[Special:Watchlist|izlədiyiniz səhifələr]] siyahısına əlavə edildi. Bu səhifədə və əlaqəli müzakirə səhifəsindəki bütün dəyişikliklər orada göstəriləcək və səhifə asanlıqla seçiləbilmək üçün [[Special:RecentChanges|son dəyişikliklərdə]] qalın şriftlərlə görünəcəkdir. <p> Səhifəni izləmə siyahınızdan çıxarmaq üçün yan lövhədəki \"izləmə\" düyməsinə vurun.",
        "protect-default": "Bütün istifadəçilərə icazə ver",
        "protect-fallback": "\"$1\" icazəsi tələb olunur",
        "protect-level-autoconfirmed": "Yeni və anonim istifadəçiləri blokla",
-       "protect-level-sysop": "Yalnız idarəçilər",
+       "protect-level-sysop": "Yalnız idarəçilərə icazə verilir",
        "protect-summary-cascade": "kaskad mühafizə",
        "protect-expiring": "$1 (UTC)- tarixində vaxtı bitir",
        "protect-expiring-local": "$1-də bitir",
        "undeletedrevisions": "Cəmi {{PLURAL:$1|1 redaktə|$1 redaktə}} geri qaytarıldı.",
        "undeletedrevisions-files": "{{PLURAL:$1|1 versiya|$1 versiya}} və {{PLURAL:$2|1 fayl|$2 fayl}} bərpa edildi",
        "undeletedfiles": "{{PLURAL:$1|1 fayl|$1 fayl}} bərpa olundu",
-       "cannotundelete": "Bərpaetmə xətası. Başqa istifadəçi sizdən əvvəl səhifəni bərpa edib.",
+       "cannotundelete": "Bərpaetmə xətası:\n$1",
        "undeletedpage": "'''$1 bərpa edildi'''\n\nMəqalələrin bərpa edilməsi və silinməsi haqqında son dəyişiklikləri nəzərdən keçirmək üçün [[Special:Log/delete|silmə qeydlərinə]] baxın.",
        "undelete-header": "Son silinmiş səhifələrə baxmaq üçün [[Special:Log/delete|silmə qeydlərinə]] bax.",
        "undelete-search-title": "Silinmiş səhifələri axtar",
        "autoblockid": "Avtoblok #$1",
        "block": "İstifadəçini blokla",
        "unblock": "İstifadəçinin blokunu götür",
-       "blockip": "İstifadəçini blokla",
+       "blockip": "{{GENDER:$1|İstifadəçini}} blokla",
        "blockip-legend": "İstifadəçinin bloklanması",
        "ipaddressorusername": "IP-ünvanı və ya istifadəçi adı",
        "ipbexpiry": "Bitmə müddəti:",
        "ipb-confirm": "Bloku təsdiqlə",
        "badipaddress": "Səhv IP",
        "blockipsuccesssub": "bloklandı",
-       "blockipsuccesstext": "[[Special:Contributions/$1| $1]]bloklanıb..<br />\nBax [[Special:BlockList|IP blok siyahısı]] bloklanmış IP-lər.",
+       "blockipsuccesstext": "[[Special:Contributions/$1|$1]] bloklanıb.<br />\nBlokları yoxlamaq üçün [[Special:BlockList|bloklama siyahısına]] baxın.",
        "ipb-blockingself": "Özünü bloklayacaqsınız.! Bunu etmək istədiyinizdən əminsinizmi?",
        "ipb-confirmhideuser": "İstifadəçini bloklamaq və redaktə siyahısından onun adını silmək üzərəsiniz. Bunu etmək istədiyinizdən əminsinizmi?",
        "ipb-edit-dropdown": "Bloklama səbəblərini redaktə et",
        "ipb-unblock-addr": "$1 üzərindəki blok götürüldü",
        "ipb-unblock": "Bloku götür",
        "ipb-blocklist": "Mövcud blokları göstər",
-       "ipb-blocklist-contribs": "$1 istifadəçi fəaliyyətləri",
+       "ipb-blocklist-contribs": "{{GENDER:$1|$1}} istifadəçi hesabının fəaliyyətləri",
        "unblockip": "İstifadəçinin blokunu götür",
        "unblockiptext": "Əvvəlcədən bloklanmış bir IP ünvanına və ya istifadəçi adına yazma geri vermek için aşağıdakı formadan istifadə edin.",
        "ipusubmit": "Bu bloku götür",
        "blocklog-showsuppresslog": "Bu istifadəçi daha əvvəl bloklanmışdır. Bloklama gündəliyi referans üçün aşağıda göstərilib:",
        "blocklogentry": "tərəfindən [[$1]] bloklandı, blok müddəti: $2 $3",
        "reblock-logentry": "[[$1]] üçün bloklama parametrlərini, başa çatma tarixi $2 $3 olmaqla, dəyişdirdi",
-       "blocklogtext": "İstifadəçilərin bloklanması və blokun götürülməsi siyahısı.\nAvtomatik bloklanmış IP-ünvanlar burada göstərilmir.\nHal-hazırkı [[Special:BlockList|qadağaların və bloklamaların siyahısı]]na bax.",
+       "blocklogtext": "İstifadəçilərin bloklanması və blokun götürülməsi siyahısı.\nAvtomatik bloklanmış IP-ünvanlar burada göstərilmir.\nHazırkı [[Special:BlockList|qadağaların və bloklamaların siyahısına bax]].",
        "unblocklogentry": "$1 üzərindəki blok götürüldü",
        "block-log-flags-anononly": "yalnız qeydiyyatsız istifadəçilər",
        "block-log-flags-nocreate": "yeni hesab yaratma bloklanıb",
        "range_block_disabled": "İdarəçilərə diapazonu bloklamaq qadağandır.",
        "ipb_expiry_invalid": "Bitmə vaxtı səhvdir",
        "ipb_expiry_temp": "Gizli istifadəçi adı bloklamaları müddətsiz olmalıdır.",
-       "ipb_hide_invalid": "İstifadəçi hesabınln gizlədilməsi qeyri-mümkündür; həddən çox redaktəsi var.",
+       "ipb_hide_invalid": "Bu istifadəçi hesabının gizlədilməsi mümkün deyil, onun töhfəsi {{PLURAL:$1|bir redaktədən|$1 redaktədən}} çoxdur.",
        "ipb_already_blocked": "\"$1\" artıq bloklanıb",
        "ipb-needreblock": "$1 artıq bloklanıb.\nBloklama şərtlərini dəyişmək istəyirsiniz?",
        "ipb-otherblocks-header": "Başqa {{PLURAL:$1|bloklama|bloklamalar}}",
        "lockedbyandtime": "(by {{GENDER:$1|$1}} on $2 at $3)",
        "move-page": "Dəyişdir $1",
        "move-page-legend": "Səhifənin adını dəyiş",
-       "movepagetext": "Aşağıdakı formadan istifədə etmə səhifənin adını, bütün tarixçəsini də köçürməklə yeni başlığa dəyişəcək.\nƏvvəlki başlıq yeni başlığa istiqamətləndirmə səhifəsinə çevriləcək.\nKöhnə səhifəyə keçidləri avtomatik olaraq dəyişə bilərsiniz.\nBu seçimi etmədiyiniz halda, [[Special:DoubleRedirects|təkrarlanan]] və ya [[Special:BrokenRedirects|qırıq istiqamətləndirmələri]] yoxlamağı yaddan çıxarmayın.\nKeçidlərin lazımi yerə istiqamətləndirilməsini təmin etmək sizin məsuliyyətinizdədir.\n\nNəzərə alın ki, hədəf başlığı altında bir səhifə mövcuddursa yerdəyişmə '''baş tutmayacaq'''. Buna həmin səhifənin boş olması və ya istiqamətləndirmə səhifəsi olması və keçmişdə redaktə edilməməsi halları istisnadır. Bu o deməkdir ki, səhvən adını dəyişdiyiniz səhifələri geri qaytara bilər, bununla yanaşı artıq mövcud olan səhifənin üzərinə başqa səhifə yaza bilməzsiniz.\n\n'''XƏBƏRDARLIQ!'''\nBu yerdəyişmə populiyar səhifə üçün əsaslı və gözlənilməz ola bilər, ona görə də bu dəyişikliyi yerinə yetirməzdən əvvəl, bunun mümkün nəticələrini başa düşdüyünüzdən əmin olun.",
+       "movepagetext": "Aşağıdakı formadan istifədə etməklə səhifənin adını və bütün tarixçəsini yeni başlığa dəyişəcəksiniz.\nƏvvəlki başlıq yeni başlığa yönləndirmə səhifəsinə çevriləcək.\nKöhnə səhifəyə keçidləri avtomatik olaraq dəyişə bilərsiniz.\nBunu etməsəniz, zəhmət olmasa, [[Special:DoubleRedirects|təkrarlanan]] və ya [[Special:BrokenRedirects|qırılmış istiqamətləndirmələri]] yoxlamağı unutmayın.\nKeçidlərin lazımi yerə istiqamətləndirilməsini təmin etmək sizin məsuliyyətinizdədir.\n\nNəzərə alın ki, hədəflədiyiniz adda bir səhifə artıq mövcuddursa, addəyişmə <strong>baş tutmayacaq</strong>. Lakin həmin səhifənin boş olması, istiqamətləndirmə səhifəsi olması və redaktə tarixçəsinin olmaması halları istisnadır. Bu o deməkdir ki, səhvən adını dəyişdiyiniz səhifələri geri qaytara bilər, amma artıq mövcud olan səhifənin üzərinə başqa səhifə yaza bilməzsiniz.\n\n<strong>XƏBƏRDARLIQ!</strong>\nPopulyar səhifələrin adlarının dəyişdirilməsi əsaslı və gözlənilməz nəticələrə səbəb ola bilər. Ona görə də bu dəyişikliyi yerinə yetirməzdən əvvəl, bunun mümkün nəticələrini başa düşdüyünüzdən əmin olun.",
        "movepagetalktext": "Uyğun müzakirə səhifəsi avtomatik hərəkət edəcək '''əgər:'''\n* boş olmayan müzakirə səhifəsi yeni adla artıq mövcuddursa, və ya\n* Siz bayrağı aşağıdan götürsəniz.\n\nHəmin hallarda , ehtiyac yaranarsa siz səhifələri əllə birləşdirmək məcburiyyətində qalacaqsınız",
        "movearticle": "Səhifənin adını dəyişdir",
        "movenotallowed": "Siz səhifələrin adını dəyişə bilməzsiniz.",
        "import-upload": "XML-veriləni yüklə",
        "import-token-mismatch": "Seans məlumatlarının itirilməsi. Lütfən, yenidən cəhd edin.",
        "import-invalid-interwiki": "Göstərilən vikidən köçürmək mümkün deyil",
-       "import-error-edit": "\"$1\" səhifəsi idxal edilə bilinmir, çünki onu dəyişmək səlahiyyətiniz yoxdur.",
-       "import-error-create": "\"$1\" səhifəsi açılmır, çünki onu yaratmaq səlahiyyətiniz yoxdur.",
+       "import-error-edit": "\"$1\" səhifəsi idxal edilmədi, çünki sizin onu dəyişmək səlahiyyətiniz yoxdur.",
+       "import-error-create": "\"$1\" səhifəsi idxal edilmədi, çünki sizin onu yaratmaq səlahiyyətiniz yoxdur.",
        "importlogpage": "Çıxarılma gündəliyi",
        "importlogpagetext": "Səhifələrin idarəçilər tərəfindən digər vikilərdən dəyişiklik tarixçəsi ilə birlikdə köçürülməsi",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revision|dəyişiklik}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|dəyişiklik|dəyişiklik}} idxal edildi.",
        "import-logentry-interwiki": "vikilərarası idxal $1",
-       "import-logentry-interwiki-detail": "$2-dən $1 {{PLURAL:$1|dəyişiklik|dəyişikliklər}}",
+       "import-logentry-interwiki-detail": "$2 vikidən $1 {{PLURAL:$1|dəyişiklik|dəyişiklik}} idxal edildi",
        "tooltip-pt-userpage": "İstifadəçi səhifəniz",
        "tooltip-pt-anonuserpage": "The user page for the ip you",
        "tooltip-pt-mytalk": "Danışıq səhifəm",
        "spambot_username": "MediaViki spam təmizləməsi",
        "pageinfo-title": "\"$1\" üçün məlumat",
        "pageinfo-header-basic": "Əsas məlumatlar",
-       "pageinfo-header-edits": "Redaktələr",
+       "pageinfo-header-edits": "Redaktə tarixçəsi",
        "pageinfo-header-restrictions": "Səhifə mühafizəsi",
        "pageinfo-header-properties": "Səhifə xüsusiyyətləri",
-       "pageinfo-watchers": "Baxış sayı",
+       "pageinfo-watchers": "Səhifəyə baxışların sayı",
        "pageinfo-firstuser": "Səhifəni yaradan",
        "pageinfo-firsttime": "Səhifənin yaranma tarixi",
        "pageinfo-lastuser": "Sonuncu redaktor",
        "pageinfo-lasttime": "Sonuncu redaktənin tarixi",
-       "pageinfo-edits": "Redaktələrin sayı",
-       "pageinfo-authors": "Fərqli müəlliflərin sayı",
+       "pageinfo-edits": "Redaktələrin ümumi sayı",
+       "pageinfo-authors": "Fərqli müəlliflərin ümumi sayı",
        "pageinfo-toolboxlink": "Əsas məlumatlar",
        "pageinfo-redirectsto": "İstiqamətləndirmə",
        "pageinfo-redirectsto-info": "məlumat",
        "exif-personinimage": "Təsvir edilmiş şəxs",
        "exif-compression-1": "Sıxılmış",
        "exif-copyrighted-true": "Müəlliflik hüququ ilə qorunur",
-       "exif-copyrighted-false": "İctimai istifadə",
+       "exif-copyrighted-false": "Müəlliflik hüququ göstərilməyib",
        "exif-unknowndate": "Naməlum tarix",
        "exif-orientation-1": "Normal",
        "exif-orientation-2": "Üfüqi çevrilib",
        "duplicate-defaultsort": "<strong>Diqqət:</strong> Susmaya görə \"$2\" çeşidləmə açarı susmaya görə əvvəlki \"$1\" çeşidləmə açarını inkar edir.",
        "version": "Versiya",
        "version-extensions": "NIzamlanmış genişlənmələr",
-       "version-skins": "Üzlük",
+       "version-skins": "Yüklənmiş üzlüklər",
        "version-specialpages": "Xüsusi səhifələr",
        "version-parserhooks": "Parser hooks",
        "version-variables": "Dəyişkənlər",
        "version-hook-name": "Çəngəlin adı",
        "version-hook-subscribedby": "Abunə olan",
        "version-version": "(Versiya $1)",
-       "version-license": "Lisenziya",
+       "version-license": "MediaViki lisenziyası",
        "version-ext-license": "Lisenziya",
        "version-ext-colheader-version": "Versiya",
        "version-ext-colheader-license": "Lisenziya",
        "specialpages": "Xüsusi səhifələr",
        "specialpages-group-maintenance": "Cari məruzələr",
        "specialpages-group-other": "Digər xüsusi səhifələr",
-       "specialpages-group-login": "Daxil ol/ hesab yarat",
+       "specialpages-group-login": "Daxil ol / hesab yarat",
        "specialpages-group-changes": "Son dəyişikliklər və qeydlər",
        "specialpages-group-media": "Media məruzələri və yükləmələr",
        "specialpages-group-users": "İstifadəçilər və hüquqlar",
        "specialpages-group-highuse": "Ən çox istifadə edilən səhifələr",
        "specialpages-group-pages": "Səhifələrin siyahıları",
        "specialpages-group-pagetools": "Səhifə alətləri",
-       "specialpages-group-wiki": "Viki məlumatları və alətləri",
+       "specialpages-group-wiki": "Məlumatlar və alətlər",
        "specialpages-group-redirects": "Xüsusi istiqamətləndirmə səhifələri",
        "specialpages-group-spam": "Spam alətləri",
        "blankpage": "Boş səhifə",
        "compare-rev2": "Dəyişiklik 2",
        "compare-submit": "Qarşılaşdır",
        "dberr-problems": "Üzr istəyirik! Bu saytda texniki problemlər var.",
-       "dberr-info": "($1: Məlumat bazası ilə əlaqə yoxdur)",
+       "dberr-info": "(Məlumat bazası ilə əlaqə yoxdur: $1)",
        "htmlform-invalid-input": "Girişinizin bir qismilə əlaqədəar problemlər var",
        "htmlform-select-badoption": "İşarə etdiyiniz xüsus keçərli deyil.",
        "htmlform-int-invalid": "Göstərdiyiniz ifadə tam ədəd deyil.",
        "htmlform-selectorother-other": "Digər",
        "sqlite-has-fts": "$1 tam mətn axtarma ilə",
        "sqlite-no-fts": "$1 tam mətn axtarma olmadan",
-       "logentry-suppress-delete": "$1 suppressed page $3",
+       "logentry-suppress-delete": "$1 $3 səhifəsini {{GENDER:$2|gizlətdi}}",
        "revdelete-content-hid": "gizli mətn",
        "revdelete-summary-hid": "gizli tarixçə",
        "revdelete-uname-hid": " gizli istifadəçi adı",
        "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ı",
-       "logentry-newusers-autocreate": "$1 hesabı avtomatik yaradıldı",
+       "logentry-newusers-newusers": "$1 istifadəçi hesabı yaradıldı",
+       "logentry-newusers-create": "$1 istifadəçi hesabı yaradıldı",
+       "logentry-newusers-create2": "$3 istifadəçi hesabı $1 tərəfindən yaradıldı",
+       "logentry-newusers-autocreate": "$1 istifadəçi hesabı avtomatik yaradıldı",
        "rightsnone": "(yoxdur)",
        "revdelete-summary": "redaktə xülasəsi",
        "feedback-subject": "Mövzu:",
index d4d3c26..79518cf 100644 (file)
        "import-logentry-interwiki": "імпартавана зь іншай вікі $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|вэрсія імпартаваная|вэрсіі імпартаваныя|вэрсіяў імпартаваныя}} з $2",
        "javascripttest": "Тэставаньне JavaScript",
-       "javascripttest-title": "Праводзіцца тэставаньне $1",
        "javascripttest-pagetext-noframework": "Гэтая старонка трымаецца для правядзеньня тэстаў JavaScript.",
        "javascripttest-pagetext-unknownframework": "Невядомая бібліятэка тэставаньня «$1».",
+       "javascripttest-pagetext-unknownaction": "Невядомае дзеяньне «$1».",
        "javascripttest-pagetext-frameworks": "Калі ласка, выберыце адну з прапанаваных бібліятэка тэставаньня: $1",
        "javascripttest-pagetext-skins": "Выберыце афармленьне для тэставаньня:",
        "javascripttest-qunit-intro": "Глядзіце [$1 дакумэнтацыю па тэставаньні] на mediawiki.org.",
-       "javascripttest-qunit-heading": "Набор QUnit-тэстаў для MediaWiki JavaScript",
        "tooltip-pt-userpage": "Вашая ўласная старонка",
        "tooltip-pt-anonuserpage": "Старонка ўдзельніка для IP-адрасу, зь якога Вы рэдагуеце",
        "tooltip-pt-mytalk": "Ваша старонка гутарак",
index a0698db..3bee651 100644 (file)
        "tog-hideminor": "Скриване на малки редакции в последните промени",
        "tog-hidepatrolled": "Скриване на патрулираните редакции от списъка с последните промени",
        "tog-newpageshidepatrolled": "Скриване на патрулираните редакции от списъка на новите страници",
-       "tog-extendwatchlist": "Разширяване на списъка, така че да показва всички промени, не само най-скорошните",
-       "tog-usenewrc": "Ð\93Ñ\80Ñ\83пиÑ\80ане Ð¿Ð¾ Ñ\81Ñ\82Ñ\80аниÑ\86и Ð½Ð° Ð¿Ñ\80омениÑ\82е и списъка за наблюдение",
-       "tog-numberheadings": "Ð\9dомериране на заглавията",
-       "tog-showtoolbar": "Ð\9fоказване Ð½Ð° Ð¸Ð½Ñ\81Ñ\82Ñ\80Ñ\83менÑ\82иÑ\82е за редактиране",
+       "tog-extendwatchlist": "Разширяване на списъка за наблюдение, така че показва всички промени, не само последните",
+       "tog-usenewrc": "Ð\93Ñ\80Ñ\83пиÑ\80ане Ð½Ð° Ð¿Ñ\80омени Ð¿Ð¾ Ñ\81Ñ\82Ñ\80аниÑ\86иÑ\82е Ð½Ð° Ð¿Ð¾Ñ\81ледниÑ\82е Ð¿Ñ\80омени и списъка за наблюдение",
+       "tog-numberheadings": "Ð\90вÑ\82омаÑ\82иÑ\87но Ð½омериране на заглавията",
+       "tog-showtoolbar": "Ð\9fоказване Ð½Ð° Ð»ÐµÐ½Ñ\82аÑ\82а Ñ\81 Ð¸Ð½Ñ\81Ñ\82Ñ\80Ñ\83менÑ\82и за редактиране",
        "tog-editondblclick": "Редактиране на страниците чрез двойно щракване",
        "tog-editsectiononrightclick": "Възможност за редактиране на раздел при щракване с десния бутон върху заглавието му",
        "tog-watchcreations": "Добавяне на създадените от мен страници и качените от мен файлове към списъка ми за наблюдение",
@@ -48,7 +48,7 @@
        "tog-previewonfirst": "Показване на предварителен преглед при първа редакция",
        "tog-enotifwatchlistpages": "Уведомяване по е-пощата при промяна на страница или файл от списъка ми за наблюдение",
        "tog-enotifusertalkpages": "Уведомяване по е-пощата при промяна на беседата ми",
-       "tog-enotifminoredits": "УведомÑ\8fване Ð¿Ð¾ Ðµ-поÑ\89аÑ\82а Ð´Ð°Ð¶Ðµ Ð¿Ñ\80и Ð¼Ð°Ð»ÐºÐ¸ Ð¿Ñ\80омени Ð½Ð° Ñ\81Ñ\82Ñ\80аниÑ\86и Ð¸Ð»Ð¸ Ñ\84айлове",
+       "tog-enotifminoredits": "Уведомяване по е-пощата при малки промени на страници или файлове",
        "tog-enotifrevealaddr": "Показване на електронния ми адрес в известяващите писма",
        "tog-shownumberswatching": "Показване на броя на потребителите, наблюдаващи дадена страница",
        "tog-oldsig": "Текущ подпис:",
@@ -70,7 +70,7 @@
        "underline-always": "Винаги",
        "underline-never": "Никога",
        "underline-default": "Според настройките на облика или браузъра",
-       "editfont-style": "Стил на шрифта в кутията за редактиране",
+       "editfont-style": "Стил на шрифта в кутията за редактиране:",
        "editfont-default": "По подразбиране за браузъра",
        "editfont-monospace": "Равноширок шрифт",
        "editfont-sansserif": "Безсерифен шрифт",
        "userinvalidcssjstitle": "'''Внимание:''' Не съществува облик „$1“. Необходимо е да се знае, че имената на потребителските ви страници за CSS и Джаваскрипт трябва да се състоят от малки букви, например: „{{ns:user}}:Иван/vector.css“ (а не „{{ns:user}}:Иван/Vector.css“).",
        "updated": "(обновена)",
        "note": "'''Забележка:'''",
-       "previewnote": "'''Важно е да се помни, че това е само предварителен преглед. Промените все още не са съхранени!'''",
+       "previewnote": "<strong>Обърнете внимание, че това е само предварителен преглед.</strong>\nПромените все още не са съхранени!",
        "continue-editing": "Продължаване към полето за редактиране",
        "previewconflict": "Този предварителен преглед отразява текста в горната текстова кутия така, както би се показал, ако съхраните.",
        "session_fail_preview": "'''За съжаление редакцията ви не успя да бъде обработена поради загуба на данните за текущата сесия. Опитайте отново. Ако все още не работи, опитайте да [[Special:UserLogout|излезете]] и да влезете отново.'''",
        "content-failed-to-parse": "Неуспех при анализиране на съдържанието от тип $2 за модела $1: $3",
        "invalid-content-data": "Невалидни данни за съдържание",
        "content-not-allowed-here": "\nНа страницата [[$2]] не е позволено използването на $1",
-       "editwarning-warning": "Ако излезете от тази страница, може да загубите всички незапазени промени, които сте направили. \nАко сте влезли в системата, можете да изключите това предупреждение през меню \"Редактиране\" във вашите лични настройки.",
+       "editwarning-warning": "Ако излезете от тази страница, може да загубите всички несъхранени промени, които сте направили. \nАко сте влезли в системата, можете да изключите това предупреждение чрез менюто \"Редактиране\" в личните ви настройки.",
        "editpage-notsupportedcontentformat-title": "Форматът на съдържанието не се поддържа",
        "content-model-wikitext": "уикитекст",
        "content-model-text": "обикновен текст",
        "revdelete-legend": "Задаване на ограничения:",
        "revdelete-hide-text": "Текст на версията",
        "revdelete-hide-image": "Скриване на файловото съдържание",
-       "revdelete-hide-name": "Скриване на действието и целта",
+       "revdelete-hide-name": "Скриване на цели и параметри",
        "revdelete-hide-comment": "Скриване на резюмето",
        "revdelete-hide-user": "Потребителско име/IP адрес на редактора",
        "revdelete-hide-restricted": "Прилагане на тези ограничения и за администраторите",
        "movepagetalktext": "Ако съществува, съответната дискусионна страница ще бъде преместена автоматично заедно с нея, '''освен ако:'''\n* не местите страницата от едно именно пространство в друго,\n* вече съществува непразна дискусионна страница с това име или\n* не сте отметнали долната кутийка.\n\nВ тези случаи, ако желаете, ще е необходимо да преместите страницата ръчно.",
        "movearticle": "Преместване на страница:",
        "moveuserpage-warning": "'''Внимание:''' Предприели сте опит да преместите потребителска страница. Забележете, че от преместването на страницата '''няма''' да последва преименуване на потребителя.",
+       "movecategorypage-warning": "<strong>Внимание:</strong> На път сте да преместите категорийна страница. Моля, обърнете внимание, че ще бъде преместена само страницата на категорията. <em>Никоя</em> от страниците в старата категория <em>няма</em> да бъде прекатегоризирана.",
        "movenologintext": "Необходимо е да [[Special:UserLogin|влезете]], за да може да премествате страници.",
        "movenotallowed": "Нямате права за преместване на страници.",
        "movenotallowedfile": "Нямате права да премествате файлове.",
        "log-name-pagelang": "Дневник на езиковите промени",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (включено)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''изключено''')",
-       "mediastatistics": "Медиа статистики",
+       "mediastatistics": "Медия статистики",
        "mediastatistics-table-mimetype": "MIME тип",
        "mediastatistics-header-audio": "Аудио",
        "mediastatistics-header-video": "Видео",
index e9011cf..2a98592 100644 (file)
        "pool-queuefull": "পুলের লাইন পূর্ণ",
        "pool-errorunknown": "অজানা ত্রুটি",
        "pool-servererror": "পুল কাউন্টার সার্ভিস নিষ্ক্রিয় ($1)।",
+       "poolcounter-usage-error": "ব্যবহারের ত্রুটি: $1",
        "aboutsite": "{{SITENAME}} বৃত্তান্ত",
        "aboutpage": "Project:বৃত্তান্ত",
        "copyright": "বিষয়বস্তু $1-এর আওতায় প্রকাশিত যদি না অন্য কিছু নির্ধারিত থাকে।",
        "action-viewmyprivateinfo": "আপনার ব্যক্তিগত তথ্য দেখুন",
        "action-editmyprivateinfo": "আপনার ব্যক্তিগত তথ্য সম্পাদনা করুন",
        "nchanges": "$1টি {{PLURAL:$1|পরিবর্তন}}",
-       "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|সর্বশেষ প্রদর্শনের পর}}",
+       "enhancedrc-since-last-visit": "{{PLURAL:$1|সর্বশেষ প্রদর্শনের পর}} $1টি",
        "enhancedrc-history": "ইতিহাস",
        "recentchanges": "সাম্প্রতিক পরিবর্তনসমূহ",
        "recentchanges-legend": "সাম্প্রতিক পরিবর্তনের পছন্দসমূহ",
        "import-logentry-interwiki": "$1 উইকি-স্থানান্তরিত",
        "import-logentry-interwiki-detail": "$2-এর থেকে $1টি {{PLURAL:$1|সংশোধন}} করা হয়েছে",
        "javascripttest": "জাভাস্ক্রিপ্ট পরীক্ষা",
-       "javascripttest-title": "$1 পরীক্ষা চলছে",
        "javascripttest-pagetext-noframework": "এই পাতাটি জাভাস্ক্রিপ্ট পরীক্ষার জন্য সংরক্ষিত।",
        "javascripttest-pagetext-unknownframework": "পরীক্ষার অজানা ফ্রেমওয়ার্ক \"$1\"।",
        "javascripttest-pagetext-frameworks": "অনুগ্রহ করে নিচের কোনো একটি ফ্রেমওয়ার্ক নির্ধারণ করুন: $1",
        "javascripttest-pagetext-skins": "পরীক্ষার জন্য একটি স্কীন নির্ধারণ করুন:",
        "javascripttest-qunit-intro": "mediawiki.org থেকে [$1 পরীক্ষার ডলুমেন্টেশন] দেখুন।",
-       "javascripttest-qunit-heading": "মিডিয়াউইকি জাভাস্ক্রিপ্ট কিউইউনিট টেস্ট স্যুট",
        "tooltip-pt-userpage": "আপনার ব্যবহারকারী পাতা",
        "tooltip-pt-anonuserpage": "যে আইপি ঠিকানা থেকে আপনি সম্পাদনা করছেন, তার ব্যবহারকারী পাতা",
        "tooltip-pt-mytalk": "আপনার আলাপের পাতা",
        "version-entrypoints": "শুরুর ইউআরএল",
        "version-entrypoints-header-entrypoint": "শুরু",
        "version-entrypoints-header-url": "ইউআরএল",
+       "version-libraries-version": "সংস্করণ",
        "redirect": "পাতা, ফাইল, ব্যবহারকরী, অথবা সংশোধন আইডি দ্বারা পুনঃনির্দেশ করা হয়েছে",
        "redirect-legend": "একটি ফাইল অথবা পাতায় পুনঃনির্দেশ করা হয়েছে",
        "redirect-summary": "এই বিশেষ পাতাটি একটি ফাইলে (ফাইলের নাম), একটি পাতায় (সংস্করণ আইডি বা পাতা আইডি), অথবা একটি ব্যবহারকরী পাতায় (সংখ্যায় লেখা ব্যবহারকারী আইডি) পুনঃনির্দেশিত হয়েছে। ব্যবহার:  [[{{#Special:Redirect}}/file/উদাহরণ.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], অথবা [[{{#Special:Redirect}}/user/101]]।",
        "sqlite-no-fts": "$1 বাদে পূর্ণ টেক্সট সার্চ সমর্থন",
        "logentry-delete-delete": "$1 কর্তৃক $3 পাতাটি অপসারিত হয়েছে",
        "logentry-delete-restore": "$1 কর্তৃক $3 পাতাটি {{GENDER:$2|ফিরিয়ে আনা}} হয়েছে",
-       "logentry-delete-event": "$1 {{PLURAL:$5|à¦\8fà¦\95à¦\9fি à¦²à¦\97 à¦\87ভà§\87নà§\8dà¦\9fà§\87র|$5 à¦²à¦\97 à¦\87ভà§\87নà§\8dà¦\9fসমà§\82হà§\87র}} à¦­à¦¿à¦\9cিবিলিà¦\9fি {{GENDER:$2|পরিবর্তন}} করেছেন $3: $4",
-       "logentry-delete-revision": "$1 {{PLURAL:$5|একটি সংস্করণের|$5 সংস্করণসমূহের}} ভিজিবিলিটি {{GENDER:$2|পরিবর্তন}} করেছেন $3: $4",
-       "logentry-delete-event-legacy": "$1 $3à¦\9fায় à¦²à¦\97 à¦\87ভà§\87নà§\8dà¦\9fসমà§\82হà§\87র à¦­à¦¿à¦\9cিবিলিà¦\9fি {{GENDER:$2|পরিবর্তন}} করেছেন",
-       "logentry-delete-revision-legacy": "$1 $3à¦\9fায় à¦¸à¦\82সà§\8dà¦\95রণসমà§\82হà§\87র à¦­à¦¿à¦\9cিবিলিà¦\9fি {{GENDER:$2|পরিবর্তন}} করেছেন",
+       "logentry-delete-event": "$1 {{PLURAL:$5|à¦\8fà¦\95à¦\9fি à¦²à¦\97 à¦\87ভà§\87নà§\8dà¦\9fà§\87র|$5 à¦²à¦\97 à¦\87ভà§\87নà§\8dà¦\9fসমà§\82হà§\87র}} à¦¦à§\83শà§\8dযমানতা {{GENDER:$2|পরিবর্তন}} করেছেন $3: $4",
+       "logentry-delete-revision": "$1 {{PLURAL:$5|একটি সংস্করণের|$5টি সংস্করণের}} দৃশ্যমানতা {{GENDER:$2|পরিবর্তন}} করেছেন $3: $4",
+       "logentry-delete-event-legacy": "$1 $3à¦\9fায় à¦²à¦\97 à¦\87ভà§\87নà§\8dà¦\9fসমà§\82হà§\87র à¦¦à§\83শà§\8dযমানতা {{GENDER:$2|পরিবর্তন}} করেছেন",
+       "logentry-delete-revision-legacy": "$1 $3à¦\9fায় à¦¸à¦\82সà§\8dà¦\95রণসমà§\82হà§\87র à¦¦à§\83শà§\8dযমানতা {{GENDER:$2|পরিবর্তন}} করেছেন",
        "logentry-suppress-delete": "$1 কর্তৃক $3 পাতাটি {{GENDER:$2|ফিরিয়ে আনা}} হয়েছে",
-       "logentry-suppress-event": "$1 à¦\97à§\8bপনà§\87 {{PLURAL:$5|à¦\8fà¦\95à¦\9fি à¦²à¦\97 à¦\87ভà§\87নà§\8dà¦\9fà§\87র|$5 à¦²à¦\97 à¦\87ভà§\87নà§\8dà¦\9fসমà§\82হà§\87র}} à¦­à¦¿à¦\9cিবিলিà¦\9fি {{GENDER:$2|পরিবর্তন}} করেছেন $3: $4",
-       "logentry-suppress-revision": "$1 গোপনে {{PLURAL:$5|একটি সংস্করণের|$5 সংস্করণসমূহের}} ভিজিবিলিটি {{GENDER:$2|পরিবর্তন}} করেছেন $3: $4",
-       "logentry-suppress-event-legacy": "$1 à¦\97à§\8bপনà§\87 $3à¦\9fায় à¦²à¦\97 à¦\87ভà§\87নà§\8dà¦\9fসমà§\82হà§\87র à¦­à¦¿à¦\9cিবিলিà¦\9fি {{GENDER:$2|পরিবর্তন}} করেছেন",
-       "logentry-suppress-revision-legacy": "$1 à¦\97à§\8bপনà§\87 $3à¦\9fায় à¦¸à¦\82সà§\8dà¦\95রণসমà§\82হà§\87র à¦­à¦¿à¦\9cিবিলিà¦\9fি {{GENDER:$2|পরিবর্তন}} করেছেন",
+       "logentry-suppress-event": "$1 à¦\97à§\8bপনà§\87 {{PLURAL:$5|à¦\8fà¦\95à¦\9fি à¦²à¦\97 à¦\87ভà§\87নà§\8dà¦\9fà§\87র|$5 à¦²à¦\97 à¦\87ভà§\87নà§\8dà¦\9fসমà§\82হà§\87র}} à¦¦à§\83শà§\8dযমানতা {{GENDER:$2|পরিবর্তন}} করেছেন $3: $4",
+       "logentry-suppress-revision": "$1 গোপনে {{PLURAL:$5|একটি সংস্করণের|$5টি সংস্করণের}} দৃশ্যমানতা {{GENDER:$2|পরিবর্তন}} করেছেন $3: $4",
+       "logentry-suppress-event-legacy": "$1 à¦\97à§\8bপনà§\87 $3à¦\9fায় à¦²à¦\97 à¦\87ভà§\87নà§\8dà¦\9fসমà§\82হà§\87র à¦¦à§\83শà§\8dযমানতা {{GENDER:$2|পরিবর্তন}} করেছেন",
+       "logentry-suppress-revision-legacy": "$1 à¦\97à§\8bপনà§\87 $3à¦\9fায় à¦¸à¦\82সà§\8dà¦\95রণসমà§\82হà§\87র à¦¦à§\83শà§\8dযমানতা {{GENDER:$2|পরিবর্তন}} করেছেন",
        "revdelete-content-hid": "বিষয়বস্তু লুকায়িত",
        "revdelete-summary-hid": "সম্পাদনা সারাংশ লুকায়িত",
        "revdelete-uname-hid": "ব্যবহারকারী নাম লুকায়িত",
index af20be0..2a91aaa 100644 (file)
        "pool-queuefull": "La cua de treball és plena",
        "pool-errorunknown": "Error desconegut",
        "pool-servererror": "El servei de recompte de la reserva no és disponible ($1).",
+       "poolcounter-usage-error": "Error d'ús: $1",
        "aboutsite": "Quant al projecte {{SITENAME}}",
        "aboutpage": "Project:Quant a",
        "copyright": "El contingut està disponible sota la llicència $1 si no s'indica el contrari.",
        "history-feed-empty": "La pàgina demanada no existeix.\nPotser s'ha suprimit o reanomenat.\nIntenteu [[Special:Search|cercar al mateix wiki]] per a noves pàgines rellevants.",
        "rev-deleted-comment": "(resum d'edició eliminat)",
        "rev-deleted-user": "(s'ha suprimit el nom d'usuari)",
-       "rev-deleted-event": "(s'ha suprimit el registre d'accions)",
+       "rev-deleted-event": "(s'han suprimit els detalls del registre)",
        "rev-deleted-user-contribs": "[nom d'usuari o adreça IP esborrada - modificació ocultada de les contribucions]",
        "rev-deleted-text-permission": "S'ha '''suprimit''' aquesta versió de la pàgina.\nVegeu-ne més detalls al [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registre de supressions].",
        "rev-suppressed-text-permission": "S'ha '''suprimit''' aquesta versió de la pàgina.\nVegeu-ne més detalls al [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registre de supressions].",
        "import-logentry-interwiki": "s'ha importat $1 via interwiki",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisió|revisions}} importades de $2",
        "javascripttest": "Proves de JavaScript",
-       "javascripttest-title": "S'estan executant $1 proves",
        "javascripttest-pagetext-noframework": "Es reserva la pàgina per a l'execució de tests amb JavaScript.",
        "javascripttest-pagetext-unknownframework": "L'entorn de proves «$1» és desconegut.",
+       "javascripttest-pagetext-unknownaction": "Acció desconeguda «$1».",
        "javascripttest-pagetext-frameworks": "Trieu un dels següents entorns de prova: $1",
        "javascripttest-pagetext-skins": "Trieu un tema on executar-hi els tests:",
        "javascripttest-qunit-intro": "Consulteu la [documentació de tests de $1] a mediawiki.org.",
-       "javascripttest-qunit-heading": "Entorn de proves JavaScript QUnit per al MediaWiki",
        "tooltip-pt-userpage": "La vostra pàgina d'usuari",
        "tooltip-pt-anonuserpage": "La pàgina d'usuari per la ip que utilitzeu",
        "tooltip-pt-mytalk": "La vostra pàgina de discussió.",
        "version-entrypoints": "URL de punts d'entrada",
        "version-entrypoints-header-entrypoint": "Punt d'entrada",
        "version-entrypoints-header-url": "URL",
+       "version-libraries": "Biblioteques instal·lades",
+       "version-libraries-library": "Biblioteca",
+       "version-libraries-version": "Versió",
        "redirect": "Redirigeix per fitxer, usuari, pàgina o ID de la revisió",
        "redirect-legend": "Redirigeix a un fitxer o a una pàgina",
        "redirect-summary": "Aquesta pàgina especial redirigeix a un fitxer (donat el nom del fitxer), una pàgina (donats un ID de la revisió o un ID de pàgina), o a una pàgina d'usuari (donat un ID numèric d'usuari). Ús: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].",
        "compare-revision-not-exists": "La revisió que heu especificat no existeix.",
        "dberr-problems": "Ho sentim. Aquest lloc web està experimentant dificultats tècniques.",
        "dberr-again": "Intenteu esperar uns minuts i tornar a carregar.",
-       "dberr-info": "(No es pot contactar amb el servidor de dades: $1)",
-       "dberr-info-hidden": "(No es pot contactar amb el servidor de la base de dades)",
+       "dberr-info": "(No es pot accedir a la base de dades: $1)",
+       "dberr-info-hidden": "(No es pot accedir a la base de dades)",
        "dberr-usegoogle": "Podeu intentar fer la cerca via Google mentrestant.",
        "dberr-outofdate": "Tingueu en compte que la seva indexació del nostre contingut pot no estar actualitzada.",
        "dberr-cachederror": "A continuació hi ha una còpia emmagatzemada de la pàgina demanada, que pot no estar actualitzada.",
index cdce819..030722d 100644 (file)
        "allpagesprefix": "按頭部顯示頁面:",
        "allpagesbadtitle": "給出其頁面其標題是𣍐合法其,或者有蜀萆跨語言或跨維基其前綴。伊可能包括蜀萆或者価萆𣍐使廮標題裏勢其字符。",
        "categories": "類別",
-       "deletedcontributions": "乞刪其用戶貢獻",
-       "deletedcontributions-title": "乞刪其用戶貢獻",
+       "deletedcontributions": "乞刪其用戶貢獻",
+       "deletedcontributions-title": "乞刪其用戶貢獻",
        "linksearch-ok": "尋討",
        "linksearch-line": "$1是趁$2𡅏鏈接過其",
        "emailuser": "寄電子郵件乞茲隻用戶",
        "sp-contributions-newbies": "囇顯示新開賬戶其貢獻",
        "sp-contributions-newbies-sub": "才來其",
        "sp-contributions-blocklog": "封鎖日誌",
-       "sp-contributions-deleted": "開除來其用戶貢獻",
+       "sp-contributions-deleted": "乞刪唻其用戶貢獻",
        "sp-contributions-uploads": "上傳",
        "sp-contributions-logs": "日誌",
        "sp-contributions-talk": "討論",
index 63049a4..5ba5061 100644 (file)
        "viewsourcetext": "Хьоьга далундерг хьажар а дезахь хlокху агlон чура йоза хьаэцар:",
        "viewyourtext": "Хьан йиш ю '''хьой нисдинчу''' дӀадолалун йозе хьажа а цуна копи ян а:",
        "protectedinterface": "ХӀара схьгайтарна гӀирса хаамаш латтош йолу агӀо ю. Куьйгалхошна бен иза хийца цало.",
-       "editinginterface": "<strong>ТеÑ\80гам Ð±Ðµ:</strong> Ð\90Ñ\85Ñ\8cа Ñ\82аеÑ\88 Ñ\8e Ð¸Ð½Ñ\82еÑ\80Ñ\84ейÑ\81ан Ð¹Ð¾Ð·Ð° Ð´Ð¾Ð»Ñ\83 Ð°Ð³Ó\80о Ð¿Ñ\80огÑ\80амин Ð»Ð°Ñ\82Ñ\82оÑ\80ан.\nЦÑ\83на Ð±Ð¸Ð½Ð° Ñ\85ийÑ\86ам Ñ\85Ñ\8cокÑ\85Ñ\83 Ð²икипедин кхечу декъашхошна гур бу.",
+       "editinginterface": "<strong>ТеÑ\80гам Ð±Ðµ:</strong> Ð\90Ñ\85Ñ\8cа Ñ\82аеÑ\88 Ñ\8e Ð¸Ð½Ñ\82еÑ\80Ñ\84ейÑ\81ан Ð¹Ð¾Ð·Ð° Ð´Ð¾Ð»Ñ\83 Ð°Ð³Ó\80о Ð¿Ñ\80огÑ\80аммин Ð»Ð°Ñ\82Ñ\82оÑ\80ан.\nЦÑ\83на Ð±Ð¸Ð½Ð° Ñ\85ийÑ\86ам Ñ\85Ñ\8cокÑ\85Ñ\83 Ð\92икипедин кхечу декъашхошна гур бу.",
        "cascadeprotected": "АгӀо хийцам ца байта гӀоралла дина ю {{PLURAL:$1|хӀокху агӀона|хӀокху агӀонийн}} юкъа йогӀуш хилар бахьнехь:\n$2",
        "namespaceprotected": "ХӀан бакъо яц анна цӀераш чохь тадарш да «$1».",
        "customcssprotected": "Хьан бакъо яц хӀара CSS-агӀо тая, иза кхечу декъашхочун гӀерс болу дера.",
        "import-logentry-interwiki": "«$1» — викиюкъара импорт",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|верси импорт йина|версеш импорт йина}} $2 чура",
        "javascripttest": "JavaScript хьажар",
-       "javascripttest-title": "$1 хьожуш бу",
        "tooltip-pt-userpage": "Декъашхочуьна агlо",
        "tooltip-pt-mytalk": "Сан дийцаре агlо",
        "tooltip-pt-preferences": "Хьан гlирс нисбар",
index 39a0c03..ae6e5ef 100644 (file)
        "import-logentry-interwiki": "přenesl $1",
        "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.",
        "javascripttest-pagetext-unknownframework": "Neznámá testovací knihovna „$1“.",
+       "javascripttest-pagetext-unknownaction": "Neznámá akce „$1“.",
        "javascripttest-pagetext-frameworks": "Zvolte jednu z následujících testovacích knihoven: $1",
        "javascripttest-pagetext-skins": "Zvolte vzhled, pod kterým se mají testy spustit:",
        "javascripttest-qunit-intro": "Vizte [$1 dokumentaci testování] na mediawiki.org",
-       "javascripttest-qunit-heading": "Sada testů JavaScriptu v MediaWiki pomocí QUnit",
        "tooltip-pt-userpage": "Vaše uživatelská stránka",
        "tooltip-pt-anonuserpage": "Uživatelská stránka pro IP adresu, ze které editujete",
        "tooltip-pt-mytalk": "Vaše diskusní stránka",
        "version-entrypoints-header-url": "URL",
        "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Cesta k článkům]",
        "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Cesta ke skriptům]",
+       "version-libraries": "Nainstalované knihovny",
+       "version-libraries-library": "Knihovna",
+       "version-libraries-version": "Verze",
        "redirect": "Přesměrování podle souboru, uživatele, stránky nebo ID revize",
        "redirect-legend": "Přesměrování na soubor či stránku",
        "redirect-summary": "Tato speciální stránka přesměrovává na soubor (podle názvu), stránku (podle ID stránky nebo revize) nebo uživatele (podle číselného uživatelského ID). Použití: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]] nebo [[{{#Special:Redirect}}/user/101]].",
        "compare-revision-not-exists": "Zadaná revize neexistuje.",
        "dberr-problems": "Promiňte! Tento server má v tuto chvíli technické problémy.",
        "dberr-again": "Zkuste několik minut počkat a poté znovu načíst stránku.",
-       "dberr-info": "(Nelze navázat spojení s databázovým serverem: $1)",
-       "dberr-info-hidden": "(Nelze navázat spojení s databázovým serverem)",
+       "dberr-info": "(Nelze se připojit k databázi: $1)",
+       "dberr-info-hidden": "(Nelze se připojit k databázi)",
        "dberr-usegoogle": "Mezitím můžete zkusit hledat pomocí Google.",
        "dberr-outofdate": "Uvědomte si, že jejich vyhledávací index našeho obsahu může být zastaralý.",
        "dberr-cachederror": "Následující stránka je kopie z cache a nemusí být aktuální.",
index 229690a..4deb3ee 100644 (file)
@@ -39,7 +39,7 @@
        "tog-shownumberswatching": "Dangos y nifer o ddefnyddwyr sy'n gwylio",
        "tog-oldsig": "Y llofnod cyfredol:",
        "tog-fancysig": "Trin y llofnod fel testun wici (heb gyswllt wici awtomatig)",
-       "tog-uselivepreview": "Defnyddio rhagolwg byw (arbrofol)",
+       "tog-uselivepreview": "Defnyddio rhagolwg byw",
        "tog-forceeditsummary": "Tynnu fy sylw pan adawaf flwch crynodeb golygu yn wag",
        "tog-watchlisthideown": "Cuddio fy ngolygiadau fy hunan yn fy rhestr wylio",
        "tog-watchlisthidebots": "Cuddio golygiadau bot yn fy rhestr wylio",
        "otherlanguages": "Ieithoedd eraill",
        "redirectedfrom": "(Ailgyfeiriad oddi wrth $1)",
        "redirectpagesub": "Tudalen ailgyfeirio",
+       "redirectto": "Ailgyfeirio i:",
        "lastmodifiedat": "Newidiwyd y dudalen hon ddiwethaf $2, $1.",
        "viewcount": "{{PLURAL:$1|Ni chafwyd dim|Cafwyd $1|Cafwyd $1|Cafwyd $1|Cafwyd $1|Cafwyd $1}} ymweliad â'r dudalen hon.",
        "protectedpage": "Tudalen a ddiogelwyd",
        "jumptonavigation": "llywio",
        "jumptosearch": "chwilio",
        "view-pool-error": "Ymddiheurwn, mae gormod o waith gan y gweinyddion ar hyn o bryd.\nMae gormod o ddefnyddwyr am weld y dudalen hon ar unwaith.\nArhoswch ychydig cyn ceisio mynd at y dudalen hon eto.\n\n$1",
+       "generic-pool-error": "Drapia, mae'r gweinyddion dan gryn bwysau ar hyn o bryd.\nMae gormod o ddefnyddwyr yn ceisio gwneud yr un peth!\nDaliwch eich gafael am chydig funudau cyn mynd ati i geisio eto.",
        "pool-timeout": "Cafwyd goroedi wrth aros am y clo",
        "pool-queuefull": "Mae cwt y gronfa brosesu yn llawn",
        "pool-errorunknown": "Gwall anhysbys",
+       "poolcounter-usage-error": "Gwall defnydd: $1",
        "aboutsite": "Ynglŷn â {{SITENAME}}",
        "aboutpage": "Project:Amdanom",
        "copyright": "Rhoddir y cynnwys ar gael ar delerau'r drwydded $1, heblaw ei fod wedi nodi'n wahanol.",
        "hidetoc": "cuddio",
        "collapsible-collapse": "Crebacher",
        "collapsible-expand": "Ehanger",
+       "confirmable-confirm": "Wyt ti'n siwr?",
+       "confirmable-yes": "Ydw",
+       "confirmable-no": "Nac ydw",
        "thisisdeleted": "Ydych chi am ddangos, neu ddad-ddileu $1?",
        "viewdeleted": "Gweld $1?",
        "restorelink": "$1 {{PLURAL:$1|golygiad sydd wedi'i ddileu|golygiad sydd wedi'i ddileu|olygiad sydd wedi'u dileu|golygiad sydd wedi'u dileu|golygiad sydd wedi'u dileu|golygiad sydd wedi'u dileu}}",
        "viewsourcetext": "Cewch weld a chopïo côd y dudalen:",
        "viewyourtext": "Cewch weld a copïo ffynhonnell ''eich golygiadau'' i'r dudalen hon:",
        "protectedinterface": "Testun ar gyfer rhyngwyneb y wici yw cynnwys y dudalen hon. Clowyd y dudalen er mwyn ei diogeli. Os am gyfieithu'r neges neu ei newid ym mhob wici yn hytrach nag yn hwn yn unig, defnyddiwch [//translatewiki.net/ translatewiki.net], y prosiect MediaWiki sy'n hyrwyddo'r gwaith cyfieithu.",
-       "editinginterface": "'''Dalier sylw:''' Rydych yn golygu tudalen sy'n rhan o destun rhyngwyneb y meddalwedd. Bydd newidiadau i'r dudalen hon yn effeithio ar y rhyngwyneb a ddefnyddir ar y wici hwn yn unig. Os am gyfieithu'r neges rhagosodedig a ddefnyddir ar bob wici, ystyriwch ddefnyddio [//translatewiki.net/ translatewiki.net], sef y prosiect MediaWiki sy'n hyrwyddo creu rhyngwyneb amlieithog ar wicïau.",
+       "editinginterface": "<strong>Dalier sylw:</strong> Rydych yn golygu tudalen sy'n rhan o destun rhyngwyneb y meddalwedd. Bydd newidiadau i'r dudalen hon yn effeithio ar y rhyngwyneb a ddefnyddir ar y wici hwn yn unig.",
+       "translateinterface": "I ychwanegu neu newid y cyfieithiad ar gyfer pob wici, defnyddiwch [//translatewiki.net/ translatewiki.net], sef prosiect lleol MediaWiki.",
        "cascadeprotected": "Diogelwyd y dudalen hon rhag ei newid, oherwydd ei bod wedi ei chynnwys yn y {{PLURAL:$1|dudalen ganlynol|dudalen ganlynol|tudalennau canlynol|tudalennau canlynol|tudalennau canlynol|tudalennau canlynol}}, a {{PLURAL:$1|honno yn ei thro wedi ei|honno yn ei thro wedi ei|rheiny yn eu tro wedi eu|rheiny yn eu tro wedi eu|rheiny yn eu tro wedi eu|rheiny yn eu tro wedi eu}} diogelu, a'r dewisiad 'sgydol' ynghynn:\n$2",
        "namespaceprotected": "Nid oes caniatâd gennych i olygu tudalennau yn y parth '''$1'''.",
        "customcssprotected": "Nid oes caniatâd ganddoch i olygu'r dudalen CSS hon oherwydd bod gosodiadau personol defnyddiwr arall arno.",
        "invalidtitle-knownnamespace": "Teitl annilys o'r enw \"$3\" yn y parth \"$2\"",
        "invalidtitle-unknownnamespace": "Teitl annilys ag iddi'r rhif parth anhysbys $1 a'r enw \"$2\"",
        "exception-nologin": "Nid ydych wedi mewngofnodi",
-       "exception-nologin-text": "[[Special:Userlogin|Mewngofnodwch]] er mwyn gweld y dudalen neu gyflawni'r weithred.",
+       "exception-nologin-text": "Mewngofnodwch er mwyn gweld y dudalen neu gyflawni'r weithred.",
        "exception-nologin-text-manual": "Mae angen $1 er mwyn gweld y dudalen neu gyflawni'r weithred.",
        "virus-badscanner": "Cyfluniad gwael: sganiwr firysau anhysbys: ''$1''",
        "virus-scanfailed": "methodd y sgan (côd $1)",
        "createaccount-text": "Creodd rhywun gyfrif o'r enw $2 ar {{SITENAME}} ($4) ar gyfer y cyfeiriad e-bost hwn. \"$3\" yw'r cyfrinair ar gyfer \"$2\". Dylech fewngofnodi a newid eich cyfrinair yn syth.\n\nRhydd ichi anwybyddu'r neges hon os mai camgymeriad oedd creu'r cyfrif.",
        "login-throttled": "Rydych wedi ceisio mewngofnodi gormod o weithiau ar ben ei gilydd.\nOedwch $1 cyn mentro eto.",
        "login-abort-generic": "Ni lwyddodd y mewngofnodi - Rhoddwyd y gorau iddo",
+       "login-migrated-generic": "Trosglwyddwyd eich cyfrif ac nid yw eich enw defnyddiwr bellach yn bodoli ar y wici hwn.",
        "loginlanguagelabel": "Iaith: $1",
        "suspicious-userlogout": "Gwrthodwyd eich cais i allgofnodi oherwydd ei fod yn ymddangos mai gweinydd wedi torri neu ddirprwy gelc a anfonodd y cais.",
        "createacct-another-realname-tip": "Gallwch ddewis roi eich enw go iawn.\nOs y gwnewch, fe gaiff yr enw go iawn ei defnyddio wrth dadogi'ch gwaith.",
        "resetpass-abort-generic": "Mae estyniad wedi atal newid y cyfrinair.",
        "resetpass-expired": "Mae oes eich cyfrinair wedi dod i ben. Gosodwch gyfrinair newydd i fewngofnodi.",
        "resetpass-expired-soft": "Mae eich cyfrinair wedi dod i ben ac mae'n rhaid ei ailosod. Dewisiwch gyfrinair newydd sbon nawr, neu cliciwch \"{{int:resetpass-submit-cancel}}\" a'i ailosod rywdro eto.",
+       "resetpass-validity-soft": "Nid yw eich cyfrinair $1 yn dal ddilys.\n\nDewisiwch gyfrinair newydd nawr, neu gliciwch \"{{int:resetpass-submit-cancel}}\" i'w ailosod yn nes ymlaen.",
        "passwordreset": "Ailosod cyfrinair",
        "passwordreset-text-one": "Cwblhewch y ffurflen hon er mwyn ailosod eich cyfrinair.",
        "passwordreset-text-many": "{{PLURAL:$1|Llanwch un o'r blychau er mwyn derbyn cyfrinair dros dro mewn ebost.}}",
        "preview": "Rhagolwg",
        "showpreview": "Dangos rhagolwg",
        "showdiff": "Dangos newidiadau",
-       "anoneditwarning": "'''Dalier sylw''': Nid ydych wedi mewngofnodi. Fe fydd eich cyfeiriad IP yn ymddangos ar hanes golygu'r dudalen hon. Gallwch ddewis cuddio'ch cyfeiriad IP drwy greu cyfrif (a mewngofnodi) cyn golygu.",
+       "blankarticle": "<strong>Gan bwyll:</strong> Mae'r dudalen rydych yn ei chreu'n wag. Os cliciwch \"{{int:savearticle}}\" eto, yna caiff y dudalen ei chreu heb unrhyw gynnwys ynddi.",
+       "anoneditwarning": "<strong>Dalier sylw</strong>: Nid ydych wedi mewngofnodi. Fe fydd eich cyfeiriad IP yn ymddangos ar hanes golygu'r dudalen hon. Gallwch ddewis cuddio'ch cyfeiriad IP drwy greu cyfrif (a mewngofnodi) cyn golygu.",
        "anonpreviewwarning": "''Nid ydych wedi mewngofnodi. Os y cadwch eich newidiadau caiff eich cyfeiriad IP ei gofnodi yn hanes golygu'r dudalen hon.''",
        "missingsummary": "'''Sylwer:''' Nid ydych wedi gosod nodyn yn y blwch 'Crynodeb'.\nOs y pwyswch eto ar 'Cadw'r dudalen' caiff y golygiad ei gadw heb nodyn.",
+       "selfredirect": "<strong>Gofal:</strong> Rydych yn ailgyfeirio'r dudalen hon ati hi ei hun!  Gwirwch yr hyn rydych yn ceisio'i wneud. Os cliciwch \"{{int:savearticle}}\" eto yna caiff y dudalen ailgyfeirio (wallus!) ei chreu beth bynnag.",
        "missingcommenttext": "Rhowch eich sylwadau isod.",
        "missingcommentheader": "'''Nodyn:''' Nid ydych wedi cynnig unrhywbeth yn y blwch 'Pwnc/Pennawd:'. Os y cliciwch \"{{int:savearticle}}\" eto fe gedwir y golygiad heb bennawd.",
        "summary-preview": "Rhagolwg o'r crynodeb:",
        "edit-gone-missing": "Ni ellid diweddaru'r dudalen.\nYmddengys iddi gael ei dileu.",
        "edit-conflict": "Cyd-ddigwyddiad golygu.",
        "edit-no-change": "Anwybyddwyd eich golygiad, gan na newidiwyd y testun.",
+       "postedit-confirmation-created": "Crewyd y dudalen.",
+       "postedit-confirmation-restored": "Adferwyd y dudalen.",
        "postedit-confirmation-saved": "Rhoddwyd eich golygiad ar gadw.",
        "edit-already-exists": "Ni ellid creu tudalen newydd.\nMae ar gael yn barod.",
        "defaultmessagetext": "Y testun rhagosodedig",
        "content-model-text": "testun plaen",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
+       "content-json-empty-object": "Dim gwrthrych",
+       "content-json-empty-array": "Rhesi gwag",
+       "duplicate-args-category": "Tudalennau gyda meysydd deublyg yn y Nodion",
+       "duplicate-args-category-desc": "Mae'r dudalen hon yn cynnwys meysydd yn y Nodion, ddwy waith e.e.  <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> neu <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "'''Rhybudd:''' Mae gormod o alwadau ar ffwythiannau dosrannu sy'n dreth ar adnoddau yn y dudalen hon.\n\nDylai fod llai na $2 {{PLURAL:$2|galwad|alwad|alwad|galwad}} yn y dudalen, ond ar hyn o bryd mae $1 {{PLURAL:$1|galwad|alwad|alwad|galwad}} ynddi.",
        "expensive-parserfunction-category": "Tudalennau a gormod o alwadau ar ffwythiannau dosrannu sy'n dreth ar adnoddau",
        "post-expand-template-inclusion-warning": "'''Rhybudd:''' Mae maint y nodiadau ar ôl eu chwyddo yn rhy fawr.\nNi chaiff rhai nodiadau eu cynnwys.",
        "parser-template-recursion-depth-warning": "Wedi mynd dros ben y terfyn ar ddyfnder dychweliad nodiadau ($1)",
        "language-converter-depth-warning": "Wedi mynd tu hwnt i'r terfyn dyfnder ($1) ar y cyfnewidydd iaith.",
        "node-count-exceeded-category": "Tudalennau lle mae nifer y nodau yn ormod",
+       "node-count-exceeded-category-desc": "Rydych wedi mynd dros y mwyafswm a ganiateir.",
        "node-count-exceeded-warning": "Mae nifer y nodau yn y dudalen yn ormod",
        "expansion-depth-exceeded-category": "Tudalennau â dyfnder ehangu tu hwnt i'r terfyn",
+       "expansion-depth-exceeded-category-desc": "Mae'r dudalen yn rhy fawr!",
        "expansion-depth-exceeded-warning": "Mae dyfnder ehangu'r dudalen y tu hwnt i'r terfyn",
        "parser-unstrip-loop-warning": "Wedi darganfod dolen dad-blicio (unstrip loop)",
        "parser-unstrip-recursion-limit": "Wedi mynd dros ben y terfyn ar ddychweliad dad-blicio (unstrip recursion) ($1)",
        "currentrev": "Diwygiad cyfoes",
        "currentrev-asof": "Y diwygiad cyfredol, am $1",
        "revisionasof": "Diwygiad $1",
-       "revision-info": "Y fersiwn a roddwyd ar gadw am $1 gan $2",
+       "revision-info": "Fersiwn a roddwyd ar gadw am $1 gan $2",
        "previousrevision": "← At y diwygiad blaenorol",
        "nextrevision": "At y diwygiad dilynol →",
        "currentrevisionlink": "Y diwygiad cyfoes",
        "history-feed-empty": "Nid yw'r dudalen a ofynwyd amdani'n bod.\nGall fod iddi gael ei dileu neu ei hailenwi.\nGallwch [[Special:Search|chwilio'r]] wici am dudalennau eraill perthnasol.",
        "rev-deleted-comment": "(dilëwyd crynodeb y golygiad)",
        "rev-deleted-user": "(enw defnyddiwr wedi ei ddiddymu)",
-       "rev-deleted-event": "(tynnwyd gweithred y lòg)",
+       "rev-deleted-event": "(tynnwyd manylion y lòg)",
        "rev-deleted-user-contribs": "[tynnwyd enw defnyddiwr neu gyfeiriad IP i ffwrdd - ni ddangosir y golygiad ar y rhestr gyfraniadau]",
        "rev-deleted-text-permission": "'''Dilëwyd''' y diwygiad hwn o'r dudalen.\nMae manylion ar gael yn y [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} lòg dileuon].",
+       "rev-suppressed-text-permission": "Mae'r drafft yma wedi'i <strong>atal</strong>.\nCeir rhagor o fanylion yn y [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} log atal].",
        "rev-deleted-text-unhide": "Cafodd y diwygiad hwn o'r dudalen ei '''ddileu'''.\nGweler cofnod y dileu ar y [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} lòg dileu].\nOnd gallwch chi [$1 weld y diwygiad] o hyd os y mynnwch.",
        "rev-suppressed-text-unhide": "Mae’r diwygiad hwn o’r dudalen wedi cael ei '''guddio'''.\nCewch weld y manylion ar y [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} lòg cuddio].\nCewch dal [$1 weld y golygiad] os y mynwch.",
        "rev-deleted-text-view": "'''Dilëwyd''' y diwygiad hwn o'r dudalen.\nGallwch ei weld; mae manylion ar gael yn y [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} lòg dileuon].",
        "revdelete-selected-text": "Dewisiwyd y {{PLURAL:$1|diwygiad|diwygiad|diwygiadau}} canlynol o [[:$2]]:",
        "revdelete-selected-file": "Dewiswyd y {{PLURAL:$1|diwygiad|diwygiad|diwygiadau}} canlynol o'r ffeil [[:$2]]:",
        "logdelete-selected": "{{PLURAL:$1|Digwyddiad|Digwyddiad|Digwyddiadau}} a ddewiswyd o'r lòg:",
+       "revdelete-text-text": "Bydd y golygiadau a ddilewyd yn dal i ymddangos yn hanes y dudalen, ond ni fydd y cyhoedd yn medru gweld rhannau ohonynt.",
+       "revdelete-text-file": "Bydd fersiynau gwahanol o'r ffeiliau'n dal i ymddangos yn hanes y dudalen, ond ni fydd y cyhoedd yn medru gweld rhannau ohonynt.",
+       "logdelete-text": "Bydd y log o weithrdoedd a ddilewyd yn dal i ymddangos yn y logs, ond ni fydd y cyhoedd yn medru gweld rhannau ohonynt.",
+       "revdelete-text-others": "Bydd gweinyddwyr eraill yn parhau i weld y manylion a guddiwyd a'u hailalw, oni bai eich bod yn gosod cyfyngiadau ychwanegol.",
        "revdelete-confirm": "Byddwch gystal â chadarnhau eich bod yn bwriadu gwneud hyn, eich bod yn deall yr effaith a gaiff, a'ch bod yn ei wneud yn ôl y [[{{MediaWiki:Policy-url}}|y polisi]].",
        "revdelete-suppress-text": "'''Dim ond''' yn yr achosion sy'n dilyn y dylech fentro cuddio gwybodaeth:\n* Gwybodaeth a all fod yn enllib\n* Gwybodaeth bersonol anaddas\n*: ''cyfeiriad cartref, rhif ffôn, rhif yswiriant cenedlaethol, ayb.''",
        "revdelete-legend": "Gosod cyfyngiadau ar y gallu i weld",
        "revdelete-hide-text": "Testun y diwygiad",
        "revdelete-hide-image": "Cuddio cynnwys y ffeil",
-       "revdelete-hide-name": "Cuddio'r weithred a'r targed",
+       "revdelete-hide-name": "Cuddio'r targed a'r paramedr",
        "revdelete-hide-comment": "Sylw golygu",
        "revdelete-hide-user": "Enw defnyddiwr/IP y golygydd",
        "revdelete-hide-restricted": "Gosod y cyfyngiadau gweld data ar weinyddwyr yn ogystal ag eraill",
        "search-result-category-size": "{{PLURAL:$1|$1 aelod}} ({{PLURAL:$2|$2 is-gategori}}, {{PLURAL:$3|$3 ffeil}})",
        "search-redirect": "(ailgyfeiriad $1)",
        "search-section": "(adran $1)",
+       "search-category": "(categori $1)",
        "search-file-match": "(yn cyfateb i gynnwys y ffeil)",
        "search-suggest": "Ai am hyn y chwiliwch: $1",
        "search-interwiki-caption": "Chwaer-brosiectau",
        "searchall": "oll",
        "showingresults": "Yn dangos $1 {{PLURAL:$1|canlyniad|canlyniad|ganlyniad|chanlyniad|chanlyniad|canlyniad}} isod gan ddechrau gyda rhif '''$2'''.",
        "showingresultsinrange": "Yn dangos hyd at {{PLURAL:$1||<strong>1</strong> canlyniad|<strong>$1</strong> ganlyniad|$1 o ganlyniadau}} isod yn yr ystod #<strong>$2</strong> i #<strong>$3</strong>.",
+       "search-showingresults": "{{PLURAL:$4|Result <strong>$1</strong> of <strong>$3</strong>|Canlyniadau: <strong>$1 - $2</strong> o <strong>$3</strong>}}",
        "search-nonefound": "Ni chafwyd dim canlyniadau i'r ymholiad.",
        "powersearch-legend": "Chwiliad uwch",
        "powersearch-ns": "Chwilio yn y parthau:",
        "powersearch-togglelabel": "Dewis:",
        "powersearch-toggleall": "Oll",
        "powersearch-togglenone": "Dim un",
+       "powersearch-remember": "Cofio'r dewis ar gyfer archwiliadau'r dyfodol",
        "search-external": "Chwiliad allanol",
        "searchdisabled": "Mae'r teclyn chwilio ar {{SITENAME}} wedi'i analluogi dros dro.\nYn y cyfamser gallwch chwilio drwy Google.\nCofiwch y gall mynegeion Google o gynnwys {{SITENAME}} fod ar ei hôl hi.",
        "search-error": "Cafwyd gwall wrth chwilio: $1",
        "preferences": "Dewisiadau",
        "mypreferences": "Dewisiadau",
        "prefs-edits": "Nifer y golygiadau:",
-       "prefsnologintext2": "Mae angen $1 er mwyn gosod eich dewisiadau personol.",
+       "prefsnologintext2": "Mewngofnodwch er mwyn newid eich dewisiadau.",
        "prefs-skin": "Gwedd",
        "skin-preview": "Rhagolwg",
        "datedefault": "Dim dewisiad",
        "gender-female": "Mae hi'n golygu tudalennau wici",
        "prefs-help-gender": "Nid oes rhaid llanw'r dewis yma. \nMae'r meddalwedd yn defnyddio hwn i gyfeirio atoch ac i'ch cyfarch yn ôl eich rhyw.\nMae'r wybodaeth hon ar gael i'r cyhoedd.",
        "email": "E-bost",
-       "prefs-help-realname": "* Enw iawn (dewisol): Os ydych yn dewis ei roi, fe fydd yn cael ei ddefnyddio er mwyn rhoi cydnabyddiaeth i chi am eich gwaith.",
+       "prefs-help-realname": "* Enw iawn yn ddewisol.\nOs ydych yn dewis ei roi, fe fydd yn cael ei ddefnyddio er mwyn rhoi cydnabyddiaeth i chi am eich gwaith.",
        "prefs-help-email": "Os ydych yn dewis gosod eich cyfeiriad e-bost yna gallwn anfon cyfrinair newydd atoch os aiff yr un gwreiddiol yn angof gennych.",
        "prefs-help-email-others": "Gallwch hefyd adael i eraill anfon e-bost atoch trwy'r cyswllt ar eich tudalen defnyddiwr neu eich tudalen sgwrs, heb ddatguddio'ch manylion personol.",
        "prefs-help-email-required": "Cyfeiriad e-bost yn angenrheidiol.",
        "prefs-tokenwatchlist": "Tocyn",
        "prefs-diffs": "Cymharu golygiadau ('gwahan')",
        "prefs-help-prefershttps": "Bydd y dewis yma'n cael ei roi ar waith y tro nesaf i chi fewngofnodi.",
+       "prefswarning-warning": "Rydych wedi newid eich Dewisiadau, ac nid ydynt eto wedi'u cadw.\nOs gadewch y dudalen hon heb glicio \"$1\" yna fe gollwch y newidiadau hyn.",
        "prefs-tabs-navigation-hint": "Awgrym: Gallwch ddefnyddio'r allweddellau sy'n saethau i'r chwith neu i'r dde i lywio rhwng y tabiau ar restr y tabiau.",
        "email-address-validity-valid": "Y cyfeiriad e-bost yn ymddangos yn un dilys",
        "email-address-validity-invalid": "Rhowch gyfeiriad e-bost dilys",
        "right-move": "Symud tudalennau",
        "right-move-subpages": "Symud tudalennau gyda'u his-dudalennau",
        "right-move-rootuserpages": "Symud prif dudalennau defnyddwyr",
+       "right-move-categorypages": "Symud tudalennau categori",
        "right-movefile": "Symud ffeiliau",
        "right-suppressredirect": "Peidio â chreu ailgyfeiriad o'r hen enw wrth symud tudalen",
        "right-upload": "Uwchlwytho ffeiliau",
        "right-deletedtext": "Gweld ysgrifen sydd wedi ei ddileu a newidiadau rhwng fersiynau ar ôl eu dileu",
        "right-browsearchive": "Chwilio drwy tudalennau dilëedig",
        "right-undelete": "Adfer tudalen dilëedig",
-       "right-suppressrevision": "Adolygu ac adfer diwygiadau sydd wedi eu cuddio rhag gweinyddwyr",
+       "right-suppressrevision": "Gweld, cuddio a datguddio adolygiadau arbennig o dudalennau, o olwg pob defnyddiwr.",
+       "right-viewsuppressed": "Gweld adolygiadau sydd wedi eu cuddio",
        "right-suppressionlog": "Gweld logiau preifat",
        "right-block": "Atal defnyddwyr eraill rhag golygu",
        "right-blockemail": "Atal defnyddiwr rhag anfon e-bost",
        "action-move": "symud y dudalen",
        "action-move-subpages": "symud y dudalen a'i is-dudalennau",
        "action-move-rootuserpages": "symud prif dudalennau defnyddwyr",
+       "action-move-categorypages": "symud y tudalennau categori",
        "action-movefile": "symud y ffeil hon",
        "action-upload": "uwchlwytho'r ffeil",
        "action-reupload": "trosysgrifo ffeil sydd eisoes ar gael",
        "recentchanges-legend-heading": "'''Allwedd:'''",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (gweler hefyd [[Special:NewPages|restr y tudalennau newydd]])",
        "recentchanges-legend-plusminus": "(''±123'')",
-       "rcnotefrom": "Isod rhestrir pob newid er <strong>'''$2'''</strong> (ymddengys hyd at <strong>'''$1'''</strong> ohonynt).",
+       "rcnotefrom": "Isod rhestrir pob newid er <strong>$3, $4</strong> (ymddengys <strong>$1</strong> ohonynt).",
        "rclistfrom": "Dangos newidiadau newydd, gan ddechrau ers $3 $2",
        "rcshowhideminor": "$1 golygiadau bychain",
        "rcshowhideminor-show": "Dangoser",
        "windows-nonascii-filename": "Nid yw'r wici hwn yn cynnal enwau ffeiliau sy'n cynnwys nodau arbennig.",
        "fileexists": "Mae ffeil gyda'r enw hwn eisoes yn bodoli; gwiriwch <strong>[[:$1]]</strong> os nad ydych yn sicr bod angen ei newid.\n[[$1|thumb]]",
        "filepageexists": "Mae tudalen ddisgrifiad ar gyfer y ffeil hon eisoes ar gael ar <strong>[[:$1]]</strong>, ond nid oes ffeil o'r enw hwn ar gael ar hyn o bryd.\nNi fydd crynodeb a osodir wrth uwchlwytho yn ymddangos ar y dudalen ddisgrifiad.\nEr mwyn gwneud i'r crynodeb ymddangos yno, bydd raid i chi olygu'r dudalen ddisgrifiad yn unswydd.\n[[$1|thumb]]",
-       "fileexists-extension": "Mae ffeil ag enw tebyg eisoes yn bod: [[$2|thumb]]\n* Enw'r ffeil ar fin ei uwchlwytho: <strong>[[:$1]]</strong>\n* Enw'r ffeil sydd eisoes yn bod: <strong>[[:$2]]</strong>\nDewiswch enw arall os gwelwch yn dda.",
+       "fileexists-extension": "Mae ffeil ag enw tebyg eisoes yn bod: [[$2|thumb]]\n* Enw'r ffeil ar fin ei uwchlwytho: <strong>[[:$1]]</strong>\n* Enw'r ffeil sydd eisoes yn bod: <strong>[[:$2]]</strong>\nYdych chi am ddewis enw mwy manwl?",
        "fileexists-thumbnail-yes": "Ymddengys bod delwedd wedi ei leihau ''(bawd)'' ar y ffeil. [[$1|thumb]]\nCymharwch gyda'r ffeil <strong>[[:$1]]</strong>.\nOs mai'r un un llun ar ei lawn faint sydd ar yr ail ffeil yna does dim angen uwchlwytho llun ychwanegol o faint bawd.",
        "file-thumbnail-no": "Mae <strong>$1</strong> ar ddechrau enw'r ffeil.\nMae'n ymddangos felly bod y ddelwedd wedi ei leihau ''(maint bawd)''.\nOs yw'r ddelwedd ar ei lawn faint gallwch barhau i'w uwchlwytho. Os na, newidiwch enw'r ffeil, os gwelwch yn dda.",
        "fileexists-forbidden": "Mae ffeil gyda'r enw hwn eisoes ar gael, ac ni ellir ei throsysgrifo.\nOs ydych am uwchlwytho'ch ffeil, ewch nôl ac uwchlwythwch hi ac enw newydd arni.\n[[File:$1|thumb|center|$1]]",
        "license": "Trwyddedu:",
        "license-header": "Trwyddedu",
        "nolicense": "Heb ddewis trwydded",
+       "licenses-edit": "Golygu deisiadau twryddedu",
        "license-nopreview": "(Dim rhagolwg ar gael)",
-       "upload_source_url": " (URL dilys, ar gael i'r cyhoedd)",
-       "upload_source_file": " (ffeil ar eich cyfrifiadur)",
+       "upload_source_url": "(y ffeil rydych wedi'i dewis o URL cyhoeddus)",
+       "upload_source_file": "(y ffeil rydych wedi'i dewis o'ch cyfrifiadur)",
+       "listfiles-delete": "dileu",
        "listfiles-summary": "Rhestr yr holl ffeiliau sydd wedi eu huwchlwytho sydd ar y dudalen hon.",
        "listfiles_search_for": "Chwilio am enw'r ddelwedd:",
        "imgfile": "ffeil",
        "filedelete-maintenance": "Mae'r gallu i ddileu ffeiliau a'u hadfer wedi ei anallogi tra bod gwaith cynnal wrthi.",
        "filedelete-maintenance-title": "Ni ellir dileu'r ffeil",
        "mimesearch": "Chwiliad MIME",
-       "mimesearch-summary": "Fe allwch ddefnyddio'r dudalen hon i hidlo'r ffeiliau yn ôl eu math MIME.\nMewnbwn: contenttype/subtype, e.e. <code>image/jpeg</code>.",
+       "mimesearch-summary": "Fe allwch ddefnyddio'r dudalen hon i hidlo'r ffeiliau yn ôl eu math MIME.\nMewnbwn: contenttype/subtype neu contenttype/*, e.e. <code>image/jpeg</code>.",
        "mimetype": "Ffurf MIME:",
        "download": "islwytho",
        "unwatchedpages": "Tudalennau sydd â neb yn eu gwylio",
        "listredirects": "Rhestru'r ail-gyfeiriadau",
        "listduplicatedfiles": "Rhestr y ffeiliau sydd wedi eu dyblygu",
+       "listduplicatedfiles-summary": "Dim ond ffeiliau lleol a gaiff eu hystyried.",
+       "listduplicatedfiles-entry": "Mae [[:File:$1|$1]] yn ddeublyg.",
        "unusedtemplates": "Nodiadau heb eu defnyddio",
        "unusedtemplatestext": "Dyma restr o'r holl dudalennau yn y parth {{ns:template}} nad ydynt wedi eu cynnwys yn unrhyw dudalen arall.\nCofiwch chwilio am gysylltiadau eraill at nodyn a'u hystyried cyn ei ddileu.",
        "unusedtemplateswlh": "cysylltiadau eraill",
        "randomincategory": "Tudalen ar hap o blith tudalennau'r categori",
        "randomincategory-invalidcategory": "Nid yw \"$1\" yn enw dilys i gategori.",
        "randomincategory-nopages": "Nid oes unrhyw dudalennau yn y categori [[:Category:$1]].",
+       "randomincategory-category": "Categori:",
+       "randomincategory-legend": "Tudalen ar hap o blith tudalennau'r categori",
        "randomredirect": "Tudalen ailgyfeirio ar hap",
        "randomredirect-nopages": "Does dim tudalennau ailgyfeirio yn y parth \"$1\".",
        "statistics": "Ystadegau",
        "wantedpages-badtitle": "Mae teitl annilys ymhlith y canlyniadau, sef: $1",
        "wantedfiles": "Ffeiliau sydd eu hangen",
        "wantedfiletext-cat": "Mae'r ffeiliau canlynol yn cael eu defnyddio er nad ydynt ar gael. Hwyrach bod ffeiliau o storfeydd allanol hefyd ar y rhestr, serch eu bod ar gael. Bydd y rhain, sydd wedi eu cynnwys yma yn anghywir, yn ymddangos a <del>llinell drwyddynt</del>. Hefyd, mae rhestr o dudalennau sydd a ffeiliau nad ydynt ar gael arnynt draw ar [[:$1]].",
+       "wantedfiletext-cat-noforeign": "Mae'r ffeiliau canlynol yn cael eu defnyddio ond nid ydynt yn bodoli. Yn ychwanegol i hyn, mae tudalen sy'n embedio ffeiliau nad ydynt yn bodoli yn cael eu rhestru yn [[:$1]].",
        "wantedfiletext-nocat": "Mae'r ffeiliau canlynol yn cael eu defnyddio er nad ydynt ar gael. Hwyrach bod ffeiliau o storfeydd allanol hefyd ar y rhestr, serch eu bod ar gael. Bydd y rhain, sydd wedi eu cynnwys yma yn anghywir, yn ymddangos a <del>llinell drwyddynt</del>.",
+       "wantedfiletext-nocat-noforeign": "Mae'r ffeiliau canlynol yn cael eu defnyddio ond nid ydynt yn bodoli.",
        "wantedtemplates": "Nodiadau sydd eu hangen",
        "mostlinked": "Tudalennau yn nhrefn nifer y cysylltiadau iddynt",
        "mostlinkedcategories": "Categorïau yn nhrefn nifer eu haelodau",
        "deadendpagestext": "Nid oes cysylltiad yn arwain at dudalen arall oddi wrth yr un o'r tudalennau isod.",
        "protectedpages": "Tudalennau wedi eu diogelu",
        "protectedpages-indef": "A ddiogelwyd yn ddi-derfyn yn unig",
+       "protectedpages-summary": "Mae'r dudalen hon yn rhestru tudalennau sydd wedi'u gwarchod. Am restr o'r teitlau sydd wedi'u gwarchod ers eu creu, gweler see [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "A sgydol-ddiogelwyd yn unig",
        "protectedpages-noredirect": "Cuddio ailgyfeiriadau",
        "protectedpagesempty": "Does dim tudalennau wedi eu diogelu gyda'r paramedrau hyn.",
        "pager-older-n": "{{PLURAL:$1|y $1 cynharach|yr $1 cynharach|y $1 cynharach|y $1 cynharach|y $1 cynharach|y $1 cynharach}}",
        "suppress": "Goruchwylio",
        "querypage-disabled": "Analluogwyd y dudalen arbennig hon er mwyn osgoi iddi andwyo perfformiad y wefan.",
+       "apihelp": "Cymorth API",
+       "apihelp-no-such-module": "Ni chafwyd hyd i fodiwl \"$1\".",
        "booksources": "Ffynonellau llyfrau",
        "booksources-search-legend": "Chwilier am lyfrau",
+       "booksources-search": "Chwilio",
        "booksources-text": "Mae'r rhestr isod yn cynnwys cysylltiadau i wefannau sy'n gwerthu llyfrau newydd a rhai ail-law. Mae rhai o'r gwefannau hefyd yn cynnig gwybodaeth pellach am y llyfrau hyn:",
        "booksources-invalid-isbn": "Ymddengys nad yw'r rhif ISBN hwn yn ddilys; efallai y cafwyd gwall wrth drosglwyddo'r rhif.",
        "specialloguserlabel": "Gwneuthurwr:",
        "listgrouprights-removegroup-self": "Yn gallu tynnu {{PLURAL:$2|grŵp}} oddi ar eich cyfrif eich hunan: $1",
        "listgrouprights-addgroup-self-all": "Yn gallu ychwanegu'r holl grwpiau at eich cyfrif eich hunan",
        "listgrouprights-removegroup-self-all": "Yn gallu tynnu'r holl grwpiau oddi ar eich cyfrif eich hunan",
+       "listgrouprights-namespaceprotection-header": "Cyfyngiadau parth",
        "listgrouprights-namespaceprotection-namespace": "Parth",
        "listgrouprights-namespaceprotection-restrictedto": "Gallu(oedd) yn caniatau i'r defnyddiwr olygu",
+       "trackingcategories": "Categoriau tracio",
+       "trackingcategories-summary": "Mae'r dudalen hon yn rhestru categoriau tracio sy'n cael eu creu'n otomatig gan feddalwedd MediaWiki. Gellir newid eu henwau drwy addasu'r negeseuon ym mharthenw {{ns:8}}.",
+       "trackingcategories-msg": "Categori tracio",
        "trackingcategories-name": "Enw'r neges",
+       "trackingcategories-desc": "Meincnodau derbyn categori",
+       "noindex-category-desc": "ni chaiff y dudalen ymweliad gan robot gan ei bod yn cynnwys y gair lledrith <code><nowiki>__NOINDEX__</nowiki></code> ynddi.",
+       "post-expand-template-inclusion-category-desc": "Mae maint y dudalen yn fwy na <code>$wgMaxArticleSize</code> wedi cynnyddu'r Nodion, felly ni chynyddwyd rhai Nodion.",
+       "broken-file-category-desc": "Mae'r dudalen yn cynnwys cyswllt sydd wedi'i dorri (dolen i ffeil nad yw'n bod).",
        "trackingcategories-nodesc": "Dim disgrifiad ar gael.",
        "trackingcategories-disabled": "Categorïau yr analluogwyd",
        "mailnologin": "Does dim cyfeiriad i'w anfon iddo",
        "mywatchlist": "Rhestr wylio",
        "watchlistfor2": "Yn ôl gofyn $1 $2",
        "nowatchlist": "Mae eich rhestr wylio'n wag.",
-       "watchlistanontext": "Rhaid $1 er mwyn gweld neu ddiwygio'ch rhestr wylio.",
+       "watchlistanontext": "Rhaid mewngofnodi er mwyn gweld neu olygu'r rhestr wylio.",
        "watchnologin": "Nid ydych wedi mewngofnodi",
        "addwatch": "Ychwanegu at y rhestr wylio",
        "addedwatchtext": "Mae'r dudalen \"[[:$1|$1]]\" wedi cael ei hychwanegu at eich [[Special:Watchlist|rhestr wylio]].\nPan fydd y dudalen hon, neu ei thudalen sgwrs, yn newid, fe fyddant yn ymddangos ar y rhestr honno.",
+       "addedwatchtext-short": "Mae'r dudalen \"$1\"  wedi'i hychwanegu i'ch rhestr wylio.",
        "removewatch": "Tynnu oddi ar eich rhestr wylio",
        "removedwatchtext": "Mae'r dudalen \"[[:$1]]\" wedi'i thynnu oddi ar [[Special:Watchlist|eich rhestr wylio]].",
+       "removedwatchtext-short": "Mae'r dudalen \"$1\" wedi'i thynnu o'ch tudalen wylio.",
        "watch": "Gwylio",
        "watchthispage": "Gwylier y dudalen hon",
        "unwatch": "Stopio gwylio",
        "watchlist-details": "{{PLURAL:$1|Nid oes dim tudalennau|Mae $1 dudalen|Mae $1 dudalen|Mae $1 tudalen|Mae $1 thudalen|Mae $1 o dudalennau}} ar eich rhestr wylio, heb gynnwys tudalennau sgwrs ar wahan.",
        "wlheader-enotif": "Galluogwyd hysbysiadau trwy e-bost.",
        "wlheader-showupdated": "Mae tudalennau sydd wedi newid ers i chi eu gweld ddiwethaf wedi'u '''hamlygu'''.",
-       "wlnote": "{{PLURAL:$1|Ni fu unrhyw newid|Isod mae'r '''$1''' newid diweddaraf|Isod mae'r '''$1''' newid diweddaraf|Isod mae'r '''$1''' newid diweddaraf|Isod mae'r '''$1''' newid diweddaraf|Isod mae'r '''$1''' newid diweddaraf}} yn ystod {{PLURAL:$2||yr awr|y ddwyawr|y teirawr|y \"$2\" awr|y(r) \"$2\" awr}} ddiwethaf, fel ag yr oedd am $4, $3.",
-       "wlshowlast": "Dangoser newidiadau'r $1 awr ddiwethaf neu'r $2 {{PLURAL:$2|diwrnod|diwrnod|ddiwrnod|diwrnod|diwrnod|diwrnod}} diwethaf neu'r  newidiadau.",
+       "wlnote": "Isod, {{PLURAL:$1|yw'r golygiad diweddaraf |yw'r golygiadau diweddaraf <strong>$1</strong> changes}} yn y {{PLURAL:$2|hour|<strong>$2</strong> awr}}, fel ag y mae ar $3, $4.",
+       "wlshowlast": "Dangoser newidiadau'r $1 awr ddiwethaf neu'r $2 {{PLURAL:$2|diwrnod|diwrnod|ddiwrnod|diwrnod|diwrnod|diwrnod}} diwethaf neu'r newidiadau.",
        "watchlist-options": "Dewisiadau ar gyfer y rhestr wylio",
        "watching": "Wrthi'n ychwanegu...",
        "unwatching": "Wrthi'n tynnu...",
        "exbeforeblank": "y cynnwys cyn blancio oedd: '$1'",
        "delete-confirm": "Dileu \"$1\"",
        "delete-legend": "Dileu",
-       "historywarning": "'''Rhybudd:''' bu tua $1 {{PLURAL:$1|golygiad|golygiad|olygiad|golygiad|golygiad|o olygiadau}} yn hanes y dudalen rydych ar fin ei dileu:",
+       "historywarning": "<strong>Rhybudd:</strong> bu tua $1 {{PLURAL:$1|golygiad|golygiad|olygiad|golygiad|golygiad|o olygiadau}} yn hanes y dudalen rydych ar fin ei dileu:",
        "confirmdeletetext": "Rydych chi ar fin dileu tudalen neu ddelwedd, ynghŷd â'i hanes, o'r data-bas, a hynny'n barhaol.\nOs gwelwch yn dda, cadarnhewch eich bod chi wir yn bwriadu gwneud hyn, eich bod yn deall y canlyniadau, ac yn ei wneud yn ôl [[{{MediaWiki:Policy-url}}|polisïau {{SITENAME}}]].",
        "actioncomplete": "Wedi cwblhau'r weithred",
        "actionfailed": "Methodd y weithred",
        "delete-edit-reasonlist": "Golygu rhestr y rhesymau dros ddileu",
        "delete-toobig": "Cafwyd dros $1 {{PLURAL:$1|o olygiadau}} i'r dudalen hon.\nCyfyngwyd ar y gallu i ddileu tudalennau sydd wedi eu golygu cymaint â hyn, er mwyn osgoi amharu ar weithrediad databas {{SITENAME}} yn ddamweiniol.",
        "delete-warning-toobig": "Cafwyd dros $1 {{PLURAL:$1|o olygiadau}} i'r dudalen hon.\nGallai dileu tudalen, gyda hanes golygu cymaint â hyn iddi, beri dryswch i weithrediadau'r databas ar {{SITENAME}}; ewch ati'n ofalus.",
+       "deleteprotected": "Ni allwch ddileu'r dudalen hon gan ei bod wedi'i chloi.",
        "deleting-backlinks-warning": "'''Rhybudd:''' Mae [[Special:WhatLinksHere/{{FULLPAGENAME}}|tudalennau eraill]] yn cysylltu i'r dudalen yr ydych ar fin ei dileu, neu'n trawsgynnwys y dudalen hon.",
        "rollback": "Gwrthdroi golygiadau",
        "rollback_short": "Gwrthdroi",
        "protect-othertime": "Cyfnod arall:",
        "protect-othertime-op": "cyfnod arall",
        "protect-existing-expiry": "Ar hyn o bryd daw'r gwarchod i ben am: $3, $2",
+       "protect-existing-expiry-infinity": "Diwedd amser: tragwyddoldeb",
        "protect-otherreason": "Rheswm arall:",
        "protect-otherreason-op": "Rheswm arall",
        "protect-dropdown": "*Rhesymau cyffredin dros ddiogelu\n** Fandaliaeth yn rhemp\n** Sbam yn rhemp\n** Ymrafael golygu gwrthgynhyrchiol\n** Tudalen aml ei defnydd",
        "sp-contributions-newbies-sub": "Ar gyfer cyfrifon newydd",
        "sp-contributions-newbies-title": "Cyfraniadau defnyddwyr ar gyfer cyfrifon newydd",
        "sp-contributions-blocklog": "lòg blocio",
+       "sp-contributions-suppresslog": "atal cyfraniadau'r defnyddiwr",
        "sp-contributions-deleted": "cyfraniadau defnyddiwr dileedig",
        "sp-contributions-uploads": "uwchlwythiadau",
        "sp-contributions-logs": "logiau",
        "autoblockid": "Awtoflocio #$1",
        "block": "Rhwystro defnyddiwr",
        "unblock": "Dad-rwystro defnyddiwr",
-       "blockip": "Rhwystro'r defnyddiwr",
+       "blockip": "Rhwystro'r {{GENDER:$1|defnyddiwr}}",
        "blockip-legend": "Rhwystro'r defnyddiwr",
        "blockiptext": "Defnyddiwch y ffurflen hon i rwystro cyfeiriad IP neu ddefnyddiwr rhag ysgrifennu i'r gronfa ddata. \nDylech chi ddim ond gwneud hyn er mwyn rhwystro fandaliaeth, a chan ddilyn [[{{MediaWiki:Policy-url}}|polisi'r wici]]. \nRhowch reswm dros rwystro'r defnyddiwr (er enghraifft, dywedwch pa dudalen(au) a fandaleiddiwyd).",
        "ipaddressorusername": "Cyfeiriad IP neu enw defnyddiwr:",
        "ipb-unblock-addr": "Dadflocio $1",
        "ipb-unblock": "Dadflocio enw defnyddiwr neu gyfeiriad IP",
        "ipb-blocklist": "Dangos y blociau cyfredol",
-       "ipb-blocklist-contribs": "Cyfraniadau $1",
+       "ipb-blocklist-contribs": "Cyfraniadau {{GENDER:$1|$1}}",
        "unblockip": "Dadflocio defnyddiwr",
        "unblockiptext": "Defnyddiwch y ffurflen isod i ail-alluogi golygiadau gan ddefnyddiwr neu o gyfeiriad IP a fu gynt wedi'i flocio.",
        "ipusubmit": "Tynnu'r rhwystr hwn",
        "unblocked": "Mae [[User:$1|$1]] wedi cael ei ddad-flocio",
        "unblocked-range": "Dadrwystrir $1",
        "unblocked-id": "Tynnwyd rhwystr $1",
+       "unblocked-ip": "Mae [[Special:Contributions/$1|$1]] wedi ei atal.",
        "blocklist": "Defnyddwyr a rwystrwyd",
        "ipblocklist": "Defnyddwyr a rwystrwyd",
        "ipblocklist-legend": "Dod o hyd i ddefnyddiwr a rwystrwyd",
        "movepagetalktext": "Bydd y dudalen sgwrs yn symud gyda'r dudalen hon '''onibai:'''\n*bod tudalen sgwrs wrth yr enw newydd yn bodoli'n barod\n*bod y blwch isod heb ei farcio.\n\nOs felly, gallwch symud y dudalen sgwrs neu ei gyfuno ar ôl symud y dudalen ei hun.",
        "movearticle": "Symud y dudalen:",
        "moveuserpage-warning": "'''Sylwer:''' Yr ydych ar fin symud tudalen defnyddiwr. Sylwch mai'r dudalen yn unig a gaiff ei symud ac ''na fydd'' y defnyddiwr yn cael ei ail-enwi.",
+       "movecategorypage-warning": "<strong>Rhybudd:</strong> Rydych ar fin dileu categori. Sylwch mai dim ond y dudalen a gaiff ei symud, a bydd y tudalennau o fewn yr hen gategori yn aros fel ag yr oeddent.",
        "movenologintext": "Mae'n rhaid bod yn ddefnyddiwr cofrestredig a'ch bod wedi [[Special:UserLogin|mewngofnodi]] cyn medru symud tudalen.",
        "movenotallowed": "Nid oes caniatâd gennych i symud tudalennau.",
        "movenotallowedfile": "Nid yw'r gallu ganddoch i symud ffeiliau.",
        "cant-move-user-page": "Nid yw'r gallu ganddoch i symud tudalennau defnyddwyr (heblaw am isdudalennau).",
        "cant-move-to-user-page": "Nid yw'r gallu ganddoch i symud tudalen i dudalen defnyddiwr (heblaw am i isdudalen defnyddiwr).",
+       "cant-move-category-page": "Nid oes gennych yr hawl i symud categoriau.",
+       "cant-move-to-category-page": "Nid oes gennych yr hawl i droi tudalen yn gategori.",
        "newtitle": "I'r teitl newydd:",
        "move-watch": "Gwylier y dudalen hon",
        "movepagebtn": "Symud y dudalen",
        "thumbnail-temp-create": "Wedi methu gwneud ffeil mân-lun dros dro",
        "thumbnail-dest-create": "Wedi methu rhoi'r mân-lun ar gadw yn y man y gofynwyd iddo fod",
        "thumbnail_invalid_params": "Paramedrau maint mân-lun annilys",
+       "thumbnail_toobigimagearea": "Ffeil a'i mhaint yn fwy na $1",
        "thumbnail_dest_directory": "Methwyd â chreu'r cyfeiriadur cyrchfan",
        "thumbnail_image-type": "Nid yw'r math hwn o ddelwedd yn cael ei gynnal",
        "thumbnail_gd-library": "Mae ffurfwedd y llyfrgell GD yn anghyflawn: y ffwythiant $1 yn eisiau",
        "import": "Mewnforio tudalennau",
        "importinterwiki": "Mewnforiad traws-wici",
        "import-interwiki-text": "Dewiswch wici a thudalen i'w mewnforio.\nFe gedwir dyddiadau ac enwau'r golygwyr ar gyfer y diwygiadau i'r dudalen.\nMae cofnod o bob weithred o fewnforio i'w gweld ar y [[Special:Log/import|lòg mewnforio]].",
+       "import-interwiki-sourcewiki": "Ffynhonnell y wici:",
+       "import-interwiki-sourcepage": "Ffynhonnell (tud.)",
        "import-interwiki-history": "Copïer yr holl fersiynau yn hanes y dudalen hon",
        "import-interwiki-templates": "Cynhwyser pob nodyn",
        "import-interwiki-submit": "Mewnforio",
        "import-token-mismatch": "Collwyd data'r sesiwn. Ceisiwch eto.",
        "import-invalid-interwiki": "Ni ellir uwchlwytho o'r wici dewisedig.",
        "import-error-edit": "Ni fewnforiwyd y dudalen \"$1\" oherwydd nad yw'r gallu i'w golygu gennych.",
-       "import-error-create": "Ni fewnforiwyd y dudalen \"$1\" oherwydd nad yw'r gallu i'w chreu gennych.",
+       "import-error-create": "Ni fewnforiwyd y dudalen \"$1\" oherwydd nad yw'r hawl i'w chreu gennych.",
        "import-error-interwiki": "Ni fewnforwyd y dudalen \"$1\" oherwydd bod yr enw arni wedi ei neilltuo at ddiben cysylltu'n allanol (rhyngwici).",
        "import-error-special": "Ni fewnforiwyd y dudalen \"$1\" oherwydd ei bod yn perthyn i barth arbennig lle nad oes tudalennau i'w cael.",
        "import-error-invalid": "Ni fewnforwyd y dudalen \"$1\" oherwydd bod yr enw arni yn annilys.",
        "import-error-unserialize": "Ni allwyd ddad-gyfresu'r diwygiad $2 o'r dudalen '$1'. Adroddwyd bod y diwygiad yn defnyddio'r model cynnwys $3, wedi ei gyfresu fel $4.",
+       "import-error-bad-location": "Ni ellir storio golygiad $2 ar y wici hwn, gan nad yw'r model hwnnw ($3) yn cael ei gynnal ar y dudalen.",
        "import-options-wrong": "{{PLURAL:$2|Dewis|Dewis|Dewisiadau}} annilys: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "Mae teitl y dudalen wraidd a roddir yn annilys.",
        "import-rootpage-nosubpage": "Nid yw'r parth \"$1\", sef parth y brif dudalen y mewnforir iddi, yn caniatau is-dudalennau.",
        "importlogpage": "Lòg mewnforio",
        "importlogpagetext": "Cofnodion mewnforio tudalennau ynghyd â'u hanes golygu oddi ar wicïau eraill, gan weinyddwyr.",
        "import-logentry-upload": "wedi mewnforio [[$1]] trwy uwchlwytho ffeil",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|diwygiad|diwygiad|ddiwygiad|diwygiad|diwygiad|diwygiad}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|diwygiad|diwygiad|ddiwygiad|diwygiad|diwygiad|diwygiad}} wedi'i fewnforio",
        "import-logentry-interwiki": "wedi symud $1 (traws-wici)",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|diwygiad|diwygiad|ddiwygiad|diwygiad|diwygiad|diwygiad}} o $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|diwygiad|diwygiad|ddiwygiad|diwygiad|diwygiad|diwygiad}} wedi'i fewnforio o $2",
        "javascripttest": "Profi JavaScript",
-       "javascripttest-title": "Yn cynnal profion $1",
        "javascripttest-pagetext-noframework": "Neilltuwyd y dudalen hon at gynnal profion JavaScript.",
        "javascripttest-pagetext-unknownframework": "Ni nabyddwyd y fframwaith profi \"$1\".",
+       "javascripttest-pagetext-unknownaction": "Gweithred dienw \"$1\"",
        "javascripttest-pagetext-frameworks": "Dewiswch un o'r fframweithiau profi canlynol: $1",
        "javascripttest-pagetext-skins": "Dewiswch wedd i gynnal profion arni:",
        "javascripttest-qunit-intro": "Gweler y [$1 wybodaeth am y profion] ar mediawiki.org.",
-       "javascripttest-qunit-heading": "Cyfres brofi MediaWiki JavaScript QUnit",
        "tooltip-pt-userpage": "Eich tudalen defnyddiwr",
        "tooltip-pt-anonuserpage": "Y tudalen defnyddiwr ar gyfer y cyfeiriad IP yr ydych yn ei ddefnyddio wrth olygu",
        "tooltip-pt-mytalk": "Eich tudalen sgwrs",
        "tooltip-pt-mycontris": "Rhestr eich cyfraniadau yn nhrefn amser",
        "tooltip-pt-login": "Fe'ch anogir i fewngofnodi, er nad oes rhaid gwneud.",
        "tooltip-pt-logout": "Allgofnodi",
+       "tooltip-pt-createaccount": "Rydym yn argymell eich bod yn creu cyfri ac yn menwgofnodi. Fodd bynnag, dydy hyn ddim yn orfodol",
        "tooltip-ca-talk": "Sgwrsio am y dudalen",
        "tooltip-ca-edit": "Gallwch olygu'r dudalen hon. Da o beth fyddai defnyddio'r botwm 'Dangos rhagolwg' cyn rhoi ar gadw.",
        "tooltip-ca-addsection": "Ychwanegu adran newydd",
        "newimages-summary": "Mae'r dudalen arbennig hon yn dangos y ffeiliau a uwchlwythwyd yn ddiweddar.",
        "newimages-legend": "Hidlo",
        "newimages-label": "Enw'r ffeil (neu ran ohono):",
+       "newimages-showbots": "Dangoswch uwchlwythiadau'r botiaid",
        "noimages": "Does dim byd i'w weld.",
        "ilsubmit": "Chwilio",
        "bydate": "yn ôl dyddiad",
        "autosumm-replace": "Gwacawyd y dudalen a gosod y canlynol yn ei le: '$1'",
        "autoredircomment": "Yn ailgyfeirio at [[$1]]",
        "autosumm-new": "Crëwyd tudalen newydd yn dechrau gyda '$1'",
+       "autosumm-newblank": "Rydych wedi creu tudalen wag",
        "lag-warn-normal": "Hwyrach na ddangosir isod y newidiadau a ddigwyddodd o fewn y $1 {{PLURAL:$1|eiliad|eiliad|eiliad|eiliad|eiliad|eiliad}} ddiwethaf.",
        "lag-warn-high": "Mae gweinydd y data-bas ar ei hôl hi: efallai nad ymddengys newidiadau o fewn y $1 {{PLURAL:$1|eiliad|eiliad|eiliad|eiliad|eiliad|eiliad}} ddiwethaf ar y rhestr.",
        "watchlistedit-normal-title": "Golygu'r rhestr wylio",
        "watchlistedit-raw-done": "Diweddarwyd eich rhestr wylio.",
        "watchlistedit-raw-added": "Ychwanegwyd {{PLURAL:$1|1 teitl|$1 teitl|$1 deitl|$1 theitl|$1 theitl|$1 o deitlau}}:",
        "watchlistedit-raw-removed": "Tynnwyd {{PLURAL:$1|1 teitl|$1 teitl|$1 deitl|$1 theitl|$1 theitl|$1 o deitlau}}:",
+       "watchlistedit-clear-title": "Cliriwyd y rhestr wylio",
+       "watchlistedit-clear-legend": "Clirier y rhestr wylio",
+       "watchlistedit-clear-explain": "Bydd holl deitlau eich rhestr wylio'n cael eu tynnu oddi yno",
+       "watchlistedit-clear-titles": "Teitlau:",
+       "watchlistedit-clear-submit": "Clrio'r rhestr wylio (Mae hyn yn barhaol!)",
+       "watchlistedit-clear-done": "Cliriwyd eich rhestr wylio.",
+       "watchlistedit-clear-removed": "Cliriwyd {{PLURAL:$1|1 title was|$1 teitl}}:",
+       "watchlistedit-too-many": "Mae na ormod o dudalennau i'w harddangos yma.",
+       "watchlisttools-clear": "Clirier y rhestr wylio",
        "watchlisttools-view": "Gweld newidiadau perthnasol",
        "watchlisttools-edit": "Gweld a golygu'r rhestr wylio",
        "watchlisttools-raw": "Golygu'r rhestr wylio syml",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|sgwrs]])",
        "duplicate-defaultsort": "Rhybudd: Mae'r allwedd trefnu diofyn \"$2\" yn gwrthwneud yr allwedd trefnu diofyn blaenorol \"$1\".",
+       "duplicate-displaytitle": "<strong>Gofal:</strong> Mae arddangos \"$2\" yn clirio'r arddangosiadau cynharach \"$1\".",
+       "invalid-indicator-name": "<strong>Gan bwyll:</strong> Ni ddylid gadael y man nodi statws  <code>name</code> yn wag.",
        "version": "Fersiwn",
        "version-extensions": "Estyniadau gosodedig",
-       "version-skins": "Gweddau",
+       "version-skins": "Gweddau a osodwyd",
        "version-specialpages": "Tudalennau arbennig",
        "version-parserhooks": "Bachau dosrannydd",
        "version-variables": "Newidynnau",
        "version-hook-name": "Enw'r bachyn",
        "version-hook-subscribedby": "Tanysgrifwyd gan",
        "version-version": "(Fersiwn $1)",
+       "version-no-ext-name": "[dim enw]",
        "version-license": "Trwydded MediaWiki",
        "version-ext-license": "Trwydded",
        "version-ext-colheader-name": "Estyniad",
+       "version-skin-colheader-name": "Croen",
        "version-ext-colheader-version": "Fersiwn",
        "version-ext-colheader-license": "Trwydded",
        "version-ext-colheader-description": "Disgrifiad",
        "version-entrypoints": "URLs y mannau cyflwyno",
        "version-entrypoints-header-entrypoint": "Man cyflwyno",
        "version-entrypoints-header-url": "URL",
+       "version-libraries": "llyfrgelloedd a osodwyd ar eich cyfer",
+       "version-libraries-library": "Llyfrgell",
+       "version-libraries-version": "Fersiwn",
        "redirect": "Ailgyfeirio yn ôl enw ffeil, defnyddiwr, tudalen neu ID y diwygiad",
        "redirect-legend": "Ailgyfeirio i ffeil neu dudalen",
        "redirect-summary": "Mae'r dudalen arbennig hon yn ailgyfeirio at ffeil (o roi enw'r ffeil), at dudalen (o roi ID rhyw ddiwygiad o'r dudalen neu ID y dudalen), neu at dudalen defnyddiwr (o roi rhif ID y defnyddiwr).\nDefnydd: \n[[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], neu [[{{#Special:Redirect}}/user/101]].",
        "specialpages-group-wiki": "Data ac offer",
        "specialpages-group-redirects": "Tudalennau arbennig ailgyfeirio",
        "specialpages-group-spam": "Offer sbam",
+       "specialpages-group-developer": "Arfau ar gyfer y Datblygwr",
        "blankpage": "Tudalen wag",
        "intentionallyblankpage": "Gadawyd y dudalen hon yn wag o fwriad",
        "external_image_whitelist": " #Leave this line exactly as it is<pre>\n#Gosodwch ddarnau o ymadroddion rheolaidd (y rhan sy'n cael ei osod rhwng y //) isod\n#Caiff y rhain eu cysefeillio gyda URL y delweddau allanol (a chyswllt poeth atynt)\n#Dangosir y rhai sy'n cysefeillio fel delweddau; dangosir cyswllt at y ddelwedd yn unig ar gyfer y lleill\n#Caiff y llinellau sy'n dechrau gyda # eu trin fel sylwadau\n#Nid yw'n gwahaniaethu rhwng llythrennau mawr a bach\n\n#Put all regex fragments above this line. Leave this line exactly as it is</pre>",
        "compare-revision-not-exists": "Nid yw'r diwygiad a enwyd ar gael.",
        "dberr-problems": "Mae'n ddrwg gennym! Mae'r wefan hon yn dioddef anawsterau technegol.",
        "dberr-again": "Oedwch am ychydig funudau cyn ceisio ail-lwytho.",
-       "dberr-info": "(Ni ellir cysylltu â gweinydd y bas data: $1)",
-       "dberr-info-hidden": "(Ni ellir cysylltu â gweinydd y gronfa ddata)",
+       "dberr-info": "(Ni ellir cysylltu â chronfa ddata: $1)",
+       "dberr-info-hidden": "(Ni ellir cysylltu â'r gronfa ddata)",
        "dberr-usegoogle": "Yn y cyfamser gallwch geisio chwilio gyda Google.",
        "dberr-outofdate": "Sylwch y gall eu mynegeion o'n cynnwys fod ar ei hôl hi.",
        "dberr-cachederror": "Dyma gopi o'r dudalen a ofynnwyd amdani, a dynnwyd o'r celc. Mae'n bosib nad y fersiwn diweddaraf yw'r copi hwn.",
        "htmlform-chosen-placeholder": "Dewiswch opsiwn",
        "htmlform-cloner-create": "Ychwaneger rhes",
        "htmlform-cloner-delete": "Tynner i ffwrdd",
+       "htmlform-cloner-required": "Mae angen o leiaf un peth!",
        "sqlite-has-fts": "$1 gyda chymorth chwilio yr holl destun",
        "sqlite-no-fts": "$1 heb gymorth chwiliad yr holl destun",
        "logentry-delete-delete": "Dileodd $1 y dudalen $3",
        "revdelete-uname-unhid": "datguddiwyd yr enw defnyddiwr",
        "revdelete-restricted": "cyfyngwyd ar allu gweinyddwyr i weld",
        "revdelete-unrestricted": "tynnwyd y cyfyngiadau ar allu gweinyddwyr i weld",
+       "logentry-merge-merge": "Mae $1 {{GENDER:$2|wedi cyfuno}} $3 i fewn i $4 (golygiadau hyd at $5)",
        "logentry-move-move": "Symudodd $1 y dudalen $3 i $4",
        "logentry-move-move-noredirect": "Symudodd $1 y dudalen $3 i $4 heb adael dolen ailgyfeirio",
        "logentry-move-move_redir": "{{GENDER:$2|Symudwyd}} y dudalen $3 i $4 gan $1 dros y ddolen ailgyfeirio",
        "logentry-rights-rights": "{{GENDER:$2|Newidiodd}} $1 y grwpiau y mae $3 yn aelod ohonynt o $4 i $5",
        "logentry-rights-rights-legacy": "{{GENDER:$2|Newidiodd}} $1 y grwpiau y mae $3 yn aelod ohonynt",
        "logentry-rights-autopromote": "{{GENDER:$2|Dyrchafwyd}} $1 yn awtomatig o $4 i $5",
+       "logentry-upload-upload": "Mae $1 {{GENDER:$2|wedi uwchlwytho}} $3",
+       "logentry-upload-overwrite": "Mae $1 {{GENDER:$2|wedi uwchlwytho}} fersiwn newydd o $3",
+       "logentry-upload-revert": "Mae $1 {{GENDER:$2|wedi uwchlwytho}} $3",
        "rightsnone": "(dim)",
        "revdelete-summary": "crynodeb golygu",
        "feedback-bugornote": "Os ydych yn barod i ddisgrifio problem technegol yn fanwl gallwch [$1 gyflwyno adroddiad am y bỳg]. Fel arall, gallwch ddefnyddio'r ffurflen syml isod. Fe roddir eich sylwadau ar y dudalen \"[$3 $2]\", ynghyd â'ch enw defnyddiwr ac enw'r gweinydd sydd ar waith gennych.",
        "api-error-stashfailed": "Gwall mewnol: methodd y gweinydd â rhoi'r ffeil dros dro ar gadw.",
        "api-error-publishfailed": "Gwall mewnol: methodd y gweinydd â chyhoeddi'r ffeil dros dro.",
        "api-error-stasherror": "Cafwyd gwall wrth uwchlwytho'r ffeil i'w gelcio.",
+       "api-error-stashedfilenotfound": "Methwyd a dod o hyd i'r ffeil a gadwyd pan ymdrechwyd i'w uwchlwytho.",
+       "api-error-stashpathinvalid": "Roedd y llwybr i'r ffeil a gadwyd yn wallus.",
+       "api-error-stashfilestorage": "Cafwyd gwall wrth geisio cadw'r ffeil.",
+       "api-error-stashzerolength": "Methodd ein gweinydda chadw'r ffeil, oherwydd nad oedd yn bodoli.",
+       "api-error-stashnotloggedin": "Mae;n hanfodol eich bod wedi mewngofnodi cyn y medrwch gadw ffeiliau.",
+       "api-error-stashwrongowner": "Nid eich heiddo chi mo'r ffeil y ceisiwch ei drin.",
+       "api-error-stashnosuchfilekey": "Dydy'r ffeil rydych yn ceisio'i gael yn y cuddfan celc ddim yn bodoli.",
        "api-error-timeout": "Ni chafwyd ymateb gan y gweinydd mewn da bryd.",
        "api-error-unclassified": "Cafwyd gwall anhysbys",
        "api-error-unknown-code": "Gwall anhysbys: \"$1\"",
        "expand_templates_remove_nowiki": "Cuddio'r tagiau <nowiki> wrth ehangu",
        "expand_templates_generate_xml": "Dangos y goeden dosrannu XML",
        "expand_templates_generate_rawhtml": "Dangos HTML crai",
-       "expand_templates_preview": "Rhagolwg"
+       "expand_templates_preview": "Rhagolwg",
+       "pagelanguage": "Dewis iaith y dudalen",
+       "pagelang-name": "Tudalen",
+       "pagelang-language": "Iaith",
+       "pagelang-use-default": "Defnyddier yr iaith arferol",
+       "pagelang-select-lang": "Dewis iaith",
+       "right-pagelang": "Newidiwch iaith y dudalen",
+       "action-pagelang": "newidiwch iaith y dudalen",
+       "log-name-pagelang": "Newidiwch iaith y log",
+       "log-description-pagelang": "Dyma log o newidiadau yn nhudalen yr ieithoedd",
+       "logentry-pagelang-pagelang": "Newidiodd $1 {{GENDER:$2}} iaith ydudalen am $3 o $4 i $5.",
+       "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (galluogi)",
+       "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''diffoddwyd''')",
+       "mediastatistics": "Ystadegau cyfryngau",
+       "mediastatistics-summary": "Ystadegau am fathau o ffeiliau a uwchlwythwyd. Mae hyn yn cynnwys y fersiynau diweddaraf o'r ffeil yn unig.",
+       "mediastatistics-nbytes": "{{PLURAL:$1|$1 beit|$1 beit}} ($2; $3%)",
+       "mediastatistics-table-mimetype": "Math o MIME",
+       "mediastatistics-table-extensions": "Estyniadau posibl",
+       "mediastatistics-table-count": "Nifer o ffeiliau",
+       "mediastatistics-table-totalbytes": "Cyfanswm eu maint",
+       "mediastatistics-header-unknown": "Anhysbys",
+       "mediastatistics-header-bitmap": "Delweddau Bitmap",
+       "mediastatistics-header-drawing": "Lluniau fector",
+       "mediastatistics-header-audio": "Sain",
+       "mediastatistics-header-video": "Fideos",
+       "mediastatistics-header-multimedia": "Cyfryngau cyfoethog",
+       "mediastatistics-header-office": "Office",
+       "mediastatistics-header-text": "Testun",
+       "mediastatistics-header-executable": "Gweithredadwy",
+       "mediastatistics-header-archive": "Fformat wedi'i gywasgu",
+       "json-warn-trailing-comma": "Tynnwyd $1 {{PLURAL:$1|coma}} o JSON",
+       "json-error-unknown": "Roedd gwall gyda JSON. Gwall: $1",
+       "json-error-depth": "Aethpwyd dros y dyfnder mwyaf a ganiateir",
+       "json-error-state-mismatch": "JSON gwallus neu annilys",
+       "json-error-syntax": "Gwall mewn cystrawen",
+       "json-error-utf8": "Llythrennau UTF-8 gwallus, o boib gan godio anghywir"
 }
index 98833d3..c8508de 100644 (file)
        "import-logentry-interwiki": "importierte „$1“ (Transwiki)",
        "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.",
        "javascripttest-pagetext-unknownframework": "Unbekanntes Framework „$1“.",
+       "javascripttest-pagetext-unknownaction": "Unbekannte Aktion „$1“.",
        "javascripttest-pagetext-frameworks": "Bitte wähle eine der folgenden Prüfumgebungen aus: $1",
        "javascripttest-pagetext-skins": "Wähle eine Benutzeroberfläche zur Durchführung der Tests aus:",
        "javascripttest-qunit-intro": "Siehe die [$1 Dokumentation zu Tests] auf mediawiki.org",
-       "javascripttest-qunit-heading": "MediaWiki-JavaSkript-QUnit-Tester",
        "tooltip-pt-userpage": "Deine Benutzerseite",
        "tooltip-pt-anonuserpage": "Benutzerseite der IP-Adresse von der aus du Änderungen durchführst",
        "tooltip-pt-mytalk": "Deine Diskussionsseite",
        "pageinfo-robot-policy": "Indizierung durch Suchmaschinen",
        "pageinfo-robot-index": "Erlaubt",
        "pageinfo-robot-noindex": "Nicht erlaubt",
-       "pageinfo-watchers": "Anzahl der Beobachter der Seite",
+       "pageinfo-watchers": "Anzahl der Beobachter dieser Seite",
        "pageinfo-few-watchers": "Weniger als {{PLURAL:$1|ein|$1}} Beobachter",
        "pageinfo-redirects-name": "Anzahl der Weiterleitungen zu dieser Seite",
        "pageinfo-redirects-value": "$1",
index a8d1a9e..360172b 100644 (file)
        "mycustomjsprotected": "Desturê şıma çıniyo ke na pela JavaScripti bıvurnê.",
        "myprivateinfoprotected": "Ğısusi malumatana ğo timar kerdışire icazeta şıma çıniya.",
        "mypreferencesprotected": "Terciha timar kerdışire icazeta şıam çıniya.",
-       "ns-specialprotected": "Pelê xısusiy nênê vurnayış.",
+       "ns-specialprotected": "Pelê xısusiyi nênê vurnayış.",
        "titleprotected": "Eno [[User:$1|$1]] zerreyê ena peli nişeno vuriye.\nSebeb: \"''$2''\".",
        "filereadonlyerror": "Dosyay vurnayışê \"$1\" nê abê no lakin depoy dosya da \"$2\" mod dê  salt wendi deyo.\n\nXızmetkarê  kılitkerdışi wa bewni ro enay wa çımra ravyarno: \"$3\".",
        "invalidtitle-knownnamespace": "Canemey \"$2\" u metnê \"$3\" xırabo",
        "import-logentry-interwiki": "$1 transwiki biyo",
        "import-logentry-interwiki-detail": "$2 ra $1 {{PLURAL:$1|çımraviyarnayış|çımraviyarnayışi}}",
        "javascripttest": "Cerebnayışê JavaScripti",
-       "javascripttest-title": "Testê $1 gurweyênê",
        "javascripttest-pagetext-noframework": "Na pela testanê JavaScripta gurweynayışi re abıryaya.",
        "javascripttest-pagetext-unknownframework": "Çerçeweyê \"$1\" cerbnayışi xırabo.",
        "javascripttest-pagetext-frameworks": "Şıma ra reca xorê cêr ra test weçinê:$1",
        "javascripttest-pagetext-skins": "Testa akarfinayışi rê verqayt:",
        "javascripttest-qunit-intro": "Mediawiki.org dı [dokumanê $1] bıvinê.",
-       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit test suite",
        "tooltip-pt-userpage": "Pela şımaya karberi",
        "tooltip-pt-anonuserpage": "pelê karberê IPyi",
        "tooltip-pt-mytalk": "Pela toya werênayışi",
        "fileduplicatesearch-result-1": "Dosyayê ''$1î'' de hem-kopya çini yo.",
        "fileduplicatesearch-result-n": "Dosyayê ''$1î'' de {{PLURAL:$2|1 hem-kopya|$2 hem-kopyayî'}} esto.",
        "fileduplicatesearch-noresults": "Ebe namey \"$1\" ra dosya nêdiyayê.",
-       "specialpages": "Pelê xısusiy",
+       "specialpages": "Pelê xısusiyi",
        "specialpages-note-top": "Kıtabek",
        "specialpages-note": "* Pelê xasê normali.\n* <span class=\"mw-specialpagerestricted\">Pelê xasê nımıtey.</span>",
        "specialpages-group-maintenance": "Raporê tepıştışi",
index 9092739..2bb5cff 100644 (file)
        "category-subcat-count-limited": "In cla categoréia ché a gh'é{{PLURAL:$1|'na sòt-categoréia, nutêda|$1 sòt-categoréi, nutêdi}}ché 'd sègvit.",
        "category-article-count": "{{PLURAL:$2|In cla categoréia ché a gh'é sōl 'na pàgina, sgnêda ché.|Cla categoréia ché la gh'à {{PLURAL:$1|la pàgina sgnêda| al pàgini $1 sgnêdi}} ed sègvit, in un totêl ed $2.}}",
        "category-article-count-limited": "In cla categoréia ché a gh'é {{PLURAL:$1|la pàgina nutêda|al  $1 pàgini nutêdi ch'é 'd sègvit.}}",
-       "category-file-count": "{{PLURAL:$2|In cla categoréia ché a gh'é sōl un file, sgnê ché.|In cla categoréia ché gh'é{{PLURAL:$1|un file sgnê ché| i file $1, sgnê}} ed sègvit, in un totêl ed $2.}}",
+       "category-file-count": "{{PLURAL:$2|In cla categoréia ché a gh'é sōl un file, sgnê ché.|In cla categoréia ché gh'é{{PLURAL:$1|un file sgnê ché|$1 file , sgnê}} ed sègvit, in un totêl ed $2.}}",
        "category-file-count-limited": "In cla categoréia ché a gh'é {{PLURAL:$1|al file nutê|i $1 file nutê}} ché 'd sègvit.",
        "listingcontinuesabbrev": "cunt.",
        "index-category": "Pàgini gancêdi",
        "right-viewmyprivateinfo": "Guêrda al tō infurmasiòun personêli (per eşèimpi: indirés ed pôsta eletrônica, nòm vèira)",
        "right-editmyprivateinfo": "Câmbia 'l tō infurmasiòun personêli (per eşèimpi: indirés ed pôsta eletrônica, nòm vèira)",
        "right-editmyoptions": "Câmbia al tō preferèinsi",
-       "right-rollback": "Scanşèla a la şvêlta al mudéfichi ed l'ûltèint ch'l'à mudifichê 'na pàgina pariculêra",
+       "right-rollback": "Scanşèla a la şvêlta al mudéfichi ed l'ûltem utèint ch'l'à mudifichê 'na pàgina particulêra",
        "right-markbotedits": "Sègna al mudéfichi da turnêr a mèter cme préma cme fâti da 'na mâchina in avtomâtich",
        "right-noratelimit": "An n'é mìa ublighê al lémit 'd asiòun",
        "right-import": "Côpia dal pàgini da 'd j êter wiki",
-       "right-importupload": "Zuntêr da pàgini da un file carghê.",
+       "right-importupload": "Zuntêr dal pàgini da un file carghê.",
        "right-patrol": "Sègna al mudéfichi 'd j êter utèint cme verifichêdi",
        "right-autopatrol": "Sègna in avtomâtich al mudéfichi che t'é fât cme verifichêdi",
        "right-patrolmarks": "Drōva la funsiòun ed veréfica dal j ûltmi mudéfichi",
        "action-movefile": "spustêr cól file ché",
        "action-upload": "carghêr cól file ché",
        "action-reupload": "scréver in sém a cól file ché ch' al gh'é bèle",
+       "action-reupload-shared": "scréver insém a cól file ché preşèint int l'archévi spartî",
+       "action-upload_by_url": "carghêr cól file ché da 'n indirés URL",
+       "action-writeapi": "drōva al j API in scritûra",
        "action-delete": "scanşlêr cla pàgina ché",
+       "action-deleterevision": "scanşlêr cla versiòun ché",
+       "action-deletedhistory": "guêrda la stòria scanşlêda de sté pàgina",
+       "action-browsearchive": "serchêr pàgini scanşlêdi",
+       "action-undelete": "tōr indrê cla pàgina ché",
+       "action-suppressrevision": "turnêr a vèder e mèter al mudéfichi lughêdi",
+       "action-suppressionlog": "guardêr sté regéster privê",
+       "action-block": "bluchê sté utèint in scritûra",
+       "action-protect": "cambiêr i livē 'd prutesiòun per cla  pàgina ché",
+       "action-rollback": "scanşèla a la şvêlta al mudéfichi ed l'ûltem utèint ch'l'à mudifichê 'na pàgina particulêra",
+       "action-import": "côpia dal pàgini da 'n' êtra wiki",
+       "action-importupload": "zuntêr dal pàgini da un file carghê",
+       "action-patrol": "sgnêr al mudéfichi 'd j êter utèint cme verifichêdi",
+       "action-autopatrol": "sgnêr al tō mudéfichi cme verifichêdi",
+       "action-unwatchedpages": "vèder un elèinch ed pàgini mìa guardêdi",
+       "action-mergehistory": "unîr la stôria 'd cla pàgina ché",
+       "action-userrights": "mudefichêr tót i dirét ed j utèint",
+       "action-userrights-interwiki": "mudefichêr i dirét ed j utèint insém a êtri wiki",
+       "action-siteadmin": "bluchêr e şbluchêr al databêş",
+       "action-sendemail": "spidîr pôsta eletrônica",
+       "action-editmywatchlist": "mudéfica i tō tgnû sòt ôc",
+       "action-viewmywatchlist": "Guêrda i tō tgnû 'd ôc specêl",
+       "action-viewmyprivateinfo": "guêrda al tō infurmasiòun personêli",
+       "action-editmyprivateinfo": "mudéfica al tō infurmasiòun personêli",
+       "action-editcontentmodel": "câmbia al mudèl dèinter a 'na pàgina",
        "nchanges": "$1\n{{PLURAL:$1|mudéfica|mudéfichi}}",
+       "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|da l'ûltma vîşita}}",
+       "enhancedrc-history": "stòria",
        "recentchanges": "Ûltmi mudéfichi",
        "recentchanges-legend": "Siēlti ûltmi mudéfichi.",
+       "recentchanges-summary": "Cla pàgina ché la preşèinta al mudéfichi piô nōvi a còl che gh'é dèinter al sît.",
+       "recentchanges-noresult": "Nisóna mudéfica dèinter al peréiod scrét ch'la sudésfa chi critèri ché.",
        "recentchanges-feed-description": "Cól feed ché 'l arpôrta al mudéfichi piô frèschi a còl che gh'é dèinter al sît.",
        "recentchanges-label-newpage": "Cun cla mudéfica ché t'é fât 'na pàgina nōva.",
        "recentchanges-label-minor": "Còsta l'é 'na mudéfica céca",
        "compare-page2": "Pàgina 2",
        "compare-rev1": "Revişiòn 1",
        "compare-rev2": "Revişiòn 2",
-       "htmlform-reset": "Scanşèla la mudéfica",
+       "htmlform-reset": "Scanşèla 'l mudéfichi",
        "htmlform-selectorother-other": "Êter",
        "rightsnone": "(nisûn)",
        "feedback-subject": "Argomèint:",
index 4ff46c9..56936bb 100644 (file)
        "import-logentry-interwiki": "η σελίδα $1 εισάχθηκε μεταξύ wiki",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|Εισήχθη $1 αναθεώρηση|Εισήχθησαν $1 αναθεωρήσεις}} από $2",
        "javascripttest": "Δοκιμή JavaScript",
-       "javascripttest-title": "Εκτελούνται  $1  δοκιμές",
        "javascripttest-pagetext-noframework": "Αυτή η σελίδα είναι δεσμευμένη για την εκτέλεση δοκιμών σε JavaScript.",
        "javascripttest-pagetext-unknownframework": "Άγνωστο πλαίσιο δοκιμών \" $1 \".",
        "javascripttest-pagetext-frameworks": "Παρακαλώ επιλέξτε ένα από τα ακόλουθα πλαίσια δοκιμών: $1",
        "javascripttest-pagetext-skins": "Επιλέξτε ένα skin για να εκτελέσετε δοκιμές με αυτό:",
        "javascripttest-qunit-intro": "Ανατρέξτε στην ενότητα [ $1 τεκμηρίωση δοκιμών] στο mediawiki.org.",
-       "javascripttest-qunit-heading": "Σουίτα δοκιμών JavaScript QUnit του MediaWiki",
        "tooltip-pt-userpage": "Η σελίδα χρήστη σας",
        "tooltip-pt-anonuserpage": "Η σελίδα χρήστη στον οποίο αντιστοιχεί η διεύθυνση IP που έχετε",
        "tooltip-pt-mytalk": "Η σελίδα συζήτησής σας",
index 8712f44..3c86243 100644 (file)
        "deleteprotected": "You cannot delete this page because it has been protected.",
        "deleting-backlinks-warning": "'''Warning:''' [[Special:WhatLinksHere/{{FULLPAGENAME}}|Other pages]] link to or transclude the page you are about to delete.",
        "rollback": "Roll back edits",
-       "rollback_short": "Rollback",
        "rollbacklink": "rollback",
        "rollbacklinkcount": "rollback $1 {{PLURAL:$1|edit|edits}}",
        "rollbacklinkcount-morethan": "rollback more than $1 {{PLURAL:$1|edit|edits}}",
        "namespace": "Namespace:",
        "invert": "Invert selection",
        "tooltip-invert": "Check this box to hide changes to pages within the selected namespace (and the associated namespace if checked)",
+       "tooltip-whatlinkshere-invert": "Check this box to hide links from pages within the selected namespace.",
        "namespace_association": "Associated namespace",
        "tooltip-namespace_association": "Check this box to also include the talk or subject namespace associated with the selected namespace",
        "blanknamespace": "(Main)",
index 06b6e8d..86e6c5f 100644 (file)
        "import-logentry-interwiki": "transwikificada $1",
        "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.",
        "javascripttest-pagetext-unknownframework": "Marco de pruebas desconocido \"$1\".",
        "javascripttest-pagetext-frameworks": "Por favor, seleccione uno de los marcos de pruebas siguientes: $1",
        "javascripttest-pagetext-skins": "Elija un aspecto (skin) para ejecutar las pruebas:",
        "javascripttest-qunit-intro": "Consulte la [$1 documentación sobre las pruebas] en mediawiki.org.",
-       "javascripttest-qunit-heading": "Conjunto de pruebas MediaWiki JavaScript QUnit",
        "tooltip-pt-userpage": "Tu página de {{gender:|usuario|usuaria}}",
        "tooltip-pt-anonuserpage": "La página de usuario de la IP desde la que editas",
        "tooltip-pt-mytalk": "Tu página de discusión",
index 55b5283..0756359 100644 (file)
        "import-logentry-interwiki": "importis teisest vikist lehekülje $1",
        "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.",
        "javascripttest-pagetext-unknownframework": "Tundmatu katseraamistik \"$1\".",
        "javascripttest-pagetext-frameworks": "Palun vali üks järgmistest katseraamistikest: $1",
        "javascripttest-pagetext-skins": "Vali kujundus, millega katsetada:",
        "javascripttest-qunit-intro": "Vaata [$1 katsetamise dokumentatsiooni] asukohas mediawiki.org.",
-       "javascripttest-qunit-heading": "MediaWiki JavaScripti QUnit-katsekomplekt",
        "tooltip-pt-userpage": "Sinu kasutajaleht",
        "tooltip-pt-anonuserpage": "Sinu IP-aadressi kasutajalehekülg",
        "tooltip-pt-mytalk": "Sinu arutelulehekülg",
        "exif-focallength": "Fookuskaugus",
        "exif-subjectarea": "Põhimotiivi ala",
        "exif-flashenergy": "Välgu võimsus",
-       "exif-focalplanexresolution": "Fokaaltasandi laius",
-       "exif-focalplaneyresolution": "Fokaaltasandi kõrgus",
+       "exif-focalplanexresolution": "Fokaaltasandi rõhteraldus",
+       "exif-focalplaneyresolution": "Fokaaltasandi püsteraldus",
        "exif-focalplaneresolutionunit": "Fokaaltasandi eraldusühik",
        "exif-subjectlocation": "Põhimotiivi asukoht",
        "exif-exposureindex": "Särituse number",
index c226150..603b042 100644 (file)
        "thumbnail-temp-create": "Ezin izan da behin-behineko iruditxoa sortu",
        "thumbnail-dest-create": "Ezin izan da iruditxoa gorde helburuan",
        "thumbnail_invalid_params": "Irudi txikiaren ezarpenak ez dira baliagarriak",
+       "thumbnail_toobigimagearea": "$1 baino gehiagoko fitxategia",
        "thumbnail_dest_directory": "Ezinezkoa izan da helburu direktorioa sortu",
        "thumbnail_image-type": "Irudi mota ez babestua",
        "thumbnail_gd-library": "GD liburutegiaren konfigurazio osagabea: $1 funtzioa falta da",
        "import-logentry-interwiki": "$1 wiki artean mugitu da",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|berrikuspen|berrikuspen}} $2-(e)tik",
        "javascripttest": "JavaScript frogatzen",
-       "javascripttest-title": "$1 frogak egiten",
        "javascripttest-pagetext-noframework": "Orrialde hau JavaScript frogak egiteko gordeta dago.",
        "javascripttest-pagetext-unknownframework": "Froga eremu ez-ezaguna \"$1\".",
        "javascripttest-pagetext-frameworks": "Mesedez, aukera ezazu froga eremu hauetako bat: $1",
        "javascripttest-pagetext-skins": "Aukeratu frogak egiteko itxura bat:",
        "javascripttest-qunit-intro": "Ikusi [$1 frogen dokumentazioa] mediawiki.org orrialdean.",
-       "javascripttest-qunit-heading": "MediWiki JavaScript QUnit froga taldea",
        "tooltip-pt-userpage": "Nire lankide orria",
        "tooltip-pt-anonuserpage": "Zure IParen lankide orrialdea",
        "tooltip-pt-mytalk": "Nire eztabaida orria",
        "watchlistedit-raw-done": "Zure jarraipen zerrenda berritu da.",
        "watchlistedit-raw-added": "{{PLURAL:$1|Titulu 1 gehitu da|$1 gehitu dira}}:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|Izenburu 1|$1 izenburu}} ezabatu dira:",
+       "watchlistedit-clear-titles": "Izenburuak:",
        "watchlisttools-view": "Aldaketa garrantzitsuak ikusi",
        "watchlisttools-edit": "Zerrenda ikusi eta aldatu",
        "watchlisttools-raw": "Zerrenda idatziz aldatu",
        "version-entrypoints": "Sarrera puntuko URLa",
        "version-entrypoints-header-entrypoint": "Sarrera puntua",
        "version-entrypoints-header-url": "URL",
+       "version-libraries-version": "Bertsioa",
        "redirect": "Birzuzendu fitxategi, lankide edo berrikuspen IDaren arabera",
        "redirect-legend": "Orrialde edo fitxategi batera birzuzendu",
        "redirect-submit": "Joan",
index d094ad0..00528b1 100644 (file)
@@ -70,7 +70,7 @@
        "tog-shownumberswatching": "شمار کاربران پی‌گیرندهٔ نمایش یابد",
        "tog-oldsig": "امضای کنونی:",
        "tog-fancysig": "امضا به صورت ویکی‌متن در نظر گرفته شود (بدون درج خودکار پیوند)",
-       "tog-uselivepreview": "استفاده از پیش‌نمایش زنده (نیازمند جاوااسکریپت) (آزمایشی)",
+       "tog-uselivepreview": "استفاده از پیش‌نمایش زنده",
        "tog-forceeditsummary": "هنگامی که خلاصهٔ ویرایش ننوشته‌ام به من اطلاع داده شود",
        "tog-watchlisthideown": "ویرایش‌های خودم در فهرست پی‌گیری‌ها پنهان شود",
        "tog-watchlisthidebots": "ویرایش‌های ربات‌ها در فهرست پی‌گیری‌ها پنهان شود",
        "pool-queuefull": "صف مخزن پر است",
        "pool-errorunknown": "خطای ناشناخته",
        "pool-servererror": "پول سنتر سرویس در دسترس نیست ( $1 ).",
+       "poolcounter-usage-error": "خطای استفاده: $1",
        "aboutsite": "دربارهٔ {{SITENAME}}",
        "aboutpage": "Project:درباره",
        "copyright": "محتوایات تحت اجازه‌نامهٔ $1 هستند مگر اینکه خلافش ذکر شده باشد.",
        "anoneditwarning": "<strong>هشدار:</strong> شما وارد نشده‌اید. نشانی آی‌پی شما برای عموم قابل مشاهده خواهد بود اگر هر تغییری ایجاد کنید. اگر <strong>[$1 وارد شوید]</strong> یا <strong>[$2 یک حساب کاربری بسازید]</strong>، ویرایش‌هایتان به نام کاربری‌تان نسبت داده خواهد شد، همراه با مزایای دیگر.",
        "anonpreviewwarning": "''شما به سامانه وارد نشده‌اید. ذخیره کردن باعث می‌شود که نشانی آی‌پی شما در تاریخچهٔ این صفحه ثبت گردد.''",
        "missingsummary": "'''یادآوری:''' شما خلاصهٔ ویرایش ننوشته‌اید.\nاگر دوباره دکمهٔ «{{int:savearticle}}» را فشار دهید ویرایش شما بدون آن ذخیره خواهد شد.",
+       "selfredirect": "<strong>هشدار:</strong> شما در حال تغییرمسیر صفحه به خودش هستید.\nامکان دارد هدف اشتباهی را برای تغییرمسیر انتخاب کردید، یا ممکن است صفحهٔ اشتباهی را ویرایش می‌کنید.\n\nاگر بر روی \"{{int:savearticle}}\" دوباره کلیک کنید، تغییرمسیر ساخته خواهد شد.",
        "missingcommenttext": "لطفاً توضیحی در زیر بیفزایید.",
        "missingcommentheader": "'''یادآوری:''' شما موضوع/عنوان این یادداشت را مشخص نکرده‌اید.\nاگر دوباره دکمهٔ «{{int:savearticle}}» را فشار دهید ویرایش شما بدون آن ذخیره خواهد شد.",
        "summary-preview": "پیش‌نمایش خلاصه:",
        "content-model-text": "متنی ساده",
        "content-model-javascript": "جاوااسکریپت",
        "content-model-css": "سی‌اس‌اس",
+       "content-json-empty-object": "ابجکت خالی",
+       "content-json-empty-array": "آرایهٔ خالی",
        "duplicate-args-category": "صفحه‌های دارای آرگومان تکراری در فراخوانی الگو",
        "duplicate-args-category-desc": "صفحاتی که دارای آرگومان تکراری هستند مانند، <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> یا <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "'''هشدار:''' این صفحه حاوی تعدادی زیادی فراخوانی دستورهای تجزیه‌گر است.\n\nتعداد آن‌ها باید کمتر از $2 {{PLURAL:$2|فراخوانی|فراخوانی}} باشد، و اینک {{PLURAL:$1|$1 فراخوانی|$1 فراخوانی}} است.",
        "history-feed-empty": "صفحهٔ درخواست شده وجود ندارد.\nممکن است که از ویکی حذف یا اینکه نامش تغییر داده شده باشد.\nصفحات تازه را برای موارد مرتبط در این ویکی [[Special:Search|جستجو کنید]].",
        "rev-deleted-comment": "(خلاصه ویرایش حذف شد)",
        "rev-deleted-user": "(نام کاربری حذف شد)",
-       "rev-deleted-event": "(مورد از سیاهه پاک شده)",
+       "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}}}} سیاههٔ حذف] موجود باشد.",
        "revdelete-selected-text": "{{PLURAL:$1|نسخهٔ انتخاب‌شده|نسخه‌های انتخابی}} [[:$2]]:",
        "revdelete-selected-file": "{{PLURAL:$1|نسخهٔ انتخاب‌شدهٔ|نسخه‌های انتخابی}} [[:$2]]:",
        "logdelete-selected": "{{PLURAL:$1|مورد|موارد}} انتخاب شده از سیاهه:",
-       "revdelete-text-text": "Ù\86سخÙ\87â\80\8cÙ\87اÛ\8c Ø­Ø°Ù\81â\80\8cشدÙ\87 Ù\87Ù\85Ú\86Ù\86اÙ\86 Ø¯Ø± ØªØ§Ø±Û\8cÛ\8cØ®Ú\86Ù\87 Ù\86Ù\85اÛ\8cاÙ\86 Ø®Ù\88اÙ\86د Ø¨Ù\88د Ù\88Ù\84Û\8c Ù\82سÙ\85تâ\80\8cÙ\87اÛ\8cÛ\8c Ø§Ø² Ù\85حتÙ\88Û\8cات ØºØ¨Ø±Ù\82ابÙ\84 Ø¯Ø³ØªØ±Ø³ Ø¨Ø±Ø§Û\8c Ø¹Ù\85Ù\88Ù\85 خواهد بود.",
+       "revdelete-text-text": "Ù\85شخصات Ù\86سخÙ\87â\80\8cÙ\87اÛ\8c Ø­Ø°Ù\81 Ø´Ø¯Ù\87 Ù\87Ù\85Ú\86Ù\86اÙ\86 Ø¯Ø± ØªØ§Ø±Û\8cØ®Ú\86Ù\87 ØµÙ\81Ø­Ù\87 Ù\86Ù\85اÛ\8cاÙ\86 Ø®Ù\88اÙ\87د Ø¨Ù\88د Ù\88Ù\84Û\8c Ø¯Ø³ØªØ±Ø³Û\8c Ø¨Ù\87 Ù\82سÙ\85تâ\80\8cÙ\87اÛ\8cÛ\8c Ø§Ø² Ù\85حتÙ\88Û\8cات Ø§Û\8cÙ\86 Ù\86سخÙ\87â\80\8cÙ\87ا Ø¨Ø±Ø§Û\8c Ø¹Ù\85Ù\88Ù\85 Ù\85Ù\85Ú©Ù\86 Ù\86خواهد بود.",
        "revdelete-text-file": "نسخه‌های حذف‌شده همچنان در تاریخچهٔ پرونده نمایان خواهد بود ولی قسمت‌هایی از محتویات آن‌ها برای عموم غیرقابل دسترس خواهد بود.",
        "logdelete-text": "نسخه‌های حذف‌شده همچنان در سیاهه‌های نمایان خواهد بود ولی قسمت‌هایی از محتویات آن‌ها غیرقابل دسترس برای عموم خواهد بود.",
        "revdelete-text-others": "سایر مدیران هنوز می‌توانند این محتوای پنهان را ببینند و از همین طریق موارد حذف شده را احیا کنند، مگر آن که محدودیت‌های دیگری اعمال گردد.",
        "revdelete-legend": "تنظیم محدودیت‌های پیدایی",
        "revdelete-hide-text": "متن نسخه",
        "revdelete-hide-image": "نهفتن محتویات پرونده",
-       "revdelete-hide-name": "نهفتن عمل و هدف",
+       "revdelete-hide-name": "نهفتن متغییرها و هدف",
        "revdelete-hide-comment": "خلاصهٔ ویرایش",
        "revdelete-hide-user": "نام کاربری/نشانی آی‌پی",
        "revdelete-hide-restricted": "فرونشانی اطلاعات برای مدیران به همراه دیگران",
        "wantedtemplates": "الگوهای مورد نیاز",
        "mostlinked": "صفحه‌هایی که بیشتر از همه به آن‌ها پیوند داده شده‌است",
        "mostlinkedcategories": "رده‌هایی که بیشتر از همه به آن‌ها پیوند داده شده‌است",
-       "mostlinkedtemplates": "ببشترین صفحات تراگنجانده‌شده",
+       "mostlinkedtemplates": "بیشترین صفحات تراگنجانده‌شده",
        "mostcategories": "صفحه‌های دارای بیشترین رده",
        "mostimages": "پرونده‌هایی که بیشتر از همه به آن‌ها پیوند داده شده‌است",
        "mostinterwikis": "صفحه‌های دارای بیشترین میان‌ویکی",
        "thumbnail-temp-create": "نمی‌توان پروندهٔ بندانگشتی موقت را ساخت",
        "thumbnail-dest-create": "نمی‌توان تصویر بندانگشتی را در مقصد ذخیره کرد",
        "thumbnail_invalid_params": "پارامترهای نامجاز در تصویر بندانگشتی (thumbnail)",
+       "thumbnail_toobigimagearea": "پرونده‌ای با اندازهٔ بیشتر از $1",
        "thumbnail_dest_directory": "اشکال در ایجاد پوشهٔ مقصد",
        "thumbnail_image-type": "تصویر از نوع پشتیبانی نشده",
        "thumbnail_gd-library": "تنظیمات ناقص کتابخانهٔ GD: عملکرد $1 وجود ندارد",
        "import-logentry-interwiki": "$1 را تراویکی کرد",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|نسخه|نسخه}} واردشده از $2",
        "javascripttest": "آزمایش جاوا اسکریپت",
-       "javascripttest-title": "در حال اجرای آزمایش‌های $1",
        "javascripttest-pagetext-noframework": "این صفحه برای اجرای آزمایش‌های جاوا اسکریپت کنار گذاشته شده‌است.",
        "javascripttest-pagetext-unknownframework": "چارچوب آزمایشی ناشناخته «$1».",
+       "javascripttest-pagetext-unknownaction": "تابع ناشناختهٔ \"$1\".",
        "javascripttest-pagetext-frameworks": "لطفاً یکی از چارچوب‌های آزمایش زیر را انتخاب کنید: $1",
        "javascripttest-pagetext-skins": "پوسته‌ای را برای اجرای آزمایش‌ها انتخاب کنید:",
        "javascripttest-qunit-intro": "[$1 مستندات آزمایش] را در mediawiki.org ببینید.",
-       "javascripttest-qunit-heading": "مجموعه آزمایش QUnit جاوااسکریپت برای مدیاویکی",
        "tooltip-pt-userpage": "صفحهٔ کاربری شما",
        "tooltip-pt-anonuserpage": "صفحهٔ کاربری نشانی آی‌پی‌ای که با آن ویرایش می‌کنید",
        "tooltip-pt-mytalk": "صفحهٔ بحث شما",
        "version-entrypoints-header-url": "نشانی اینترنتی",
        "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath مسیر مقاله]",
        "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath مسیر اسکریپت]",
+       "version-libraries": "کتابخانهٔ نصب شده",
+       "version-libraries-library": "کتابخانه",
+       "version-libraries-version": "نسخه",
        "redirect": "تغییرمسیر توسط پرونده، کاربر، صفحه یا شناسهٔ نسخه",
        "redirect-legend": "تغییرمسیر به یک پرونده یا صفحه",
        "redirect-summary": "این صفحهٔ ویژه به پرونده (نام پرونده داده‌شده)، صفحه (شماره شناسهٔ صفحه یا شماره نسخهٔ داده‌شده) یا صفحهٔ کاربری (شناسهٔ عددی کاربری داده‌شده) تغییرمسیر می‌یابد. طرز استفاده: [[{{#Special:Redirect}}/file/Example.jpg]]، \n[[{{#Special:Redirect}}/page/64308]]، [[{{#Special:Redirect}}/revision/328429]] یا [[{{#Special:Redirect}}/user/101]].",
        "compare-revision-not-exists": "پالایهٔ مشخص شده وجود ندارد.",
        "dberr-problems": "شرمنده! این تارنما از مشکلات فنی رنج می‌برد.",
        "dberr-again": "چند دقیقه صبر کنید و دوباره صفحه را بارگیری کنید.",
-       "dberr-info": "(امکان برقراری ارتباط با کارساز پایگاه داده وجود ندارد: $1)",
-       "dberr-info-hidden": "(امکان تماس با پایگاه‌داده‌ها کارساز امکان‌پذیر نیست)",
+       "dberr-info": "(امکان برقراری ارتباط با پایگاه داده وجود ندارد: $1)",
+       "dberr-info-hidden": "(امکان تماس با پایگاه‌داده نیست)",
        "dberr-usegoogle": "شما در این مدت می‌توانید با استفاده از گوگل جستجو کنید.",
        "dberr-outofdate": "توجه کنید که نمایه‌های آن‌ها از محتوای ما ممکن است به روز نباشد.",
        "dberr-cachederror": "آن‌چه در ادامه می‌آید یک کپی از صفحهٔ درخواست شده است که در کاشه قرار دارد، و ممکن است به روز نباشد.",
index f7b934c..92b043a 100644 (file)
        "pool-queuefull": "Prosessijoukon jono on täynnä",
        "pool-errorunknown": "Tuntematon virhe.",
        "pool-servererror": "Pool counter -palvelu ei ole käytettävissä ($1).",
-       "poolcounter-usage-error": "Käytön virhe: $1",
+       "poolcounter-usage-error": "Käytvirhe: $1",
        "aboutsite": "Tietoja {{GRAMMAR:elative|{{SITENAME}}}}",
        "aboutpage": "Project:Tietoja",
        "copyright": "Sisältö on käytettävissä lisenssillä $1, ellei toisin ole mainittu.",
        "import-logentry-interwiki": "toi toisesta wikistä sivun $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|versio|versiota}} tuotiin wikistä $2",
        "javascripttest": "JavaScriptin testaus",
-       "javascripttest-title": "Suoritetaan $1-testejä.",
        "javascripttest-pagetext-noframework": "Tämä sivu on varattu JavaScript-testien suorittamiseen.",
        "javascripttest-pagetext-unknownframework": "Tuntematon testausalusta $1.",
        "javascripttest-pagetext-frameworks": "Valitse yksi seuraavista testausalustoista: $1",
        "javascripttest-pagetext-skins": "Valitse testauksessa käytettävä ulkoasu",
        "javascripttest-qunit-intro": "Katso [$1 testausohjeet] mediawiki.orgissa.",
-       "javascripttest-qunit-heading": "MediaWikin JavaScriptin QUnit-testikokoelma",
        "tooltip-pt-userpage": "Oma käyttäjäsivu",
        "tooltip-pt-anonuserpage": "IP-osoitteesi käyttäjäsivu",
        "tooltip-pt-mytalk": "Oma keskustelusivu",
index 9fed1da..2cb55bf 100644 (file)
        "import-logentry-interwiki": "a importé $1 d'un wiki à l'autre",
        "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.",
        "javascripttest-pagetext-unknownframework": "Structure « $1 » inconnue.",
+       "javascripttest-pagetext-unknownaction": "Action « $1 » inconnue.",
        "javascripttest-pagetext-frameworks": "Veuillez choisir l'une des structures de test suivantes : $1",
        "javascripttest-pagetext-skins": "Choisissez un habillage avec lequel lancer les tests :",
        "javascripttest-qunit-intro": "Voir [$1 la documentation de test] sur mediawiki.org.",
-       "javascripttest-qunit-heading": "Suite de test QUnit de JavaScript sur MediaWiki",
        "tooltip-pt-userpage": "Votre page utilisateur",
        "tooltip-pt-anonuserpage": "La page utilisateur de l'IP avec laquelle vous contribuez",
        "tooltip-pt-mytalk": "Votre page de discussion",
index b3ffe64..83c119c 100644 (file)
        "import-logentry-interwiki": "importou \"$1\"",
        "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.",
        "javascripttest-pagetext-unknownframework": "Descoñécese a infraestrutura dixital \"$1\" de probas.",
+       "javascripttest-pagetext-unknownaction": "Acción descoñecida \"$1\".",
        "javascripttest-pagetext-frameworks": "Seleccione unha das seguintes infraestruturas dixitais de probas: $1",
        "javascripttest-pagetext-skins": "Escolla a aparencia na que executar as probas:",
        "javascripttest-qunit-intro": "Bótelle unha ollada á [$1 documentación das probas] en mediawiki.org.",
-       "javascripttest-qunit-heading": "Conxunto de probas QUnit para o JavaScript de MediaWiki",
        "tooltip-pt-userpage": "A súa páxina de {{GENDER:|usuario|usuaria}}",
        "tooltip-pt-anonuserpage": "A páxina de usuario do enderezo IP desde o que está a editar",
        "tooltip-pt-mytalk": "A súa páxina de conversa",
index ad89a0b..1444e99 100644 (file)
        "import-logentry-interwiki": "આંતરવિકિ  $1",
        "import-logentry-interwiki-detail": "$2 માંથી આયાત કરેલ $1 {{PLURAL:$1|પુનરાવર્તન|પુનરાવર્તનો}}",
        "javascripttest": "જાવા સ્ક્રીપ્ટ પરીક્ષણ",
-       "javascripttest-title": "$1 પરીક્ષણ જારી",
        "javascripttest-pagetext-noframework": "આ પાનું જાવા સ્ક્રીપ્ટ ચલાવવા આરક્ષિત છે.",
        "javascripttest-pagetext-unknownframework": "અજાણ ચકાસણી ફ્રેમવર્ક \"$1\".",
        "javascripttest-pagetext-frameworks": "નીચેનામાંથી કોઈ એક ચકાસણી ફ્રેમવર્ક પસંદ કરો : $1",
        "javascripttest-pagetext-skins": "ચકાસણી કરવા માટેની સ્કીન પસંદ કરો",
        "javascripttest-qunit-intro": "mediawiki.org પર  [$1 testing documentation] તપાસ માહિતી જુઓ",
-       "javascripttest-qunit-heading": "મિડિયા વિકી જાવા સ્ક્રીપ્ટ QUnit test suite",
        "tooltip-pt-userpage": "તમારૂં પાનું (તમારૂં 'મારા વિષે')",
        "tooltip-pt-anonuserpage": "IP સરનામું માટેના સભ્ય પાનામાં તમે ફેરફાર કરી રહ્યાં છો.",
        "tooltip-pt-mytalk": "તમારૂં ચર્ચાનું પાનું",
index ded47b7..60d74f3 100644 (file)
        "import-logentry-interwiki": "ייבא את $1 בייבוא בין־אתרי",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|גרסה אחת של הדף $2 יובאה|$1 גרסאות של הדף $2 יובאו}}",
        "javascripttest": "בדיקת JavaScript",
-       "javascripttest-title": "הרצת בדיקות $1",
        "javascripttest-pagetext-noframework": "דף זה שמור להרצת בדיקות JavaScript.",
        "javascripttest-pagetext-unknownframework": "סביבת הבדיקות \"$1\" אינה ידועה.",
+       "javascripttest-pagetext-unknownaction": "הפעולה \"$1\" אינה ידועה.",
        "javascripttest-pagetext-frameworks": "נא לבחור אחת מסביבות הבדיקות הבאות: $1",
        "javascripttest-pagetext-skins": "בחירת עיצוב שאיתו יורצו הבדיקות:",
        "javascripttest-qunit-intro": "ראו את [$1 תיעוד הבדיקות] באתר mediawiki.org.",
-       "javascripttest-qunit-heading": "מערך בדיקות QUnit ל־JavaScript של מדיה־ויקי",
        "tooltip-pt-userpage": "דף המשתמש שלך",
        "tooltip-pt-anonuserpage": "דף המשתמש של משתמש אנונימי זה",
        "tooltip-pt-mytalk": "דף השיחה שלך",
index 09ce0c6..1130784 100644 (file)
@@ -84,7 +84,7 @@
        "tog-shownumberswatching": "ध्यान रखने वाले सदस्यों की संख्या दिखाएँ",
        "tog-oldsig": "वर्तमान हस्ताक्षर:",
        "tog-fancysig": "हस्ताक्षर का विकिपाठ के समान मानें (बिना स्वचालित कड़ी के)",
-       "tog-uselivepreview": "सजीवन झलक का उपयोग करें (प्रयोगात्मक)",
+       "tog-uselivepreview": "सजीवन झलक का उपयोग करें",
        "tog-forceeditsummary": "यदि सम्पादन सारांश ना दिया गया हो तो मुझे सूचित करें",
        "tog-watchlisthideown": "मेरी ध्यानसूची से मेरे किए परिवर्तन छिपाएँ",
        "tog-watchlisthidebots": "मेरी ध्यानसूची से बॉटों द्वारा किए परिवर्तन छिपाएँ",
        "otherlanguages": "अन्य भाषाएँ",
        "redirectedfrom": "($1 से पुनर्निर्देशित)",
        "redirectpagesub": "पुनर्निर्देश पृष्ठ",
+       "redirectto": "को अनुप्रेषित:",
        "lastmodifiedat": "इस पृष्ठ का पिछला बदलाव $1 को $2 बजे हुआ था।",
        "viewcount": "यह पृष्ठ {{PLURAL:$1|एक|$1}} बार देखा गया है।",
        "protectedpage": "सुरक्षित पृष्ठ",
        "pool-queuefull": "पूल पंक्ति भरी हुई है",
        "pool-errorunknown": "अज्ञात त्रुटि",
        "pool-servererror": "पूल काउंटर सेवा उपलब्ध नहीं है ($1)।",
+       "poolcounter-usage-error": "उपयोग त्रुटि: $1",
        "aboutsite": "{{SITENAME}} के बारे में",
        "aboutpage": "Project:परिचय",
        "copyright": "उपलब्ध सामग्री $1 के अधीन है जब तक अलग से उल्लेख ना किया गया हो।",
        "filerenameerror": "\"$1\" फ़ाइल का नाम बदलकर \"$2\" नहीं रखा जा सका।",
        "filedeleteerror": "\"$1\" फ़ाइल को हटाया नहीं जा सका।",
        "directorycreateerror": "\"$1\" डाइरेक्टरी नहीं बनाई जा सकी।",
+       "directoryreadonlyerror": "निर्देशिका \"$1\" केवल पठनीय है।",
+       "directorynotreadableerror": "निर्देशिका \"$1\" पठनीय नहीं है।",
        "filenotfound": "\"$1\" फ़ाइल नहीं मिली।",
        "unexpected": "अनपेक्षित मूल्य: \"$1\"=\"$2\".",
        "formerror": "त्रुटि: फ़ॉर्म सबमिट नहीं किया जा सका",
        "viewsourcetext": "आप इस पृष्ठ का स्रोत देख सकते हैं और उसकी नकल उतार सकते हैं:",
        "viewyourtext": "आप इस पृष्ठ में ''अपने सम्पादन'' का स्रोत देख सकते हैं और उसकी नकल उतार सकते हैं:",
        "protectedinterface": "यह पृष्ठ इस विकी के सॉफ़्टवेयर का इंटरफ़ेस पाठ देता है, और इसे गलत प्रयोग से बचाने के लिये सुरक्षित कर दिया गया है।\nसभी विकियों के लिए अनुवाद जोड़ने या बदलने के लिए कृपया मीडियाविकि के क्षेत्रीयकरण प्रकल्प [//translatewiki.net/ translatewiki.net] का प्रयोग करें।",
-       "editinginterface": "'''चेतावनी:''' आप एक ऐसे पृष्ठ को बदल रहे हैं जो सॉफ़्टवेयर का इंटरफ़ेस पाठ प्रदान करता है।\nइस पृष्ठ को बदलने से अन्य सदस्यों को प्रदर्शित इंटरफ़ेस की शक्लोसूरत में बदलाव आएगा।\nसभी विकियों के लिए अनुवाद बदलने या जोड़ने के लिए कृपया मीडियाविकि की क्षेत्रीयकरण परियोजना [//translatewiki.net/wiki/Main_Page?setlang=hi translatewiki.net] का प्रयोग करें।",
+       "editinginterface": "<strong>चेतावनी:</strong> आप एक ऐसे पृष्ठ को बदल रहे हैं जो सॉफ़्टवेयर का इंटरफ़ेस पाठ प्रदान करता है।\nइस पृष्ठ को बदलने से अन्य सदस्यों को प्रदर्शित इंटरफ़ेस की शक्लोसूरत में बदलाव आएगा।",
        "cascadeprotected": "यह पृष्ठ सुरक्षित हैं, क्योंकी यह निम्नलिखित {{PLURAL:$1|पृष्ठ|पृष्ठों}} की सुरक्षा-सीढ़ी में समाविष्ट है:\n$2",
        "namespaceprotected": "आपको '''$1''' नामस्थान में समाविष्ट पृष्ठों को बदलने की अनुमति नहीं है।",
        "customcssprotected": "आपको इस CSS पृष्ठ को संपादित करने की अनुमति नहीं है, क्योंकि इसमें अन्य सदस्य की व्यक्तिगत सेटिंग्स शामिल हैं।",
        "import-logentry-interwiki": "ट्रान्सविकि कर दिया $1",
        "import-logentry-interwiki-detail": "$2 से $1 {{PLURAL:$1|अवतरण|अवतरण}}",
        "javascripttest": "जावास्क्रिप्ट परीक्षण",
-       "javascripttest-title": "$1 परीक्षण चल रहे हैं",
        "javascripttest-pagetext-noframework": "यह पृष्ठ जावास्क्रिप्ट परीक्षण चलाने के लिए है।",
        "javascripttest-pagetext-unknownframework": "अज्ञात परीक्षण ढाँचा \"$1\"",
        "javascripttest-pagetext-frameworks": "कृपया निम्न परीक्षण ढाँचों में से एक चुनें: $1",
        "javascripttest-pagetext-skins": "परीक्षण करने के लिए त्वचा चुनें:",
        "javascripttest-qunit-intro": "mediawiki.org पर [$1 परीक्षण के प्रलेखन] देखें।",
-       "javascripttest-qunit-heading": "मीडियाविकि जावास्क्रिप्ट क्यू-युनिट परीक्षण ढाँचा",
        "tooltip-pt-userpage": "आपका प्रयोक्ता पृष्ठ",
        "tooltip-pt-anonuserpage": "आप जिस आईपी से बदलाव कर रहें हैं उसका सदस्य पान",
        "tooltip-pt-mytalk": "आपका वार्ता पृष्ठ",
index c3b8df1..ed415bc 100644 (file)
        "viewsourceold": "vidi izvor",
        "editlink": "uredi",
        "viewsourcelink": "vidi izvornik",
-       "editsectionhint": "Uređivanje odlomka: $1",
+       "editsectionhint": "Uredi odlomak $1",
        "toc": "Sadržaj",
        "showtoc": "prikaži",
        "hidetoc": "sakrij",
        "import-logentry-interwiki": "transwiki uvezeno $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|promjena|promjene|promjena}} od $2",
        "javascripttest": "Testiranje JavaScripta",
-       "javascripttest-title": "Izvršavaju se $1 testovi",
        "javascripttest-pagetext-noframework": "Ova je stranica rezervirana za izvršavanje JavaScript testova.",
        "javascripttest-pagetext-unknownframework": "Nepoznata testna okolina \"$1\".",
        "javascripttest-pagetext-frameworks": "Molimo izaberite jednu od sljedećih testnih okolina: $1",
        "javascripttest-pagetext-skins": "Izaberite temu (''skin'') za testiranje:",
        "javascripttest-qunit-intro": "Pogledajte [$1 testnu dokumentaciju] na mediawiki.org.",
-       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit testni alati",
        "tooltip-pt-userpage": "Moja suradnička stranica",
        "tooltip-pt-anonuserpage": "Suradnička stranica za IP adresu pod kojom uređujete",
        "tooltip-pt-mytalk": "Moja stranica za razgovor",
index 042304e..56049be 100644 (file)
        "import-logentry-interwiki": "$1 más wikiből áthozva",
        "import-logentry-interwiki-detail": "$1 változat innen: $2",
        "javascripttest": "JavaScript tesztelés",
-       "javascripttest-title": "$1 tesztek futtatása",
        "javascripttest-pagetext-noframework": "Ez az oldal JavaStript tesztek futtatására van fenntartva.",
        "javascripttest-pagetext-unknownframework": "Ismeretlen teszt keretrendszer: $1.",
        "javascripttest-pagetext-frameworks": "Kérlek válaszd valamelyik teszt keretrendszert az alábbiak közül: $1",
        "javascripttest-pagetext-skins": "Válassz egy megjelenítő felületet, amin a tesztet futtatod:",
        "javascripttest-qunit-intro": "Lásd a [$1 tesztelési dokumentációt]  a mediawiki.org helyen.",
-       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit tesztcsomag",
        "tooltip-pt-userpage": "A szerkesztőlapod",
        "tooltip-pt-anonuserpage": "Az általad használt IP-címhez tartozó felhasználói lap",
        "tooltip-pt-mytalk": "A vitalapod",
        "blankpage": "Üres lap",
        "intentionallyblankpage": "Ez a lap szándékosan maradt üresen",
        "external_image_whitelist": " #Ezt a sort hagyd pontosan így, ahogy van<pre>\n#Ide reguláris kifejezéseket írhatsz (azon részüket, amik a // közé mennek)\n#Ezek egyeztetve lesznek a külső képek URL-jeivel\n#Egyezés esetén képként fognak megjelenni, egyébként csak link fog rájuk mutatni\n#A #-tel kezdődő sorok megjegyzésnek számítanak\n#A kis- és nagybetűk nincsenek megkülönböztetve\n\n#A reguláris kifejezéseket ezen sor alá írd. Ezt a sort hagyd így, ahogy van.</pre>",
-       "tags": "Érvényes módosítási címkék",
+       "tags": "Lapváltozat-címkék",
        "tag-filter": "[[Special:Tags|Címke]]szűrő:",
        "tag-filter-submit": "Szűrő",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Címke|Címkék}}]]: $2)",
index 9f86acc..ec6b000 100644 (file)
        "import-logentry-interwiki": "importava $1 transwiki",
        "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.",
        "javascripttest-pagetext-unknownframework": "Structura de test \"$1\" incognite.",
        "javascripttest-pagetext-frameworks": "Per favor selige un del sequente structuras de test: $1",
        "javascripttest-pagetext-skins": "Selige un apparentia con le qual executar le tests:",
        "javascripttest-qunit-intro": "Vide [$1 documentation de tests] sur mediawiki.org.",
-       "javascripttest-qunit-heading": "Programmas de test QUnit de JavaScript de MediaWiki",
        "tooltip-pt-userpage": "Tu pagina de usator",
        "tooltip-pt-anonuserpage": "Le pagina de usator pro le adresse IP desde le qual tu face modificationes",
        "tooltip-pt-mytalk": "Tu pagina de discussion",
index a2069c8..957d3ad 100644 (file)
        "import-logentry-interwiki": "ha trasferito da altra wiki la pagina $1",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|una versione importata|$1 versioni importate}} da $2",
        "javascripttest": "Sperimentazione JavaScript",
-       "javascripttest-title": "In esecuzione test per $1",
        "javascripttest-pagetext-noframework": "Questa pagina è riservata all'esecuzione di test di JavaScript.",
        "javascripttest-pagetext-unknownframework": "Framework di test sconosciuto \"$1\".",
+       "javascripttest-pagetext-unknownaction": "Azione sconosciuta \"$1\".",
        "javascripttest-pagetext-frameworks": "Per cortesia, scegli uno dei seguenti framework per i test: $1",
        "javascripttest-pagetext-skins": "Scegli una skin con cui eseguire i test:",
        "javascripttest-qunit-intro": "Vedi su mediawiki.org la [$1 documentazione riguardante i test].",
-       "javascripttest-qunit-heading": "Suite di test di JavaScript per QUnit in MediaWiki",
        "tooltip-pt-userpage": "La tua pagina utente",
        "tooltip-pt-anonuserpage": "La pagina utente di questo indirizzo IP",
        "tooltip-pt-mytalk": "La tua pagina di discussione",
        "version-entrypoints-header-url": "URL",
        "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Percorso voci]",
        "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Percorso script]",
+       "version-libraries": "Librerie installate",
+       "version-libraries-library": "Libreria",
+       "version-libraries-version": "Versione",
        "redirect": "Reindirizzamento da file, utente, pagina o versione",
        "redirect-legend": "Reindirizza a un file o una pagina",
        "redirect-summary": "Questa pagina speciale reindirizza a un file (specificando il nome del file), a una pagina (specificando un ID di versione o un ID pagina) o a un utente (specificando un ID utente numerico).\nEsempi: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], or [[{{#Special:Redirect}}/user/101]].",
index 1fdbba4..48888b3 100644 (file)
        "import-logentry-interwiki": "$1をウィキ間移動しました",
        "import-logentry-interwiki-detail": "$2からインポート済みの$1{{PLURAL:$1|版}}",
        "javascripttest": "JavaScript をテスト中",
-       "javascripttest-title": "$1 のテストの実行",
        "javascripttest-pagetext-noframework": "このページは JavaScript のテストを実行するために予約されています。",
        "javascripttest-pagetext-unknownframework": "テストフレームワーク「$1」は不明です。",
        "javascripttest-pagetext-frameworks": "以下のテストフレームワークから1つ選択してください: $1",
        "javascripttest-pagetext-skins": "テストを実行する外装を選択してください:",
        "javascripttest-qunit-intro": "mediawiki.org上の[$1 テストのドキュメント]を参照してください。",
-       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit テストスイート",
        "tooltip-pt-userpage": "自分の利用者ページ",
        "tooltip-pt-anonuserpage": "自分が編集しているIPアドレスの利用者ページ",
        "tooltip-pt-mytalk": "自分のトークページ",
index 2d92159..1880c71 100644 (file)
        "import-logentry-interwiki": "„$1“ — ტრანსვიკი იმპორტი",
        "import-logentry-interwiki-detail": "$1 ცვლილება $2-დან",
        "javascripttest": "JavaScript-ის ტესტირება",
-       "javascripttest-title": "მიმდინარეობს $1-ის ტესტირება",
        "javascripttest-pagetext-noframework": "ეს გვერდი დარეგისტრირებულია JavaScript-ის ტესტების გასაშვებად.",
        "javascripttest-pagetext-unknownframework": "„$1-ის“ ტესტირების უცნობი გარემო.",
+       "javascripttest-pagetext-unknownaction": "უცნობი ქმედება „$1“.",
        "javascripttest-pagetext-frameworks": "გთხოვთ, აირჩიეთ ტესტირების ერთ-ერთი შემდეგი გარემო: $1",
        "javascripttest-pagetext-skins": "ტესტების გასაშვებად აირჩიეთ გაფორმების თემა:",
        "javascripttest-qunit-intro": "იხილეთ [$1 ტესტირების დოკუმენტები] mediawiki.org-ზე.",
-       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit-ის ტესტების კრებული",
        "tooltip-pt-userpage": "თქვენი მომხმარებლის გვერდი",
        "tooltip-pt-anonuserpage": "ჩემი IP-ის მქონე მომხმარებლის გვერდი",
        "tooltip-pt-mytalk": "თქვენი განხილვის გვერდი",
index ceef910..189120b 100644 (file)
@@ -8,7 +8,8 @@
                        "Daniyar",
                        "GaiJin",
                        "Kaztrans",
-                       "Balnur.s"
+                       "Balnur.s",
+                       "Нұрлан Рахымжанов"
                ]
        },
        "tog-underline": "Сілтеменің астын сызу:",
        "blocklogtext": "Бұл қатысушыларды бұғаттау және бұғаттауынан босату әрекеттерінің журналы.\nӨздіктік бұғатталған IP мекенжайлар тізімделмеген.\nҚазіргі уақыттағы белсенді тиымдар мен бұғаттауларды [[Special:BlockList|бұғаттау тізімінен]] қараңыз.",
        "unblocklogentry": "$1 есімді қатысушыны бұғаттауынан босатты",
        "block-log-flags-anononly": "тек аноним қатысушылар",
-       "block-log-flags-nocreate": "тіркелуін өшіріді",
+       "block-log-flags-nocreate": "тіркелуін өшірді",
        "block-log-flags-noautoblock": "автобұғаттау өшірілген",
        "block-log-flags-noemail": "е-пошта өшірілген",
        "block-log-flags-nousertalk": "өз талқылау бетін өңдей алмайтындай ету",
index ca92b7e..2f14433 100644 (file)
        "protectedpages-timestamp": "시간 기록",
        "protectedpages-page": "문서",
        "protectedpages-expiry": "만료 기한",
-       "protectedpages-performer": "사용자를 보호",
+       "protectedpages-performer": "보호한 사용자",
        "protectedpages-params": "보호 변수",
        "protectedpages-reason": "이유",
        "protectedpages-unknown-timestamp": "알 수 없음",
        "import-logentry-interwiki": "$1 문서를 다른 위키에서 가져왔습니다",
        "import-logentry-interwiki-detail": "$2에서 {{PLURAL:$1|판}} $1개를 가져왔습니다",
        "javascripttest": "자바스크립트 테스트",
-       "javascripttest-title": "$1 테스트 실행",
        "javascripttest-pagetext-noframework": "이 문서는 자바스크립트 테스트를 실행하기 위한 용도로 할당되어 있습니다.",
        "javascripttest-pagetext-unknownframework": "실험용 프레임워크 \"$1\"를 알 수 없습니다.",
        "javascripttest-pagetext-frameworks": "다음 실험용 프레임워크 중 하나를 선택하세요: $1",
        "javascripttest-pagetext-skins": "실험할 스킨을 선택하세요:",
        "javascripttest-qunit-intro": "mediawiki.org의 [$1 테스트 설명서]를 참고하세요.",
-       "javascripttest-qunit-heading": "미디어위키 자바스크립트 QUnit 실험군",
        "tooltip-pt-userpage": "내 사용자 문서",
        "tooltip-pt-anonuserpage": "현재 사용하는 IP 주소의 사용자 문서",
        "tooltip-pt-mytalk": "내 토론 문서",
        "tags-tag": "태그 이름",
        "tags-display-header": "바뀜 목록의 모양",
        "tags-description-header": "태그에 대한 설명",
-       "tags-active-header": "í\99\9cì\84±í\95\98ê² ì\8aµë\8b\88ê¹\8c?",
+       "tags-active-header": "í\99\9cì\84±í\99\94 ì\97¬ë¶\80",
        "tags-hitcount-header": "태그된 바뀜",
        "tags-active-yes": "예",
        "tags-active-no": "아니오",
index 3772bf2..c8fd97e 100644 (file)
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (kuckt och [[Special:NewPages|Lëscht vun den neie Säiten]])",
        "recentchanges-legend-plusminus": "''(±123)''",
        "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",
+       "rclistfrom": "Nei Ännerunge vum $3 $2 u weisen",
        "rcshowhideminor": "Kleng Ännerunge $1",
        "rcshowhideminor-show": "Weisen",
        "rcshowhideminor-hide": "Verstoppen",
        "import-logentry-interwiki": "huet $1 importéiert (Transwiki)",
        "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.",
        "javascripttest-pagetext-unknownframework": "Onbekannten Test-Framework \"$1\".",
        "javascripttest-pagetext-frameworks": "Sicht w.e.g. eng vun dësen Test-Strukturen eraus: $1",
        "javascripttest-pagetext-skins": "Sicht en Interface (skin) eraus fir d'Tester ze maachen:",
        "javascripttest-qunit-intro": "Kuckt d'[$1 Dokumentatioun vun den Tester] op mediawiki.org",
-       "javascripttest-qunit-heading": "JavaScript-QUnit Testserie op MediaWiki",
        "tooltip-pt-userpage": "Är Benotzersäit",
        "tooltip-pt-anonuserpage": "Benotzersäit vun der IP-Adress vun där aus Dir den Ament Ännerunge maachtt",
        "tooltip-pt-mytalk": "Är Diskussiounssäit",
        "api-error-overwrite": "D'Iwwerschreiwe vun engem Fichier ass net erlaabt.",
        "api-error-stashfailed": "Interne Feeler: de Server konnt den temporäre Fichier net späicheren.",
        "api-error-publishfailed": "Interne Feeler: de Server konnt den temporäre Fichier net publizéieren.",
+       "api-error-stasherror": "Beim Eropluede vum Fichier ass e Feeler geschitt.",
        "api-error-stashzerolength": "De Server konnt de Fichier net späicheren, well en eng Längt vun Null hat.",
        "api-error-timeout": "De Server huet net bannen där Zäit geäntwert déi virgesinn ass.",
        "api-error-unclassified": "En onbekannte Feeler ass geschitt",
index fe6ae4c..e1e6250 100644 (file)
        "content-model-text": "نیسسه ساده",
        "content-model-javascript": "جاوا اسكريپت",
        "content-model-css": "سی اس اس",
+       "content-json-empty-object": "سرتال حالی",
        "expensive-parserfunction-warning": "<strong>زئنار:</strong>ای بلگه مینونه دار واحونی دستوریا مئن اشکافت فره ای هئ.\n\nانازه و باید د کمتر با$2 {{جمی:$2|واحونی|واحونیا}}، ایسه {{جمی:$1|$1 واحونی|$1 واحونیا}}ئه.",
        "expensive-parserfunction-category": "بلگه یایی که واحونی پیوندگر خطا گرون فره ای ها دشو",
        "post-expand-template-inclusion-warning": "زنئار چوئه د ور گرته انازه ای یه که فره گپه.پاره ای د چوئه یا نه د ور نمیئره.",
        "right-protect": "آلشت دئن انازه پر و پیم کردن بلگه یا و ویرایشت بلگه یا پر و پیم بیه تافی",
        "right-editprotected": "ویرایشت بلگه یا پر و پیم بیه چی «{{int:protect-level-sysop}}»",
        "right-editsemiprotected": "ویرایشت بلگه یا پر و پیم بیه چی «{{int:protect-level-autoconfirmed}}»",
+       "right-editcontentmodel": "ویرایشت مدل مینونه یه گل بلگه",
        "right-editinterface": "راوط کاریار نه ویرایشت کو",
        "right-editusercssjs": "جانیایا جاوا اسکریپت و سی اس اس کاریاریا هنی نه ویرایشت کو",
        "right-editusercss": "جانیایا سی اس اس کاریاریا هنی نه ویرایشت کو",
        "action-viewmywatchlist": "سیل برگ خوتونه بوینیت",
        "action-viewmyprivateinfo": "دونسمنیا خوتونه بوینیت",
        "action-editmyprivateinfo": "دونسمنیا شصقی خوتونه ویرایشت بکید",
+       "action-editcontentmodel": "ویرایشت مدل مینونه یه گل بلگه",
        "nchanges": "$1 {{جمی:$1|آلشت|آلشتیا}}",
        "enhancedrc-since-last-visit": "$1 {{جمی:$1|د آخری دیئن}}",
        "enhancedrc-history": "ويرگار",
        "import-logentry-interwiki": "$1 نه تراویکی کرد",
        "import-logentry-interwiki-detail": "$1 {{جمی:$1|وانئری|وانئریا}} د $2 وامین اومائنه",
        "javascripttest": "ازمایشت کردن جاوا اسکریپت",
-       "javascripttest-title": "د حال انجوم دئن ازمایشتیا $1",
        "javascripttest-pagetext-noframework": "ای بلگه سی انجوم دئن ازمایشتیا جاوا اسکریپت اماییه کاری بیه.",
        "javascripttest-pagetext-unknownframework": "چوئه کار نادیار ازمایشت \"$1\"",
        "javascripttest-pagetext-frameworks": "لطفن یه گل د چوئه یا ازمایشت هاری نه انتخاو بکیت :$1",
        "javascripttest-pagetext-skins": "یه گل پوسه نه سی انجوم دئن ازمایشتا انتخاو بکیت:",
        "javascripttest-qunit-intro": "[$1 مستندیا ازمایشت] نه د mediawiki.org سیل بکیت.",
-       "javascripttest-qunit-heading": "کومله ازمایشت QUnit جاوااسکریپت سی ویکی وارسگر",
        "tooltip-pt-userpage": "بلگه كارورتو",
        "tooltip-pt-anonuserpage": "بلگه کاریاری تیرنشون آی پی ای که دش ویرایشت می کید",
        "tooltip-pt-mytalk": "بلگه قسه كردن شما",
        "exif-objectcycle-p": "فقط ایواره",
        "exif-objectcycle-b": "هم شو صو و هم ایواره",
        "exif-dc-contributor": "هومیارا",
+       "exif-dc-date": "گاتیا",
        "exif-dc-publisher": "درتیجن",
        "exif-dc-relation": "وارسگر مرتوط",
        "exif-dc-rights": "حقوق",
        "exif-iimcategory-hth": "تن آزایی",
        "exif-iimcategory-hum": "حاستنی انسانی",
        "exif-iimcategory-lab": "کار",
+       "exif-iimcategory-lif": "گواردن زئشت و شادی کردن",
        "exif-iimcategory-pol": "سیاستا",
        "exif-iimcategory-rel": "دین و ائتقات",
        "exif-iimcategory-sci": "دونسمنی و سازیاری",
        "confirmemail": "پشت راس کردن تیرنشون انجومانامه",
        "confirmemail_send": "کل کردن رازینه پشت راس کاری",
        "confirmemail_sent": "انجومانامه پشت راس کردن کل بیه.",
+       "confirmemail_needlogin": "لطف بکید $1 نه سی تیرنشون انجومانامه تو پشت راس بکید.",
+       "confirmemail_success": "تیرنشون انجومانامه تو پشت راس بیه.\nشایت شما ایسه بهایت [[Special:چی یه گل کاریار|بیایت وامین]]و د ویکی لذت بوریت",
+       "confirmemail_loggedin": "تیرنشون انجومانامه شما ایسه پشت راس بیه.",
        "confirmemail_subject": "{{SITENAME}} تیرنشون انجومانامه پشت راست کردن",
        "confirmemail_invalidated": "پشت راس کنی انجومانامه انجوم شیو بیه",
        "invalidateemail": "انجومشیو کردن پشت راس کردن انجومانامه",
        "scarytranscludetoolong": "[یو آر ال فره گپه]",
+       "deletedwhileediting": "<strong>زئنار:</strong>ای بلگه د او گاتی که شما شرو د ویرایشت کردیته پاکسا بیه!",
        "recreate": "د نو راس کردن",
        "confirm_purge_button": "خوئه",
        "confirm-watch-button": "خوئه",
        "duplicate-defaultsort": "زنهار کلیت پیش فرض جور بیه $2 تازه ای یا کلید پیش فرض جوربیه $1 رد بیه.",
        "version": "نسقه",
        "version-extensions": "دمادیسیا پورسه",
+       "version-skins": "پوسه یا پورسه بیه",
        "version-specialpages": "بلگيا ويجه",
        "version-variables": "آلشت ونا",
        "version-antispam": "نهاگرتن هرزنومه",
        "version-other": "هنی",
        "version-hook-name": "نوم قلاو",
        "version-no-ext-name": "[بی نوم]",
+       "version-license": "لیسانس ویکی وارسگر",
        "version-ext-license": "ليسانس",
        "version-ext-colheader-name": "دمادیس",
        "version-skin-colheader-name": "پوسه",
        "version-entrypoints-header-url": "يو آر ال",
        "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Article path]",
        "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Script path]",
+       "version-libraries-library": "کتاوگه",
+       "version-libraries-version": "نسقه",
        "redirect": "واگردونی وا جانیا،بلگه یا وانیئری نوم دیارکو",
+       "redirect-legend": "واگردونی د جانیا یا بلگه",
        "redirect-submit": "رو",
        "redirect-lookup": "پی جوری:",
        "redirect-value": "ارزایشت:",
        "compare-page1": "بلگه 1",
        "compare-page2": "بلگه 2",
        "compare-rev1": "دوواره ديئن1",
+       "compare-rev2": "وانئری 2",
        "compare-submit": "کنار یک نیاین",
+       "compare-invalid-title": "داسونی که شما تیار کردیته خو نئ.",
        "compare-title-not-exists": "سرون مشقص بیه وجود ناره.",
        "compare-revision-not-exists": "وانئری که شما تی دیار کردیته وجود ناره.",
+       "dberr-info-hidden": "(نبوئه د رسینه گا دسرسی داشت)",
        "htmlform-required": "یه دئه واس بوئه.",
        "htmlform-submit": "دئن",
        "htmlform-reset": "انجومشیو کردن آلشتیا",
        "htmlform-chosen-placeholder": "یه گل گزینه انتخاو بکیت",
        "htmlform-cloner-create": "هنی اضاف بکیت",
        "htmlform-cloner-delete": "ؤرداشتن",
+       "htmlform-cloner-required": "سی کمترونه یه گل ارزایشت لازمه",
        "revdelete-content-hid": "مینونه قام بیه",
+       "revdelete-summary-hid": "چکسته ویرایشت قام بیه",
        "revdelete-uname-hid": "نوم کاروری قام بیه",
        "revdelete-content-unhid": "مینونه قام نبیه",
+       "revdelete-summary-unhid": "چکسته ویرایشت قام نبیه",
        "revdelete-uname-unhid": "نوم کاروری قام نبیه",
        "rightsnone": "(هيش كوم)",
        "revdelete-summary": "چکسه ویرایشت",
        "feedback-message": "پيغوم:",
        "feedback-cancel": "انجوم شیوسن",
        "feedback-submit": "کل کردن نهاهوال حون",
+       "feedback-error2": "خطا:ویرایشت خو نبی",
        "feedback-close": "انجوم بی",
        "feedback-bugnew": "مه وارسیش کردمه. یه گل سیسرک تازه گزارشت بی",
        "searchsuggest-search": "پی جوری",
        "log-description-pagelang": "ای پهرستنومه در بلگه زونا آلشت گرته.",
        "default-skin-not-found-row-enabled": "* <رازینه>$1</رازینه> / $2 ('''ناکنشتگر بیه''')",
        "default-skin-not-found-row-disabled": "* <رازینه>$1</رازینه> / $2 ('''ناکنشتگر بیه''')",
+       "mediastatistics": "آماریا وارسگر",
+       "mediastatistics-nbytes": "{{PLURAL:$1|$1 بایت|$1 بایتیا}} ($2; $3%)",
        "mediastatistics-table-count": "شماره جانیایا",
+       "mediastatistics-table-totalbytes": "انازه وه یک شیوسه",
        "mediastatistics-header-unknown": "نادیار",
        "mediastatistics-header-bitmap": "عسگیا بیت مپ",
+       "mediastatistics-header-drawing": "کشیاریا(عسگیا وکتور)",
        "mediastatistics-header-audio": "دنگ",
        "mediastatistics-header-video": "عسگ و فیلم",
        "mediastatistics-header-multimedia": "وارسگر خو",
index 8bb96b1..3aae964 100644 (file)
        "import-logentry-interwiki": "tarpprojektinis $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|keitimas|keitimai|keitimų}} iš $2",
        "javascripttest": "JavaScript testavimas",
-       "javascripttest-title": "Vykdomas $1 testavimas",
        "javascripttest-pagetext-noframework": "Šis puslapis yra skirtas vykdyti JavaScript testavimus.",
        "javascripttest-pagetext-unknownframework": "Nežinoma \"$1\" testavimo struktūra.",
        "javascripttest-pagetext-frameworks": "Prašome pasirinkti vieną iš išvardintų testavimo struktūrų: $1",
        "javascripttest-pagetext-skins": "Pasirinkite naudotojo sąsajos išvaizdą, kuriai atliksite testavimą:",
        "javascripttest-qunit-intro": "Peržiūrėkite [$1 testavimo dokumentaciją]",
-       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit bandymų komplektas",
        "tooltip-pt-userpage": "Jūsų naudotojo puslapis",
        "tooltip-pt-anonuserpage": "Naudotojo puslapis jūsų IP adresui",
        "tooltip-pt-mytalk": "Jūsų aptarimo puslapis",
index 4ac40e6..469a24c 100644 (file)
        "category-subcat-count-limited": "Šai kategorijai ir {{PLURAL:$1|viena apakškategorija|$1 apakškategorijas}}.",
        "category-article-count": "{{PLURAL:$2|Šī kategorija satur tikai šo vienu lapu.|Šajā kategorijā kopā ir $2 lapas, šobrīd ir {{PLURAL:$1|redzama viena no tām|redzamas $1 no tām}}.}}",
        "category-article-count-limited": "Šajā kategorijā ir {{PLURAL:$1|šī viena lapa|šīs $1 lapas}}.",
-       "category-file-count": "{{PLURAL:$2|Šī kategorija satur tikai šo vienu failu.|Šajā kategorijā ir $2 faili, no kuriem {{PLURAL:$1|redzams ir viens|ir redzami $1}}.}}",
+       "category-file-count": "{{PLURAL:$2|Šajā kategorijā ir $2 failu, no kuriem {{PLURAL:$1|ir redzami $1|redzams ir $1|ir redzami $1}}.|Šī kategorija satur tikai $2 failu.|Šajā kategorijā ir $2 faili, no kuriem {{PLURAL:$1|redzams ir $1|ir redzami $1}}.}}",
        "category-file-count-limited": "Šajā kategorijā atrodas {{PLURAL:$1|tikai šis fails|šie $1 faili}}.",
        "listingcontinuesabbrev": " (turpinājums)",
        "index-category": "Indeksētās lapas",
        "statistics-edits-average": "Vidējais izmaiņu skaits uz lapu",
        "statistics-users": "Reģistrēti lietotāji",
        "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-users-active-desc": "Lietotāji, kas ir veikuši jebkādu darbību {{PLURAL:$1|iepriekšējās $1 dienās|iepriekšējā $1 dienā|iepriekšējās $1 dienās}}",
        "pageswithprop-prop": "Īpašības nosaukums:",
        "pageswithprop-submit": "Aiziet",
        "doubleredirects": "Divkāršas pāradresācijas lapas",
        "listusers-blocked": "(bloķēts)",
        "activeusers": "Aktīvo lietotāju saraksts",
        "activeusers-intro": "Šis ir lietotāju saraksts, kas veikuši kādu darbību {{PLURAL:daudzskaitlī:$1|pēdējā|pēdējās}} $1 {{PLURAL:daudzskaitlī:$1|dienā|dienās}}.",
-       "activeusers-from": "Parādīt lietotājus sākot ar:",
+       "activeusers-count": "$1 {{PLURAL:$1|darbību|darbība|darbības}} {{PLURAL:$3|pēdējās $3 dienās|pēdējā $3 dienā|pēdējās $3 dienās}}",
+       "activeusers-from": "Parādīt lietotājus, sākot ar:",
        "activeusers-hidebots": "Paslēpt botus",
        "activeusers-hidesysops": "Paslēpt administratorus",
        "activeusers-noresult": "Neviens lietotājs nav atrasts.",
        "import-logentry-interwiki": "starpvikizēts $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|versija|versijas}} no $2",
        "javascripttest": "JavaScript testēšana",
-       "javascripttest-title": "Darbina $1 testus",
        "tooltip-pt-userpage": "Tava lietotāja lapa",
        "tooltip-pt-anonuserpage": "Manas IP adreses lietotāja lapa",
        "tooltip-pt-mytalk": "Tava diskusiju lapa",
        "mediawarning": "'''Brīdinājums''': Šis faila tips var saturēt ļaunprātīgu kodu, kuru izpildot, tava datora darbība var tikt traucēta.",
        "imagemaxsize": "Attēlu apraksta lapās parādāmo attēlu maksimālais izmērs:",
        "thumbsize": "Sīkbildes izmērs:",
-       "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|lapa|lapas}}",
+       "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|lapu|lapa|lapas}}",
        "file-info": "faila izmērs: $1, MIME tips: $2",
        "file-info-size": "$1 × $2 pikseļi, faila izmērs: $3, MIME tips: $4",
        "file-info-size-pages": "$1 × $2 pikseļi, faila izmērs: $3, MIME tips: $4, $5 {{PLURAL:$5|lapa|lapas}}",
        "autosumm-replace": "Aizvieto lapas saturu ar '$1'",
        "autoredircomment": "Pāradresē uz [[$1]]",
        "autosumm-new": "Jauna lapa: $1",
+       "autosumm-newblank": "Izveidota tukša lapa",
        "lag-warn-normal": "Izmaiņas, kas ir jaunākas par  $1 {{PLURAL:$1|sekundi|sekundēm}}, var neparādīties šajā sarakstā.",
        "lag-warn-high": "Sakarā ar lielu datubāzes servera lagu, izmaiņas, kas svaigākas par $1 {{PLURAL:$1|sekundi|sekundēm}}, šajā sarakstā var neparādīties.",
        "watchlistedit-normal-title": "Izmainīt uzraugāmo rakstu sarakstu",
index fb32b7c..bb5a495 100644 (file)
        "otherlanguages": "На други јазици",
        "redirectedfrom": "(Пренасочено од $1)",
        "redirectpagesub": "Пренасочувачка страница",
-       "redirectto": "Пренасочи кон:",
+       "redirectto": "Пренасочување кон:",
        "lastmodifiedat": "Последната промена на страницава е извршена на $1 г. во $2 ч.",
        "viewcount": "Оваа страница била посетена {{PLURAL:$1|еднаш|$1 пати}}.",
        "protectedpage": "Заштитена страница",
        "import-logentry-interwiki": "трансвикифиран $1",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|Увезена е една преработка|Увезени се $1 преработки}} од $2",
        "javascripttest": "Проба на JavaScript",
-       "javascripttest-title": "Вршам $1 проби",
        "javascripttest-pagetext-noframework": "Оваа страница е резервирана за вршење на проби со JavaScript.",
        "javascripttest-pagetext-unknownframework": "Непозната рамка „$1“.",
+       "javascripttest-pagetext-unknownaction": "Непознато дејство „$1“.",
        "javascripttest-pagetext-frameworks": "Изберете една од следниве рамки: $1",
        "javascripttest-pagetext-skins": "Одберете со кое руво да ја направите пробата:",
        "javascripttest-qunit-intro": "Вид. [$1 документација на испробувањето] на mediawiki.org.",
-       "javascripttest-qunit-heading": "JavaScript-програм за испробување на МедијаВики „QUnit“",
        "tooltip-pt-userpage": "Вашата корисничка страница",
        "tooltip-pt-anonuserpage": "Корисничка страница за IP-адресата од која уредувате",
        "tooltip-pt-mytalk": "Вашата страница за разговор",
index 9d05ce6..9a80c5c 100644 (file)
@@ -46,7 +46,7 @@
        "tog-shownumberswatching": "Tunjukkan bilangan pemantau",
        "tog-oldsig": "Tanda tangan yang sedia ada:",
        "tog-fancysig": "Anggap tandatangan sebagai teks wiki (tanpa pautan automatik)",
-       "tog-uselivepreview": "Gunakan pralihat langsung (dalam percubaan)",
+       "tog-uselivepreview": "Gunakan prebiu langsung",
        "tog-forceeditsummary": "Tanya saya jika ringkasan suntingan kosong",
        "tog-watchlisthideown": "Sembunyikan suntingan saya daripada senarai pantau",
        "tog-watchlisthidebots": "Sembunyikan suntingan bot daripada senarai pantau",
        "pool-queuefull": "Giliran kolam telah penuh",
        "pool-errorunknown": "Ralat tak diketahui",
        "pool-servererror": "Perkhidmatan kaunter tabung tidak disediakan ($1).",
+       "poolcounter-usage-error": "Ralat penggunaan: $1",
        "aboutsite": "Perihal {{SITENAME}}",
        "aboutpage": "Project:Perihal",
        "copyright": "Kandungan disediakan di bawah $1 melainkan dinyatakan sebaliknya.",
        "filerenameerror": "Nama fail \"$1\" tidak dapat ditukarkan kepada \"$2\".",
        "filedeleteerror": "Fail \"$1\" tidak dapat dihapuskan.",
        "directorycreateerror": "Direktori \"$1\" gagal diciptakan.",
+       "directoryreadonlyerror": "Direktori \"$1\" boleh dibaca sahaja.",
+       "directorynotreadableerror": "Direktori \"$1\" tidak boleh dibaca.",
        "filenotfound": "Fail \"$1\" tidak dijumpai.",
        "unexpected": "Nilai tanpa diduga: \"$1\"=\"$2\".",
        "formerror": "Ralat: Borang tidak dapat dikirim.",
        "anoneditwarning": "<strong>Amaran:</strong> Anda tidak log masuk. Alamat IP anda akan disiarkan kepada umum jika anda membuat sebarang suntingan. Jika anda <strong>[$1 log masuk]</strong> atau <strong>[$2 membuka akaun]</strong>, suntingan anda akan diatribusikan kepada nama pengguna anda di samping manfaat-manfaat lain.",
        "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.",
+       "selfredirect": "<strong>Amaran:</strong> Anda sedang melencongkan laman ini kepada dirinya sendiri.\nMungkin anda telah menyatakan sasaran yang salah untuk lencongan ini ataupun sedang tersalah menyunting halaman.\nJika anda mengklik \"{{int:savearticle}}\" semula, maka lencongan tetap akan dihasilkan.",
        "missingcommenttext": "Sila masukkan komen dalam ruangan di bawah.",
        "missingcommentheader": "'''Peringatan:''' Anda tidak menyatakan tajuk bagi komen ini. Klik '''{{int:savearticle}}''' sekali lagi untuk menyimpan suntingan ini tanpa tajuk.",
        "summary-preview": "Pralihat ringkasan:",
        "content-model-text": "teks biasa",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
+       "content-json-empty-object": "Objek kosong",
+       "content-json-empty-array": "Tatasusunan kosong",
        "duplicate-args-category": "Laman yang menggunakan argumen pendua dalam panggilan templat",
        "duplicate-args-category-desc": "Laman ini mengandungi panggilan templat yang menggunakan pendua argumen seperti <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> atau <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "Amaran: Laman ini mengandungi terlalu banyak panggilan fungsi penghurai yang intensif.\n\nHad panggilan ialah $2, sekarang terdapat $1 panggilan.",
        "history-feed-empty": "Laman yang diminta tidak wujud.\nMungkin ia telah dihapuskan atau namanya telah ditukar.\nCuba [[Special:Search|cari]] laman lain yang mungkin berkaitan.",
        "rev-deleted-comment": "(ringkasan suntingan dibuang)",
        "rev-deleted-user": "(nama pengguna dibuang)",
-       "rev-deleted-event": "(entri dibuang)",
+       "rev-deleted-event": "(butiran log terpadam)",
        "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].",
        "revdelete-legend": "Tetapkan batasan:",
        "revdelete-hide-text": "Teks semakan",
        "revdelete-hide-image": "Sembunyikan kandungan fail",
-       "revdelete-hide-name": "Sembunyikan tindakan dan sasaran",
+       "revdelete-hide-name": "Sembunyikan sasaran dan parameter",
        "revdelete-hide-comment": "Ringkasan suntingan",
        "revdelete-hide-user": "Nama pengguna/IP penyunting",
        "revdelete-hide-restricted": "Sekat data daripada penyelia dan pengguna lain",
        "right-protect": "Mengubah tahap perlindungan serta menyunting halaman yang dilindungi lata",
        "right-editprotected": "Menyunting halaman-halaman yang dilindungi sebagai \"{{int:protect-level-sysop}}\"",
        "right-editsemiprotected": "Menyunting halaman-halaman yang dilindungi sebagai \"{{int:protect-level-autoconfirmed}}\"",
+       "right-editcontentmodel": "Menyunting model kandungan laman",
        "right-editinterface": "Menyunting antara muka pengguna",
        "right-editusercssjs": "Menyunting fail CSS dan JavaScript pengguna lain",
        "right-editusercss": "Menyunting fail CSS pengguna lain",
        "action-viewmywatchlist": "melihat senarai pantau sendiri",
        "action-viewmyprivateinfo": "melihat maklumat peribadi sendiri",
        "action-editmyprivateinfo": "menyunting maklumat peribadi sendiri",
+       "action-editcontentmodel": "menyunting model kandungan laman",
        "nchanges": "$1 perubahan",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|sejak lawatan terakhir}}",
        "enhancedrc-history": "sejarah",
        "thumbnail-temp-create": "Fail gambar kenit sementara tidak dapat dibuat",
        "thumbnail-dest-create": "Gambar kenit tidak dapat disimpan dalam destinasi",
        "thumbnail_invalid_params": "Parameter gambar kenit tidak sah",
+       "thumbnail_toobigimagearea": "Fail dengan dimensi melebihi $1",
        "thumbnail_dest_directory": "Direktori destinasi gagal diwujudkan",
        "thumbnail_image-type": "Jenis imej tidak disokong",
        "thumbnail_gd-library": "Tatarajah perpustakaan GD tidak lengkap: kehilangan fungsi $1",
        "import-logentry-interwiki": "$1 dipindahkan ke wiki lain",
        "import-logentry-interwiki-detail": "$1 semakan diimportkan daripada $2",
        "javascripttest": "Ujian JavaScript",
-       "javascripttest-title": "Ujian $1 sedang dijalankan",
        "javascripttest-pagetext-noframework": "Laman ini ditempah untuk menjalankan ujian JavaScript.",
        "javascripttest-pagetext-unknownframework": "Kerangka \"$1\" tidak dikenali.",
+       "javascripttest-pagetext-unknownaction": "Tindakan \"$1\" tidak dikenali.",
        "javascripttest-pagetext-frameworks": "Sila pilih salah satu kerangka yang berikut: $1",
        "javascripttest-pagetext-skins": "Sila pilih satu kulit untuk menjalankan ujian:",
        "javascripttest-qunit-intro": "Lihat [$1 pendokumenan ujian] di mediawiki.org.",
-       "javascripttest-qunit-heading": "Suit ujian MediaWiki JavaScript QUnit",
        "tooltip-pt-userpage": "Laman pengguna anda",
        "tooltip-pt-anonuserpage": "Laman pengguna bagi alamat IP anda",
        "tooltip-pt-mytalk": "Laman perbincangan anda",
        "version-entrypoints-header-url": "URL",
        "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath Laluan rencana]",
        "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Laluan skrip]",
+       "version-libraries": "Perpustakaan terpasang",
+       "version-libraries-library": "Perpustakaan",
+       "version-libraries-version": "Versi",
        "redirect": "Lencongkan mengikut ID fail, pengguna, halaman atau semakan",
        "redirect-legend": "Lencongkan ke fail atau halaman",
        "redirect-summary": "Halaman khas ini melencong kepada fail (dengan nama fail), halaman (dengan ID semakan atau ID halaman) atau halaman pengguna (dengan ID pengguna berangka). Penggunaan: [[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], atau [[{{#Special:Redirect}}/user/101]].",
        "compare-revision-not-exists": "Semakan yang anda nyatakan tidak wujud.",
        "dberr-problems": "Harap maaf. Tapak web ini dilanda masalah teknikal.",
        "dberr-again": "Cuba tunggu selama beberapa minit dan muat semula.",
-       "dberr-info": "(Tidak dapat menghubungi pelayan pangkalan data: $1)",
-       "dberr-info-hidden": "(Pelayan pangkalan data tidak dapat dihubungi)",
+       "dberr-info": "(Tidak dapat mengakses pangkalan data: $1)",
+       "dberr-info-hidden": "(Tidak dapat mengakses pangkalan data)",
        "dberr-usegoogle": "Buat masa ini, anda boleh cuba mencari melalui Google.",
        "dberr-outofdate": "Sila ambil perhatian bahawa indeks mereka bagi kandungan kami mungkin sudah ketinggalan zaman.",
        "dberr-cachederror": "Yang berikut ialah salinan bagi laman yang diminta yang diambil daripada cache, dan mungkin bukan yang terkini.",
index d4f8088..7ccab35 100644 (file)
        "right-viewmyprivateinfo": "Vide 'e proprie date private (e.g. e-mail, nomme overo)",
        "right-editmyprivateinfo": "Cagna 'e date perzunale proprie (p'esempio: e-mail, nomme overo)",
        "right-editmyoptions": "Cagna 'e preferenze proprie",
-       "right-rollback": "Annulla ampresso 'e cagnamiente 'e ll'urdem'utente c'avesse cagnato na paggena particolare",
+       "right-rollback": "Annulla ampresso 'e cagnamiente 'e ll'urdem'utente c'avesse cagnato na paggena particulare",
        "right-markbotedits": "Nzégna 'e cagnamiente suggette a rollback comme affettuate 'a nu bot",
        "right-noratelimit": "Nun suggetto a lemmeto d'aziune",
        "right-import": "Carreca paggene 'a n'ati wiki",
        "action-suppressionlog": "vide stu riggistro privato",
        "action-block": "blocca 'e cagnamiente 'a parte 'e st'utente",
        "action-protect": "cagna 'e livelle 'e prutezione pe' sta paggena",
-       "action-rollback": "annulla ampresso 'e cagnamiente 'e ll'urdem'utente c'avesse cagnato na paggena particolare",
+       "action-rollback": "annulla ampresso 'e cagnamiente 'e ll'urdem'utente c'avesse cagnato na paggena particulare",
        "action-import": "carreca paggene 'a n'ata wiki",
        "action-importupload": "carreca paggene 'a n'upload 'e file",
        "action-patrol": "nzegna 'e cagnamiente 'e l'ati utente comme cuntrullate",
        "statistics-users-active-desc": "Utente c'hanno fatto coccosa dint' 'a {{PLURAL:$1|l'urdemo juorno|l'urdeme $1 juorne}}",
        "pageswithprop": "Paggene cu na prupietà 'e paggena",
        "pageswithprop-legend": "Paggene cu na prupietà 'e paggena",
-       "pageswithprop-text": "Sta paggena alenca 'e paggene c'ausano na prupietà particolare 'e paggena.",
+       "pageswithprop-text": "Sta paggena alenca 'e paggene c'ausano na prupietà particulare 'e paggena.",
        "pageswithprop-prop": "Nomme d' 'a prupietà:",
        "pageswithprop-submit": "Vàje",
        "pageswithprop-prophidden-long": "valore d' 'a prupietà d' 'o testo luongo annascunnuto ($1)",
        "move-over-sharedrepo": "== 'O file esiste ==\n[[:$1]] esiste ncopp'a l'archivio spartuto. Spustanno 'o file ncopp'a stu titolo sovrascreverrà 'o file spartuto.",
        "file-exists-sharedrepo": "'O nomme d' 'o file c'avite scigliuto se sta ausanno dint'a l'archivio spartuto.\nPe' piacere, scigliete n'atu nomme.",
        "export": "Spurta 'e ppaggene",
-       "exporttext": "Vuje putite espurtà 'e teste e cagnà 'a cronologgia 'e na paggena particolare o n'inzieme 'e paggena ca stessero dint' 'a cocche XML.\nChisto po' essere 'mpurtato int'a n'ata wiki ausanno [[Special:Import|mporta pàggene]] 'e MediaWiki.\n\nPe' spurtà paggene, mettite 'o titolo dint' 'e casciulelle ccà abbascio, nu titolo pe' linea e sciglite si vulite 'a verziona 'e mò cu tutt' 'e verziun' 'assieme, o pùre sulamente 'a verziona 'e mò c' 'a nfurmaziona ncopp' 'a ll'urdemo cagnamiento.\n\nComme urtema possibbiletà, putite pure ausà nu cullegamento, p'esempio [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] p' 'a pàggena \"[[{{MediaWiki:Mainpage}}]]\".",
+       "exporttext": "Vuje putite espurtà 'e teste e cagnà 'a cronologgia 'e na paggena particulare o n'inzieme 'e paggena ca stessero dint' 'a cocche XML.\nChisto po' essere 'mpurtato int'a n'ata wiki ausanno [[Special:Import|mporta pàggene]] 'e MediaWiki.\n\nPe' spurtà paggene, mettite 'o titolo dint' 'e casciulelle ccà abbascio, nu titolo pe' linea e sciglite si vulite 'a verziona 'e mò cu tutt' 'e verziun' 'assieme, o pùre sulamente 'a verziona 'e mò c' 'a nfurmaziona ncopp' 'a ll'urdemo cagnamiento.\n\nComme urtema possibbiletà, putite pure ausà nu cullegamento, p'esempio [[{{#Special:Export}}/{{MediaWiki:Mainpage}}]] p' 'a pàggena \"[[{{MediaWiki:Mainpage}}]]\".",
        "exportall": "Spurta tutt' 'e paggene",
        "exportcuronly": "Appenne sulamente 'a verziona 'e mo, e nun tutt' 'a cronologgia",
        "exportnohistory": "----\n'''Vedite bbuono:''' 'A funzione 'esportazione d' 'a storia sana d' 'e paggene, ausanno stu modulo, è stata stutata pe' mutive 'e prestaziune.",
        "import-logentry-interwiki": "trasferito 'a n'ata wiki 'a paggena $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|verzione|verziune}} mpurtate 'a $2",
        "javascripttest": "Test JavaScript",
-       "javascripttest-title": "Secutanno test pe' $1",
        "javascripttest-pagetext-noframework": "Sta paggena è riservata pe' l'esecuziune d' 'e test 'e Javascript.",
        "javascripttest-pagetext-unknownframework": "Ambiente 'e test scanusciuto \"$1\".",
+       "javascripttest-pagetext-unknownaction": "Azione scanusciuta \"$1\".",
        "javascripttest-pagetext-frameworks": "Pe' piacere sciglite uno 'e ll'ambiente 'e test ccà abbascio: $1",
        "javascripttest-pagetext-skins": "Sciglite nu skin pe' ne fà 'e test:",
        "javascripttest-qunit-intro": "Vedite 'a [$1 documentaziona d' 'o test] ncopp'a mediawiki.org.",
-       "javascripttest-qunit-heading": "Ambiente 'e test MediaWiki JavaScript QUnit",
        "tooltip-pt-userpage": "A toja paggena utente",
        "tooltip-pt-anonuserpage": "'A paggena utente pe l'IP ca vuje state cagnanno cumme",
        "tooltip-pt-mytalk": "A toja paggena 'e discussione",
        "version-poweredby-others": "ati",
        "version-poweredby-translators": "tradutture 'e translatewiki.net",
        "version-credits-summary": "Nuje vulessemo tené a mmente 'e perzune ccà abbascio pe' purtà rispetto a 'e cuntribbute 'e lloro ncopp'a [[Special:Version|MediaWiki]].",
-       "version-license-info": "MediaWiki è nu software libbero; vuje 'o putite redestribbuì e/o cagnà sott' 'e termine d' 'a licienza GNU GPL ('a Licienza Pubbreca Generale) comme pubbrecata d' 'a Free Software Foundation; o pure 'a verziona 2 d' 'a Licienza, o pure (comme vulite vuje) 'a n'ata verziona cchiù nnova.\n\nMediaWiki è destribbuita c' 'a speranza d'essere utile, ma SENZA NISCIUNA GARANZIA; senza manco 'a garanzia p' 'a CUMMERCIABBELETÀ O IDONIETÀ PE' NU SCOPO PARTICOLARE. Iate a vedé 'a GNU GPL pe' n'avé cchiù nfurmaziune.\n\nAvísseve 'a ricevere [{{SERVER}}{{SCRIPTPATH}}/COPYING na copia d' 'a Licienza GNU GPL] cu stu prugramma; si nò, scrivete â Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA o [//www.gnu.org/licenses/old-licenses/gpl-2.0.html liggite sta paggena ncopp' 'a l'Internet].",
+       "version-license-info": "MediaWiki è nu software libbero; vuje 'o putite redestribbuì e/o cagnà sott' 'e termine d' 'a licienza GNU GPL ('a Licienza Pubbreca Generale) comme pubbrecata d' 'a Free Software Foundation; o pure 'a verziona 2 d' 'a Licienza, o pure (comme vulite vuje) 'a n'ata verziona cchiù nnova.\n\nMediaWiki è destribbuita c' 'a speranza d'essere utile, ma SENZA NISCIUNA GARANZIA; senza manco 'a garanzia p' 'a CUMMERCIABBELETÀ O IDONIETÀ PE' NU SCOPO PARTICULARE. Iate a vedé 'a GNU GPL pe' n'avé cchiù nfurmaziune.\n\nAvísseve 'a ricevere [{{SERVER}}{{SCRIPTPATH}}/COPYING na copia d' 'a Licienza GNU GPL] cu stu prugramma; si nò, scrivete â Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA o [//www.gnu.org/licenses/old-licenses/gpl-2.0.html liggite sta paggena ncopp' 'a l'Internet].",
        "version-software": "Software installato",
        "version-software-product": "Prodotto",
        "version-software-version": "Verziona",
index f1ae3b7..738a1df 100644 (file)
        "nosuchsectiontitle": "Finner ikke avsnittet",
        "nosuchsectiontext": "Du prøvde å redigere et avsnitt som ikke eksisterer.\nDet kan ha blitt flyttet eller slettet mens du så på siden.",
        "loginreqtitle": "Innlogging kreves",
-       "loginreqlink": "logge inn",
+       "loginreqlink": "logg inn",
        "loginreqpagetext": "Du må $1 for å se andre sider.",
        "accmailtitle": "Passord sendt.",
        "accmailtext": "Et tilfeldig passord for [[User talk:$1|$1]] har blitt sendt til $2. Det kan endres på [[Special:ChangePassword|passordendringssiden]] under innlogging.",
        "import-logentry-interwiki": "transwikiimporterte $1",
        "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.",
        "javascripttest-pagetext-unknownframework": "Ukjent testerammeverk \"$1\".",
        "javascripttest-pagetext-frameworks": "Vennligst velg en av følgende testerammeverk: $1",
        "javascripttest-pagetext-skins": "Velg et utseende for testene:",
        "javascripttest-qunit-intro": "Se [$1 testedokumentasjonen] på mediawiki.org.",
-       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit testsuite",
        "tooltip-pt-userpage": "Din brukerside",
        "tooltip-pt-anonuserpage": "Brukersiden for IP-adressen du redigerer fra",
        "tooltip-pt-mytalk": "Din diskusjonsside",
index 59c7262..741ec6d 100644 (file)
        "import-logentry-interwiki": "transwiki $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|versie|versies}} van $2",
        "javascripttest": "JavaScript testen",
-       "javascripttest-title": "Tests uutvoeren veur $1",
        "javascripttest-pagetext-noframework": "Disse zied is ereserveerd veur t uutvoeren van JavaScript-testen.",
        "javascripttest-pagetext-unknownframework": "Onbekend testraamwark \"$1\".",
        "javascripttest-pagetext-frameworks": "Kies een van de volgende testraamwarken: $1",
        "javascripttest-pagetext-skins": "Kies n vormgeving um de tests mee uut te voeren:",
        "javascripttest-qunit-intro": "Zie de [$1 testdokumentasie] op mediawiki.org.",
-       "javascripttest-qunit-heading": "QUnit testsuite veur MediaWiki JavaScript",
        "tooltip-pt-userpage": "Oew gebroekersbladziede",
        "tooltip-pt-anonuserpage": "Gebroekersbladziede vuur t IP-adres da'j broekt",
        "tooltip-pt-mytalk": "Oew oaverlegbladziede",
index b41abf6..7ec749c 100644 (file)
        "import-logentry-interwiki": "importeerde $1 via transwiki",
        "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.",
        "javascripttest-pagetext-unknownframework": "Onbekend testframework \"$1\".",
        "javascripttest-pagetext-frameworks": "Kies een van de volgende testframeworks: $1",
        "javascripttest-pagetext-skins": "Kies een vormgeving om de tests mee uit te voeren:",
        "javascripttest-qunit-intro": "Zie de [$1 testdocumentatie] op mediawiki.org.",
-       "javascripttest-qunit-heading": "QUnit testsuite voor MediaWiki JavaScript",
        "tooltip-pt-userpage": "Uw gebruikerspagina",
        "tooltip-pt-anonuserpage": "Gebruikerspagina voor uw IP-adres",
        "tooltip-pt-mytalk": "Uw overlegpagina",
index e6d89d1..3c63b4d 100644 (file)
        "import-logentry-interwiki": "overførte $1 mellom wikiar",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|Éin versjon|$1 versjonar}} frå $2",
        "javascripttest": "JavaScript-utrøyning",
-       "javascripttest-title": "Køyrer $1-utrøyningar",
        "javascripttest-pagetext-noframework": "Sida er reservert for køyring av JavaScript-utrøyningar.",
        "javascripttest-pagetext-unknownframework": "Ukjent utrøyningsrammeverk: «$1».",
+       "javascripttest-pagetext-unknownaction": "Ukjend handling \"$1\".",
        "javascripttest-pagetext-frameworks": "Vel eitt av dei fylgjande utrøyningsrammeverka: $1",
        "javascripttest-pagetext-skins": "Vel ei drakt som utrøyningane skal køyrast med:",
        "javascripttest-qunit-intro": "Sjå [$1 utrøyningsdokumentasjon] på mediawiki.org.",
-       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit testsuite",
        "tooltip-pt-userpage": "Brukarsida di",
        "tooltip-pt-anonuserpage": "Brukarsida for ip-adressa du endrar under",
        "tooltip-pt-mytalk": "Diskusjonssida di",
index 8818f47..03cce48 100644 (file)
@@ -72,7 +72,8 @@
                        "Py64",
                        "Nanaki",
                        "Alan ffm",
-                       "Macofe"
+                       "Macofe",
+                       "Devwebtel"
                ]
        },
        "tog-underline": "Podkreślenie linków:",
        "filerenameerror": "Nie można zmienić nazwy pliku „$1” na „$2”.",
        "filedeleteerror": "Nie można usunąć pliku „$1”.",
        "directorycreateerror": "Nie udało się utworzyć katalogu „$1”.",
+       "directoryreadonlyerror": "Ścieżka \"$1\" jest tylko do odczytu.",
+       "directorynotreadableerror": "Ścieżka \"$1\" nie jest odczytywalna.",
        "filenotfound": "Nie można znaleźć pliku „$1”.",
        "unexpected": "Nieoczekiwana wartość „$1”=„$2”.",
        "formerror": "Błąd – nie można wysłać formularza",
        "import-logentry-interwiki": "zaimportował(a) $1 używając transwiki",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|wersja|wersje|wersji}} z $2",
        "javascripttest": "Testowanie JavaScript",
-       "javascripttest-title": "Uruchamianie testów $1",
        "javascripttest-pagetext-noframework": "Ta strona jest zarezerwowana dla wykonywania testów JavaScript.",
        "javascripttest-pagetext-unknownframework": "Nieznany framework testowania „$1”.",
+       "javascripttest-pagetext-unknownaction": "Nieznana akcja \"$1\".",
        "javascripttest-pagetext-frameworks": "Wybierz jeden z następujących frameworków testowania: $1",
        "javascripttest-pagetext-skins": "Wybierz skórkę, na której chcesz uruchomić testy:",
        "javascripttest-qunit-intro": "Zobacz [$1 dokumentację testów] na mediawiki.org.",
-       "javascripttest-qunit-heading": "Pakiet testów JavaScriptu MediaWiki QUnit",
        "tooltip-pt-userpage": "Moja osobista strona",
        "tooltip-pt-anonuserpage": "Strona użytkownika dla adresu IP, spod którego edytujesz",
        "tooltip-pt-mytalk": "Moja strona dyskusji",
        "compare-revision-not-exists": "Wybrana wersja nie istnieje.",
        "dberr-problems": "Przepraszamy! Witryna ma problemy techniczne.",
        "dberr-again": "Spróbuj przeładować stronę za kilka minut.",
-       "dberr-info": "(Brak komunikacji z serwerem bazy danych – $1)",
-       "dberr-info-hidden": "(Nie można skontaktować się z serwerem bazy danych)",
+       "dberr-info": "(Błąd łączności z bazą danych: $1)",
+       "dberr-info-hidden": "(Błąd łączności z bazą danych)",
        "dberr-usegoogle": "Możesz spróbować wyszukać w międzyczasie za pomocą Google.",
        "dberr-outofdate": "Uwaga – indeksy zawartości serwisu mogą być nieaktualne.",
        "dberr-cachederror": "Strona została pobrana z pamięci podręcznej i może być nieaktualna.",
index 194e415..f680753 100644 (file)
        "import-logentry-interwiki": "Amportà da n'àutra wiki $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revision}} amportà da $2",
        "javascripttest": "Preuva ëd JavaScript",
-       "javascripttest-title": "Fé dle preuve $1",
        "javascripttest-pagetext-noframework": "Costa pàgina a l'é arservà për fé dle preuve JavaScript.",
        "javascripttest-pagetext-unknownframework": "Strutura ëd preuva pa conossùa «$1».",
+       "javascripttest-pagetext-unknownaction": "Assion nen conossùa «$1».",
        "javascripttest-pagetext-frameworks": "Për piasì, ch'a serna un-a dle struture ëd preuva sì-dapress: $1",
        "javascripttest-pagetext-skins": "Ch'a serna na pel për fé le preuve:",
        "javascripttest-qunit-intro": "Vëdde [$1 la documentassion dle preuve] dzora a mediawiki.org.",
-       "javascripttest-qunit-heading": "Sequensa ëd preuve QUnit ëd JavaScript su MediaWiki",
        "tooltip-pt-userpage": "Soa pàgina utent",
        "tooltip-pt-anonuserpage": "La pàgina utent për l'IP con ël qual chiel a contribuiss",
        "tooltip-pt-mytalk": "Soa pàgina ëd discussion e ciaciarade",
index 576eeb7..b5540e0 100644 (file)
@@ -63,7 +63,8 @@
                        "아라",
                        "Leon saudanha",
                        "Macofe",
-                       "He7d3r"
+                       "He7d3r",
+                       "Ti4goc"
                ]
        },
        "tog-underline": "Sublinhar ligações:",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
        "content-json-empty-object": "Objeto vazio",
+       "content-json-empty-array": "Matriz vazia",
        "duplicate-args-category": "Páginas que utilizam argumentos duplicados ao chamar predefinições",
+       "duplicate-args-category-desc": "A página contém campos de predefinições que utilizam duplicatas de argumentos, tais como <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> ou <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "'''Aviso:''' Esta página contém demasiadas chamadas de funções exigentes do analisador sintático.\n\nDevia ter menos de $2 {{PLURAL:$2|chamada|chamadas}}. Neste momento tem $1 {{PLURAL:$1|chamada|chamadas}}.",
        "expensive-parserfunction-category": "Páginas com demasiadas chamadas a funções exigentes",
        "post-expand-template-inclusion-warning": "Aviso: O tamanho de inclusão de predefinições é demasiado grande, algumas predefinições não serão incluídas.",
        "right-protect": "Mudar níveis de proteção e editar páginas protegidas em cascata",
        "right-editprotected": "Editar páginas protegidas como \"{{int:protect-level-sysop}}\"",
        "right-editsemiprotected": "Editar páginas protegidas como \"{{int:protect-level-autoconfirmed}}\"",
+       "right-editcontentmodel": "Editar o modelo de conteúdo de uma página",
        "right-editinterface": "Editar a interface de utilizador",
        "right-editusercssjs": "Editar os ficheiros CSS e JS de outros utilizadores",
        "right-editusercss": "Editar os ficheiros CSS de outros utilizadores",
        "action-viewmywatchlist": "ver a sua lista de páginas vigiadas",
        "action-viewmyprivateinfo": "ver a sua informação privada",
        "action-editmyprivateinfo": "editar a sua informação privada",
+       "action-editcontentmodel": "editar o modelo de conteúdo de uma página",
        "nchanges": "$1 {{PLURAL:$1|alteração|alterações}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|desde a última visita}}",
        "enhancedrc-history": "histórico",
        "protect-othertime": "Outra duração:",
        "protect-othertime-op": "outra duração",
        "protect-existing-expiry": "A proteção atual expirará às $3 de $2",
+       "protect-existing-expiry-infinity": "Existente tempo de expiração: infinito",
        "protect-otherreason": "Outro motivo/motivo adicional:",
        "protect-otherreason-op": "Outro motivo",
        "protect-dropdown": "*Motivos comuns para proteção\n** Vandalismo excessivo\n** ''Spam'' excessivo\n** Guerra de edições improdutiva\n** Página muito visitada",
        "thumbnail-temp-create": "Não foi possível criar o ficheiro temporário da miniatura",
        "thumbnail-dest-create": "Não é possível gravar a miniatura no destino",
        "thumbnail_invalid_params": "Parâmetros de miniatura inválidos",
+       "thumbnail_toobigimagearea": "Ficheiro com dimensões superiores a $1",
        "thumbnail_dest_directory": "Não foi possível criar o diretório de destino",
        "thumbnail_image-type": "Tipo de imagem não suportado",
        "thumbnail_gd-library": "Configuração da biblioteca GD incompleta: função $1 em falta",
        "import-logentry-interwiki": "transwikis $1",
        "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.",
        "javascripttest-pagetext-unknownframework": "Estrutura de testes \"$1\" desconhecida.",
+       "javascripttest-pagetext-unknownaction": "Ação \"$1\" desconhecida.",
        "javascripttest-pagetext-frameworks": "Escolha, por favor, uma das seguintes estruturas de teste: $1",
        "javascripttest-pagetext-skins": "Escolher um tema para executar os testes com:",
        "javascripttest-qunit-intro": "Consulte a [ $1 documentação de testes] no mediawiki.org.",
-       "javascripttest-qunit-heading": "Pacote de ferramentas de teste de JavaScript QUnit do MediaWiki",
        "tooltip-pt-userpage": "A sua página de utilizador",
        "tooltip-pt-anonuserpage": "A página de utilizador para o endereço IP que está a usar",
        "tooltip-pt-mytalk": "A sua página de discussão",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|discussão]])",
        "duplicate-defaultsort": "<strong>Aviso:</strong> A chave de ordenação padrão \"$2\" sobrepõe-se à anterior \"$1\".",
        "duplicate-displaytitle": "<strong>Aviso:</strong> Exibir título \"$2\" substituindo o título anteriormente em exibição \"$1\".",
+       "invalid-indicator-name": "<strong>Erro:</strong> O atributo <code>name</code>, da página de estados, não deve estar em branco.",
        "version": "Versão",
        "version-extensions": "Extensões instaladas",
        "version-skins": "Temas instalados",
        "api-error-stashfailed": "Erro interno: O servidor não conseguiu armazenar o ficheiro temporário.",
        "api-error-publishfailed": "Erro interno: Servidor não conseguiu publicar ficheiro temporário.",
        "api-error-stasherror": "Ocorreu um erro no carregamento do ficheiro escondido.",
+       "api-error-stashedfilenotfound": "O escondido ficheiro não foi encontrado ao tentar carregar a pasta do stash.",
+       "api-error-stashpathinvalid": "O caminho no qual o ficheiro escondido deveria ter sido encontrado era inválido.",
+       "api-error-stashfilestorage": "Ocorreu um erro no carregamento do ficheiro escondido.",
+       "api-error-stashzerolength": "O servidor não pôde esconder o ficheiro, porque ele tinha de comprimento zero.",
+       "api-error-stashnotloggedin": "Você deve estar com sessão iniciaca para gravar ficheiros no carregamento do stash.",
+       "api-error-stashwrongowner": "O ficheiro que estava a tentar aceder o stash não pertence a você.",
+       "api-error-stashnosuchfilekey": "O ficheiro de chave que está a tentar aceder no stash não existe.",
        "api-error-timeout": "O servidor não respondeu no prazo esperado.",
        "api-error-unclassified": "Ocorreu um erro desconhecido",
        "api-error-unknown-code": "Erro desconhecido: \"$1\"",
        "expand_templates_generate_xml": "Mostrar a árvore de análise sintáctica do XML",
        "expand_templates_generate_rawhtml": "Mostrar o HTML puro",
        "expand_templates_preview": "Antevisão do resultado",
+       "expand_templates_preview_fail_html": "<em>Devido ao fato de {{SITENAME}} possuir código HTML puro ativado e de ter havido perda de dados da sessão, a pré-visualização ficará oculta como precaução contra ataques do JavaScript.</em>\n\n<strong>Se esta é uma legítima tentativa de visualização, por favor tente novamente.</strong> Se não resultar, experimente [[Special:UserLogout|sair]] e iniciar sessão de novo.",
+       "expand_templates_preview_fail_html_anon": "<em>Devido ao fato de {{SITENAME}} possuir código HTML puro ativado e de não ter sessão iniciada, a pré-visualização ficará oculta como precaução contra ataques do JavaScript.</em>\n\n<strong>Se esta é uma legítima tentativa de visualização, por favor [[Especial:UserLogin|inicie sessão]] e tente novamente.</strong>",
        "pagelanguage": "Seletor de idioma da página",
        "pagelang-name": "Página",
        "pagelang-language": "Idioma",
index 2b383ec..504658e 100644 (file)
        "deleteprotected": "Used as error message when deleting the page.\n\n\"If protection keeps them from editing, they shouldn't be able to delete.\"",
        "deleting-backlinks-warning": "A warning shown when a page that is being deleted has at least one link to it or is transcluded in at least one page.",
        "rollback": "{{Identical|Rollback}}",
-       "rollback_short": "{{Identical|Rollback}}",
        "rollbacklink": "{{Doc-actionlink}}\nThis link text appears on the recent changes page to users who have the \"rollback\" right.\nThis message has a tooltip {{msg-mw|tooltip-rollback}}\n{{Identical|Rollback}}",
        "rollbacklinkcount": "{{doc-actionlink}}\nText of the rollback link showing the number of edits to be rolled back. See also {{msg-mw|rollbacklink}}.\n\nParameters:\n* $1 - the number of edits that will be rolled back. If $1 is over the value of <code>$wgShowRollbackEditCount</code> (default: 10) {{msg-mw|rollbacklinkcount-morethan}} is used.\n\nThe rollback link is displayed with a tooltip {{msg-mw|Tooltip-rollback}}",
        "rollbacklinkcount-morethan": "{{doc-actionlink}}\nText of the rollback link when a greater number of edits is to be rolled back. See also {{msg-mw|rollbacklink}}.\n\nWhen the number of edits rolled back is smaller than [[mw:Special:MyLanguage/Manual:$wgShowRollbackEditCount|$wgShowRollbackEditCount]], {{msg-mw|rollbacklinkcount}} is used instead.\n\nParameters:\n* $1 - number of edits",
        "namespace": "This message is located at [[Special:Contributions]].\n{{Identical|Namespace}}",
        "invert": "Displayed in [[Special:RecentChanges|RecentChanges]], [[Special:RecentChangesLinked|RecentChangesLinked]] and [[Special:Watchlist|Watchlist]].\n\nThis message means \"Invert selection of namespace\".\n\nThis message has a tooltip {{msg-mw|tooltip-invert}}\n{{Identical|Invert selection}}",
        "tooltip-invert": "Used in [[Special:Recentchanges]] as a tooltip for the invert checkbox. See also the message {{msg-mw|invert}}",
+       "tooltip-whatlinkshere-invert": "Used in [[Special:Whatlinkshere]] as a tooltip for the invert checkbox.\n\nSee also:\n* {{msg-mw|tooltip-invert}}\n* {{msg-mw|invert}}",
        "namespace_association": "Used in [[Special:Recentchanges]] with a checkbox which selects the associated namespace to be added to the selected namespace, so that both are searched (or excluded depending on another checkbox selection). The association is between a namespace and its talk namespace.\n\nThis message has a tooltip {{msg-mw|tooltip-namespace association}}",
        "tooltip-namespace_association": "Used in [[Special:Recentchanges]] as a tooltip for the associated namespace checkbox.\n\nSee also:\n* {{msg-mw|Namespace association}}",
        "blanknamespace": "Name for main namespace (blank namespace) in drop-down menus at [[Special:RecentChanges]] and other special pages.\n{{Identical|Main}}",
index 15051fe..447aa72 100644 (file)
        "import-logentry-interwiki": "transwikificat $1",
        "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.",
        "javascripttest-pagetext-unknownframework": "Cadru de testare „$1” necunoscut.",
+       "javascripttest-pagetext-unknownaction": "Acțiunea „$1” necunoscută.",
        "javascripttest-pagetext-frameworks": "Alegeți unul din următoarele cadre de testare: $1",
        "javascripttest-pagetext-skins": "Alegeți un aspect pentru care să rulați teste:",
        "javascripttest-qunit-intro": "A se vedea [$1 documentația de testare] pe mediawiki.org.",
-       "javascripttest-qunit-heading": "Suita de test MediaWiki JavaScript QUnit",
        "tooltip-pt-userpage": "Pagina dumneavoastră de utilizator",
        "tooltip-pt-anonuserpage": "Pagina de utilizator pentru adresa IP curentă",
        "tooltip-pt-mytalk": "Pagina dumneavoastră de discuții",
index ba87880..2f4824e 100644 (file)
@@ -33,7 +33,7 @@
        "tog-shownumberswatching": "Fa vedè 'u numere de le utinde ca uardene",
        "tog-oldsig": "Firme esistende:",
        "tog-fancysig": "Firma grezze cumme a 'nu teste de Uicchi (senza collegamende automatiche)",
-       "tog-uselivepreview": "Ause l'andeprime da 'u vive (Sperimendale)",
+       "tog-uselivepreview": "Ause l'andeprime da 'u vive",
        "tog-forceeditsummary": "Ciércame conferme quanne stoche a 'nzerische 'nu riepighe vianghe",
        "tog-watchlisthideown": "Scunne le cangiaminde mije da l'elenghe de le pàggene condrollate",
        "tog-watchlisthidebots": "Scunne le cangiaminde de le bot da l'elenghe de le pàggene condrollate",
        "hidetoc": "scunne",
        "collapsible-collapse": "Scunne",
        "collapsible-expand": "Spanne",
+       "confirmable-yes": "Sìne",
+       "confirmable-no": "None",
        "thisisdeleted": "Vide o ripristine $1?",
        "viewdeleted": "Vue ccu vide $1?",
        "restorelink": "{{PLURAL:$1|'nu cangiamende scangellete|$1 cangiaminde scangellete}}",
        "autoblockid": "Autoblocche #$1",
        "block": "Bluècche l'utende",
        "unblock": "Sbluècche l'utende",
-       "blockip": "Blocche l'utende",
+       "blockip": "Blocche {{GENDER:$1|l'utende}}",
        "blockip-legend": "Bluecche l'utende",
        "blockiptext": "Ause 'a schermata de sotte pe bloccà l'accesse in scritture de 'nu specifiche indirizze IP o utende.\nQuiste avessa essere fatte sulamende pe prevenìe 'u vandalisme e in accorde cu [[{{MediaWiki:Policy-url}}|le reghele]].\nMitte pure 'nu mutive specifiche aqquà sotte (pe esembije, nnomene 'a pàgene addò è acchiate 'u vandalisme).",
        "ipaddressorusername": "Indirizze IP o nome de l'utende:",
        "ipb-unblock-addr": "Sblocche $1",
        "ipb-unblock": "Sblocche nome utende o indirizze IP",
        "ipb-blocklist": "Vide le blocche ca esistene",
-       "ipb-blocklist-contribs": "Condrebbute pe $1",
+       "ipb-blocklist-contribs": "Condrebbute pe {{GENDER:$1|$1}}",
        "unblockip": "Sblocche l'utende",
        "unblockiptext": "Ause 'a maschera aqquà sotte pe repristinà l'accesse in scritture a le indirizze IP o a le cunde utinde ca apprime avèrene state bloccate.",
        "ipusubmit": "Live stu blocche",
        "importlogpage": "Archivie de le 'mbortaziune",
        "importlogpagetext": "'Mbortaziune amministrative de pàggene cu 'a storie de le cangiaminde da otre Uicchi.",
        "import-logentry-upload": "'mbortete [[$1]] da 'u fail carechete",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revisione|revisiune}}",
+       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revisione|revisiune}} 'mbortate",
        "import-logentry-interwiki": "transuicchied $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisione|revisiune}} da $2",
+       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revisione|revisiune}} 'mbortate da $2",
        "javascripttest": "Test de JavaScript",
-       "javascripttest-title": "Stoche a esegue $1 test",
        "javascripttest-pagetext-noframework": "Sta pàgene jè riservate pe le esecuziune de le test de Javascript.",
        "javascripttest-pagetext-unknownframework": "Ambiende de teste scanusciute \"$1\".",
        "javascripttest-pagetext-frameworks": "Pe piacere scacchie une de le seguende ambiende de test: $1",
        "javascripttest-pagetext-skins": "Scacchie 'n'aspette pe eseguì le test cu:",
        "javascripttest-qunit-intro": "Vide 'a [$1 documendazione d'u test] sus a mediawiki.org.",
-       "javascripttest-qunit-heading": "Ambiende de test MediaUicchi JavaScript QUnit",
        "tooltip-pt-userpage": "'A pàgene utende meje",
        "tooltip-pt-anonuserpage": "'A pàgene utende pe l'IP ca tu ste cange cumme",
        "tooltip-pt-mytalk": "'Ngazzaminde mie",
        "duplicate-defaultsort": "'''Attenziò:''' 'A chiave de arrangamende de default \"$2\" sovrascrive quedda precedende \"$1\".",
        "version": "Versione",
        "version-extensions": "Estenziune installete",
-       "version-skins": "Skin",
+       "version-skins": "Skin installate",
        "version-specialpages": "Pàggene speciele",
        "version-parserhooks": "Hook analizzature",
        "version-variables": "Variabbele",
        "compare-revision-not-exists": "'A revisione ca è specificate non g'esiste.",
        "dberr-problems": "Sime spiacende! Stu site stè 'ngondre de le difficoltà tecniche.",
        "dberr-again": "Aspitte quacche minute e pò recareche.",
-       "dberr-info": "(Non ge riuscime a condattà 'u server d'u database: $1)",
-       "dberr-info-hidden": "(Non ge pozze condattà 'u server d'u database)",
+       "dberr-info": "(Non ge riuscime a trasè sus a'u server d'u database: $1)",
+       "dberr-info-hidden": "(Non ge pozze trasè sus a'u server d'u database)",
        "dberr-usegoogle": "Pu mumende tu puè pruvà a cercà cu Google.",
        "dberr-outofdate": "Vide ca le indice lore de le condenute nuèstre ponne essere non aggiornate.",
        "dberr-cachederror": "Queste jè 'na copie ''cache'' d'a pàgene ca è cercate e allore non g'à puè cangià.",
index 8198723..c9b93f9 100644 (file)
        "import-logentry-interwiki": "«$1» — межвики импорт",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|версия импортирована|версии импортировано|версий  импортировано}} из $2",
        "javascripttest": "Проверка JavaScript",
-       "javascripttest-title": "Проводится проверка $1",
        "javascripttest-pagetext-noframework": "Эта страница зарезервирована для запуска JavaScript-тестов.",
        "javascripttest-pagetext-unknownframework": "Неизвестная среда тестирования «$1».",
        "javascripttest-pagetext-frameworks": "Пожалуйста, выберите одну из следующих сред тестирования: $1",
        "javascripttest-pagetext-skins": "Выберите тему оформления для запуска тестов:",
        "javascripttest-qunit-intro": "См. [$1 документацию по тестированию] на mediawiki.org.",
-       "javascripttest-qunit-heading": "Набор тестов MediaWiki JavaScript QUnit",
        "tooltip-pt-userpage": "Ваша страница участника",
        "tooltip-pt-anonuserpage": "Страница участника для моего IP",
        "tooltip-pt-mytalk": "Ваша страница обсуждения",
index 58edae8..d9bc166 100644 (file)
        "import-logentry-interwiki": "ट्रान्स्विकिकृतम् ।$1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|पुनरावृत्तिः}} $2 इत्येतस्मात् ।",
        "javascripttest": "जावालिपिपरीक्षणम् ।",
-       "javascripttest-title": "$1 परीक्षाप्रचलति ।",
        "javascripttest-pagetext-noframework": "जावलिपिचालनपरीक्षार्थम् एतत्पुटम् आरक्षितम् ।",
        "javascripttest-pagetext-unknownframework": "अज्ञातपरीक्षाप्रक्रिया  $1",
        "javascripttest-pagetext-frameworks": "अधो दत्तेषु कञ्चिदेकां परीक्षाप्रक्रियां चिनोतु : $1",
        "javascripttest-pagetext-skins": "अनेन सह परीक्षां सञ्चालयितुं  काचित् त्वक् चिनोतु ।",
        "javascripttest-qunit-intro": "mediawiki.org. [$1 अभिलेखपरीक्षा] इत्यत्र पश्यतु ।",
-       "javascripttest-qunit-heading": "मिडियाविक्याः जवालिपेः Qघटकस्य परीक्षाप्रणाली ।",
        "tooltip-pt-userpage": "भवतः/भवत्याः योजकपृष्ठम्",
        "tooltip-pt-anonuserpage": "ऐपिसङ्केतार्थं योजकपुटं भवान् सम्पादयति एवम्..",
        "tooltip-pt-mytalk": "भवतः/भवत्याः सम्भाषणपृष्ठम्",
index 0ac257b..527aec5 100644 (file)
@@ -32,7 +32,7 @@
        "tog-watchdeletion": "Agghiunci li pàggini e li file chi' cancellu â me lista talïata",
        "tog-watchrollback": "Agghiunci li pàggini unni fici nu canciu n'arreri â me lista talïata",
        "tog-minordefault": "Marca ogni' canciamentu comu nicu pi' mpustazzioni pridifinuta",
-       "tog-previewontop": "Ammustra l'antiprima avanti dâ caseḍḍa di canciamentu",
+       "tog-previewontop": "Ammustra l'antiprima avanti dâ casedda di canciamentu",
        "tog-previewonfirst": "Ammustra l'antiprima ô primu canciamentu",
        "tog-enotifwatchlistpages": "Mànnami nu missàggiu di posta elittrònica quannu na pàggina o nu file dâ me lista talïata subbìsciunu canciamenti",
        "tog-enotifusertalkpages": "Mànnami nu missaggiu di posta elettrònica quannu la me pàggina di discussioni veni canciata",
@@ -57,8 +57,8 @@
        "tog-prefershttps": "Adòpira sempri na cunnissioni sicura quannu si' trasutu",
        "underline-always": "Sempri",
        "underline-never": "Mai",
-       "underline-default": "Mpustazzioni pridifinuta dâ peḍḍi o dû browser",
-       "editfont-style": "Stili dû caràttiri dâ caseḍḍa di canciamentu:",
+       "underline-default": "Mpustazzioni pridifinuta dâ peddi o dû browser",
+       "editfont-style": "Stili dû caràttiri dâ casedda di canciamentu:",
        "editfont-default": "Pridifinutu dô browser",
        "editfont-monospace": "Tipu di caràttiri a' larghizza fissa",
        "editfont-sansserif": "Tipu di caràttiri senza grazzî",
@@ -81,7 +81,7 @@
        "february": "Frivaru",
        "march": "Marzu",
        "april": "Aprili",
-       "may_long": "Maju",
+       "may_long": "Maiu",
        "june": "Giugnu",
        "july": "Giugnettu",
        "august": "Aùstu",
@@ -93,7 +93,7 @@
        "february-gen": "frivaru",
        "march-gen": "marzu",
        "april-gen": "aprili",
-       "may-gen": "maju",
+       "may-gen": "maiu",
        "june-gen": "giugnu",
        "july-gen": "giugnettu",
        "august-gen": "austu",
        "feb": "friv",
        "mar": "mar",
        "apr": "apr",
-       "may": "maju",
+       "may": "maiu",
        "jun": "giu",
        "jul": "giugn",
        "aug": "aus",
        "february-date": "$1 di frivaru",
        "march-date": "$1 di marzu",
        "april-date": "$1 di aprili",
-       "may-date": "$1 di maju",
+       "may-date": "$1 di maiu",
        "june-date": "$1 di giugnu",
        "july-date": "$1 di giugnettu",
        "august-date": "$1 di aùstu",
        "category_header": "Pàggini ntâ catigurìa \"$1\"",
        "subcategories": "Suttacatigurìi",
        "category-media-header": "File multimidiali ntâ catigurìa \"$1\"",
-       "category-empty": "<em>Sta catigurìa pi' com'ora nun cunteni nuḍḍa pàggina e nuḍḍu file multimidiali.</em>",
+       "category-empty": "<em>Sta catigurìa pi' com'ora nun cunteni nudda pàggina e nuddu file multimidiali.</em>",
        "hidden-categories": "{{PLURAL:$1|Catigurìa ammucciata|Catigurìi ammuciati}}",
        "hidden-category-category": "Catigurìi ammucciati",
        "category-subcat-count": "{{PLURAL:$2|Sta catigurìa cunteni na sula suttacatigurìa, nnicata ccà sutta.|Sta catigurìa cunteni {{PLURAL:$1|la suttacatigurìa|li $1 suttacatigurìi nnicati}} ccà sutta, sùpira nu tutali di $2.}}",
        "missing-article": "La basi di dati nun attruvau lu testu di na pàggina ch'avìssi avutu a' attruvari, cu' nomu \"$1\" $2.\n\nSta cosa di sòlitu succedi quannu s'arrichiama, a' pàrtiri di na crunuluggìa o di nu cunfruntu tra virsioni, nu culligamentu a na pàggina chi' fu' cancillata.\n\nSi' nun è accussì, po' èssiri ca scupristi nu bug ntô software.\nPi' favuri signala stu fattu a' n'[[Special:ListUsers/sysop|amministraturi]], spicificannu l'URL.",
        "missingarticle-rev": "(№ di virsioni: $1)",
        "missingarticle-diff": "(Diff: $1, $2)",
-       "readonly_lag": "La basi di dati fu' bluccata autumaticamenti nta mentri ca li server di basi di dati slave si sincrunìzzanu cu' chiḍḍu master",
+       "readonly_lag": "La basi di dati fu' bluccata autumaticamenti nta mentri ca li server di basi di dati slave si sincrunìzzanu cu' chiddu master",
        "internalerror": "Erruri nternu",
        "internalerror_info": "Erruri nternu: $1",
        "filecopyerror": "Nun fu' pussìbbili cupiari lu file \"$1\" nta \"$2\".",
        "badarticleerror": "St'opirazzioni nun è cunsintuta nta sta pàggina.",
        "cannotdelete": "Nun fu' pussìbbili cancillari la pàggina o lu file \"$1\".\nPutissi aviri statu già cancillatu di quarchidun'autru.",
        "cannotdelete-title": "Nun è pussìbbili cancillari la pàggina \"$1\"",
-       "delete-hook-aborted": "Cancillazzioni annullata di n'hook.\nNun desi nuḍḍa spiegazzioni.",
+       "delete-hook-aborted": "Cancillazzioni annullata di n'hook.\nNun desi nudda spiegazzioni.",
        "no-null-revision": "Non fu' pussibbili crïari na virsioni nulla pâ paggina \"$1\"",
        "badtitle": "Tìtulu nun bonu",
        "badtitletext": "Lu tìtulu di pàggina addumannatu nun era vàlidu, era vacanti, o vinìa dûn culligamentu intir-linguìsticu o intir-wiki malu fattu.\nPutissi cuntèniri unu o cchiu' ssai caràttiri chi' nun su' cunsintuti ntê tìtula.",
        "createacct-benefit-body1": "{{PLURAL:$1|cuntribbutu|cuntribbuti}}",
        "createacct-benefit-body2": "{{PLURAL:$1|pàggina|pàggini}}",
        "createacct-benefit-body3": "{{PLURAL:$1|cuntribbuturi ricenti|cuntribbutura ricenti}}",
-       "badretype": "Li password chi' mittisti nun currispùnnunu tra d'iḍḍi.",
+       "badretype": "Li password chi' mittisti nun currispùnnunu tra d'iddi.",
        "userexists": "Lu nomu utenti nziritu è già usatu.\nTi prijamu pirciò di vuliri scègghîri nu nomu utenti diffirenti.",
        "loginerror": "Erruri ntâ trasuta",
        "createacct-error": "Erruri ntâ crïazzioni dû cuntu",
        "noname": "Nun spicificasti nu nomu utenti vàlidu.",
        "loginsuccesstitle": "Trasuta rinisciuta",
        "loginsuccess": "<strong>Ora si' trasutu nta {{SITENAME}} comu \"$1\".</strong>",
-       "nosuchuser": "Nun è riggistratu nuḍḍu utenti di nomu \"$1\".\nLi nomi di l'utenti fannu diffirenza tra majusculi e minusculi.\nCuntrolla chi' scrivisti lu nomu bonu, o puru [[Special:UserLogin/signup|crea un cuntu novu]].",
-       "nosuchusershort": "Nun è riggistratu nuḍḍu utenti di nomu \"$1\".\nCuntrolla chi' scrivisti u nomu bonu.",
+       "nosuchuser": "Nun è riggistratu nuddu utenti di nomu \"$1\".\nLi nomi di l'utenti fannu diffirenza tra majusculi e minusculi.\nCuntrolla chi' scrivisti lu nomu bonu, o puru [[Special:UserLogin/signup|crea un cuntu novu]].",
+       "nosuchusershort": "Nun è riggistratu nuddu utenti di nomu \"$1\".\nCuntrolla chi' scrivisti u nomu bonu.",
        "nouserspecified": "Hâ' spicificari un nomu utenti.",
        "login-userblocked": "St'utenti è bluccatu. Nun è pussìbbili di tràsiri.",
        "wrongpassword": "La password chi' mittisti nun è giusta.\nPi' favuri prova n'àutra vota.",
        "emailnotauthenticated": "Lu to nnirizzu di posta elittrònica ancora nun havi statu cunfirmatu.\nNun ti sarrannu mannati missaggi di posta elittrònica pi' sti funzioni.",
        "noemailprefs": "Innicari nu nnirizzu di posta elittrònica p'attivari sti funzioni.",
        "emailconfirmlink": "Cunfirmari lu to nnirizzu di posta elittrònica",
-       "invalidemailaddress": "Lu nnirizzu di posta elittrònica nun pò èssiri accittatu picchì pari chi havi un furmatu nun vàlidu.\nPi favuri nzirisci nu nnirizzu vàlidu o puru svacanta la caseḍḍa.",
+       "invalidemailaddress": "Lu nnirizzu di posta elittrònica nun pò èssiri accittatu picchì pari chi havi un furmatu nun vàlidu.\nPi favuri nzirisci nu nnirizzu vàlidu o puru svacanta la casedda.",
        "cannotchangeemail": "Li nnirizzi di posta elittrònica nun ponnu èssiri canciati nta sta wiki.",
        "emaildisabled": "Stu situ nun po' mannari missaggi di posta elittrònica.",
        "accountcreated": "Cuntu crïatu",
        "passwordreset-username": "Nomu utenti:",
        "passwordreset-domain": "Duminiu:",
        "passwordreset-capture": "Ammustrari u missaggiu e-mail chi' veni cumpostu?",
-       "passwordreset-capture-help": "Si attivi sta caseḍḍa, u missaggiu e-mail (câ password timpurania) veni ammustratu a' tia sparti chi' veni mannatu a' l'utenti.",
+       "passwordreset-capture-help": "Si attivi sta casedda, u missaggiu e-mail (câ password timpurania) veni ammustratu a' tia sparti chi' veni mannatu a' l'utenti.",
        "passwordreset-email": "Nnirizzu di posta elittrònica:",
        "passwordreset-emailtitle": "Dittagghî dû cuntu supra a' {{SITENAME}}",
        "passwordreset-emailtext-ip": "Quarchidunu (prubbabilmenti tu, di l'innirizzu IP $1) fici dumanna pi' l'azziramentu dâ to password pi' {{SITENAME}} ($4). {{PLURAL:$3|U siguenti cuntu utenti è assuciatu|I siguenti cunti utenti su' assuciati}} cu' stu nnirizzu di posta elittrònica:\n\n$2\n\n{{PLURAL:$3|Sta password timpurania|Sti password timpuranii}} scàdunu tra {{PLURAL:$5|un jornu|$5 jorna}}.\nOra tu avissi a' tràsiri e scègghîri na password nova. Si' fu' quarchidun'autru a' fari sta richiesta e nun tu, o si' ti ricurdasti a to password origginali e nâ voi canciari cchiu', poi gnurari stu missaggiu e cuntinuari a' adupirari a to password vecchia.",
        "changeemail-no-info": "Hâ' jèssiri trasutu p'aviri accessu direttu a' sta pàggina.",
        "changeemail-oldemail": "Nnirizzu di posta elittrònica attuali:",
        "changeemail-newemail": "Nnirizzu di posta elittrònica novu:",
-       "changeemail-none": "(nuḍḍu)",
+       "changeemail-none": "(nuddu)",
        "changeemail-password": "A to password di {{SITENAME}}:",
        "changeemail-submit": "Cancia nnirizzu",
        "changeemail-throttled": "Hai fattu troppi tintativi di trasuta.\nPi' favuri spetta $1 prima di pruvari n'autra vota.",
        "preview": "Antiprima",
        "showpreview": "Ammustra l'antiprima",
        "showdiff": "Ammustra li canciamenti",
-       "blankarticle": "<strong>Accura:</strong> La pàggina chi' stai criannu è vacanti.\nSi' clicchi \"{{int:savearticle}}\" n'autra vota, la pàggina veni crïata senza nuḍḍu cuntinutu.",
+       "blankarticle": "<strong>Accura:</strong> La pàggina chi' stai criannu è vacanti.\nSi' clicchi \"{{int:savearticle}}\" n'autra vota, la pàggina veni crïata senza nuddu cuntinutu.",
        "anoneditwarning": "<strong>Accura:</strong> Nun si' trasutu. Lu to nnirizzu IP diventa visìbbili pubblicamenti quannu fai nu canciamentu. Si' <strong>[$1 trasi]</strong> o puru <strong>[$2 crei nu cuntu]</strong>, li canciamenti chi' fai vènunu attribbuiti ô to nomu utenti, sparti di autri vantaggi.",
        "anonpreviewwarning": "''Nun trasisti comu utiliggaturi loggatu. Sarbannu, lu tò nnirizzu IP veni arriggistratu ntâ storia dî canciamenti.''",
        "missingsummary": "'''Accura:''' Nun hà statu spicificatu l'uggettu di stu canciamentu. Primennu di novu '''Sarva''' lu canciamentu veni sarvatu cu l'uggettu vacanti.",
-       "selfredirect": "<strong>Accura:</strong> Stai rimannannu sta pàggina a' iḍḍa stissa.\nPo' jèssiri chi' spicificasti na distinazzioni sbagghiata pû rimannu, o puru chi' stai canciannu a pàggina sbagghiata.\nSi' clicchi \"{{int:savearticle}}\" n'autra vota, u rimannu veni criatu u stissu.",
+       "selfredirect": "<strong>Accura:</strong> Stai rimannannu sta pàggina a' idda stissa.\nPo' èssiri chi' spicificasti na distinazzioni sbagghiata pû rimannu, o puru chi' stai canciannu a pàggina sbagghiata.\nSi' clicchi \"{{int:savearticle}}\" n'autra vota, u rimannu veni criatu u stissu.",
        "missingcommenttext": "Nziriri un cummentu ccà sutta.",
        "missingcommentheader": "<strong>Accura:</strong> Nun havi statu spicificatu l'oggettu/ntistazzioni di stu cummentu. Primennu di novu \"{{int:savearticle}}\", lu canciamentu veni sarvatu senza avìrinni.",
        "summary-preview": "Antiprima dû riassuntu:",
        "blockedtitle": "L'utenti è bluccatu",
        "blockedtext": "'''Stu nomu d'utenti o nnirizzu IP havi statu bluccatu.'''\n\nLu bloccu fu fattu di $1. Lu mutivu dû bloccu è: ''$2''.\n\n* Accuminzata dû bloccu: $8\n* Fini dû bloccu: $6\n* Ntirvallu dû bloccu: $7\n\nPoi cuntattari a $1 o a n'àutru [[{{MediaWiki:Grouppage-sysop}}|amministraturi]] pi discùtiri dû bloccu.\n\nNun poi usari la carattirìstica 'manna n'email a st'utenti' siddu nun è spicificatu nu nnirizzu email vàlidu nta li toi [[Special:Preferences|prifirenzi]] e siddu nun hai statu bluccatu di l'usari.\n\nLu tò nnirizzu IP attuali è $3, e lu nùmmiru ID dû bloccu è #$5.\n\nSpicìfica tutti li dittagghi pricidenti nta quarsiasi addumannata di chiarimenti.",
        "autoblockedtext": "Lu tò nnirizzu IP hà statu bluccatu automaticamenti pirchì fu usatu di n'àutru utenti, chi fu bluccatu di $1.\nLu mutivu è chistu:\n\n:''$2''\n\n* Accuminzata dû bloccu: $8\n* Fini dû bloccu: $6\n* Ntirvallu dû bloccu: $7\n\nPoi cuntattari a $1 o a n'àutru [[{{MediaWiki:Grouppage-sysop}}|amministraturi]] pi discùtiri dû bloccu.\n\nNun poi usari la carattirìstica 'manna n'email a st'utenti' siddu nun è spicificatu nu nnirizzu email vàlidu ntra li tòi [[Special:Preferences|prifirenzi]] e siddu nun fusti bluccatu di l'usari.\n\nLu tò nnirizzu IP attuali è $3, e l'ID dû bloccu è $5.\nPi favuri nclùdilu nta tutti li dumanni chi fai.",
-       "blockednoreason": "nuḍḍa mutivazioni data",
+       "blockednoreason": "nuddu mutivu datu",
        "whitelistedittext": "Pi' favuri $1 pi' canciari li pàggini.",
        "confirmedittext": "Hâ' cunvalidari lu to nnirizzu di posta elittrònica avanti di putiri canciari li pàggini.\nPi' favuri mposta e cunvàlida lu nnirizzu passannu dî [[Special:Preferences|to prifirenzi]].",
        "nosuchsectiontitle": "La sizzioni nun fu' truvata",
        "note": "<strong>Nota:</strong>",
        "previewnote": "<strong>Ricòrditi ca chista è sulu n'antiprima.</strong>\nLi to canciamenti ancora nun foru sarvati!",
        "continue-editing": "Vai a' l'aria di mudìfica",
-       "previewconflict": "St'antiprima currispunni a lu testu prisenti ntâ caseḍḍa di canciamentu cchiu' supra e rapprisenta la pàggina comu cumpariravi siddu scegghî di sarvàrila.",
+       "previewconflict": "St'antiprima currispunni a lu testu prisenti ntâ casedda di canciamentu cchiu' supra e rapprisenta la pàggina comu cumpariravi siddu scegghî di sarvàrila.",
        "session_fail_preview": "<strong>Purtroppu nun hà statu pussìbbili sarvari li tò canciamenti pirchì li dati dâ sissioni hannu jutu pirduti.</strong>\nPi' favuri prova n'autra vota.\nSiddu ancora nun funziona, prova a' [[Special:UserLogout|nèsciri]] e tràsiri n'autra vota.",
        "session_fail_preview_html": "'''Semu spiacenti, nun hà statu pussìbbili elabburari lu canciamentu pirchì hannu jutu pirduti li dati rilativi â sissioni.'''\n\n''Poichì nta stu situ è abbilitatu l'usu di HTML senza limitazzioni, l'antiprima nun veni visualizzata; si tratta di na misura di sicurizza contra l'attacchi JavaScript.''\n\n'''Siddu chistu è nu tintativu liggìttimu di canciamentu, arriprova. Siddu lu prubbrema pirsisti, si pò pruvari a [[Special:UserLogout|sculligàrisi]] e effittuari n'accessu novu.'''",
        "token_suffix_mismatch": "'''Lu canciamentu nun fu sarvatu pirchì lu client ammustrau di gèstiri 'n modu sbagghiatu li caràttiri di puntiggiatura nta lu token assuciatu a iddu. P'evitari na curruzzioni pussìbbili dô testu dâ pàggina, fu rifiutatu tuttu lu canciamentu. Sta situazzioni pò virificàrisi, certi voti, quannu s'adòpiranu arcuni sirvizza di proxy anònimi via web chi prisèntanu bug.'''",
        "explainconflict": "N'àutru utenti havi sarvatu na virsioni nova dâ pàggina mentri stavi effittuannu li canciamenti.\nLa casella di canciamentu supiriuri cunteni lu testu dâ pàggina attuarmenti online, accussì comu hà statu aggiurnatu di l'àutru utenti.\nLa virsioni cu li tò canciamenti è mmeci ripurtata ntâ casella di canciamentu nfiriuri.\nSiddu addisìi cunfirmàrili, hai a ripurtari li tò canciamenti ntô testu asistenti (casella supiriuri).\nPrimennu lu pulsanti '{{int:savearticle}}', veni sarvatu '''sulu''' lu testu cuntinutu ntâ casella di canciamentu supiriuri.",
        "yourtext": "Lu tò testu",
        "storedversion": "La virsioni mimurizzata",
-       "nonunicodebrowser": "<strong>Accura: Lu to browser nun supporta bonu l'Unicode.</strong>\nFu' attivata na contramisura pi' cunsintìriti di canciari li pàggini in sicurizza: li caràttiri nun-ASCII spuntirannu nta la caseḍḍa di mudìfica comu còdici esadicimali.",
+       "nonunicodebrowser": "<strong>Accura: Lu to browser nun supporta bonu l'Unicode.</strong>\nFu' attivata na contramisura pi' cunsintìriti di canciari li pàggini in sicurizza: li caràttiri nun-ASCII spuntirannu nta la casedda di mudìfica comu còdici esadicimali.",
        "editingold": "'''Accura: si sta canciannu na virsioni nun aggiurnata dâ pàggina.<br /> Siddu si scegghi di sarvàrila, tutti li canciamenti appurtati doppu sta rivisioni vannu pirduti.'''",
        "yourdiff": "Diffirenzi",
-       "copyrightwarning": "Pi' favuri nota ca tutti li cuntribbuti mannati a' {{SITENAME}} s'hannu a' cunsiddirari sutta â licenza d'usu $2 (talìa $1 pî dittagghî).\nSi' nun voi ca li to testi vènunu mudificati senza nuḍḍu riguardu e ridistribbuùti a' vogghia, allura nê mannari cca.<br />\nMannannu lu to testu nni dichiari sparti chi' lu scrivisti tu pirsunalmenti, o puru ca lu cupiasti di na fonti di pùbblicu duminiu o analugamenti lìbbira.\n<strong>Nun mannari matiriali cupertu di drittu d'auturi senza auturizzazzioni!</strong>",
-       "copyrightwarning2": "Pi' favuri nota ca tutti li cuntribbuti mannati a' {{SITENAME}} ponnu vèniri canciati, altirati o cancillati di l'autri participanti.\nSi' nun voi ca li to testi vènunu mudificati senza nuḍḍu riguardu, allura nê mannari cca.<br />\nMannannu lu to testu nni dichiari sparti ca lu scrivisti tu pirsunalmenti, o puru ca lu cupiasti di na fonti di pùbblicu duminiu o analugamenti lìbbira (talìa $1 pi' majuri dittagghî).\n<strong>Nun mannari matiriali cupertu di drittu d'auturi senza auturizzazzioni!</strong>",
+       "copyrightwarning": "Pi' favuri nota ca tutti li cuntribbuti mannati a' {{SITENAME}} s'hannu a' cunsiddirari sutta â licenza d'usu $2 (talìa $1 pî dittagghî).\nSi' nun voi ca li to testi vènunu mudificati senza nuddu riguardu e ridistribbuùti a' vogghia, allura nê mannari cca.<br />\nMannannu lu to testu nni dichiari sparti chi' lu scrivisti tu pirsunalmenti, o puru ca lu cupiasti di na fonti di pùbblicu duminiu o analugamenti lìbbira.\n<strong>Nun mannari matiriali cupertu di drittu d'auturi senza auturizzazzioni!</strong>",
+       "copyrightwarning2": "Pi' favuri nota ca tutti li cuntribbuti mannati a' {{SITENAME}} ponnu vèniri canciati, altirati o cancillati di l'autri participanti.\nSi' nun voi ca li to testi vènunu mudificati senza nuddu riguardu, allura nê mannari cca.<br />\nMannannu lu to testu nni dichiari sparti ca lu scrivisti tu pirsunalmenti, o puru ca lu cupiasti di na fonti di pùbblicu duminiu o analugamenti lìbbira (talìa $1 pi' majuri dittagghî).\n<strong>Nun mannari matiriali cupertu di drittu d'auturi senza auturizzazzioni!</strong>",
        "longpageerror": "<strong>Erruri: Lu testu ca hai suttamisu è longu {{PLURAL:$1|un kilobyte|$1 kilobyte}}, cchiù' ssai dû màssimu ca è di {{PLURAL:$2|un kilobyte|$2 kilobyte}}.</strong>\nNun si po' sarvari.",
-       "readonlywarning": "<strong>Accura: Lu database è fermu pi manutinzioni, pirciò nun poi sarvari li tò canciamenti nta stu mumentu.</strong>\nLa cosa megghia è fari un copia e ncoḍḍa dû testu nta n'àutru prugramma e sarvàrilu pi quannu lu database torna accissìbbili.\n\nL'amministraturi ca bluccau lu database desi sta spiegazzioni: $1",
+       "readonlywarning": "<strong>Accura: Lu database è fermu pi manutinzioni, pirciò nun poi sarvari li tò canciamenti nta stu mumentu.</strong>\nLa cosa megghia è fari un copia e ncodda dû testu nta n'àutru prugramma e sarvàrilu pi quannu lu database torna accissìbbili.\n\nL'amministraturi ca bluccau lu database desi sta spiegazzioni: $1",
        "protectedpagewarning": "<strong>Accura: Sta pàggina fu' prutetta a' manera chi' sulu l'utenti cu' privileggi d'amministraturi a ponnu canciari.</strong>\nPi' rifirimentu, ccassutta è ripurtata l'ultima vuci dû riggistru:",
        "semiprotectedpagewarning": "<strong>Nota:</strong> Sta pàggina fu' prutetta a' manera chi' sulu l'utenti riggistrati la ponnu canciari.\nPi' rifirimentu, ccassutta è ripurtata l'ultima vuci dû riggistru:",
        "cascadeprotectedwarning": "<strong>Accura:</strong> Sta pàggina havi statu bluccata di manera ca sulu l'utenti cu' privileggi di amministraturi la ponnu canciari, pirchì veni nclusa {{PLURAL:$1|nta siquente pàggina ca havi statu prutiggiuta|ntê siquenti pàggini ca hannu statu prutiggiuti}} a' cascata:",
        "recreate-moveddeleted-warn": "'''Accura: stai pi criari na pàggina chi fu cancillata 'n passatu.'''\n\nAccuràtivi ch'è uppurtunu cuntinuari a canciari sta pàggina.\nL'alencu dî cancillazzioni e spustamenti rilativi veni ripurtatu ccà pi cummudità:",
        "moveddeleted-notice": "Sta pàggina fu scancillata. La lista di li scancillazzioni e spustamenti veni ammustrata di sècutu pi nfurmazzioni.",
        "log-fulllog": "Talìa lu riggìstru cumpletu",
-       "edit-hook-aborted": "Canciamentu annullatu di n'hook.\nNun desi nuḍḍa spiegazzioni.",
+       "edit-hook-aborted": "Canciamentu annullatu di n'hook.\nNun desi nudda spiegazzioni.",
        "edit-gone-missing": "Nun si po' aggiurnari la pàggina.\nPari ca fu' cancillata.",
        "edit-conflict": "Cunflittu d'edizzioni.",
        "edit-no-change": "La to mudìfica fu' gnurata pirchì nun foru appurtati canciamenti ntô testu.",
        "last": "pric",
        "page_first": "prima",
        "page_last": "ùrtima",
-       "histlegend": "Pû cunfrontu tra virsioni: scègghîri li caseḍḍi currispunnenti ê virsioni di cunfruntari e carcari Invio o lu buttuni ô funnu.<br />\nLegenda: <strong>({{int:cur}})</strong> = cunfruntari cu la virsioni currenti, <strong>({{int:last}})</strong> = cunfruntari cu la virsioni avanti d'iḍḍa, <strong>{{int:minoreditletter}}</strong> = canciamentu nicu",
+       "histlegend": "Pû cunfrontu tra virsioni: scègghîri li caseddi currispunnenti ê virsioni di cunfruntari e carcari Invio o lu buttuni ô funnu.<br />\nLegenda: <strong>({{int:cur}})</strong> = cunfruntari cu la virsioni currenti, <strong>({{int:last}})</strong> = cunfruntari cu la virsioni avanti d'idda, <strong>{{int:minoreditletter}}</strong> = canciamentu nicu",
        "history-fieldset-title": "Scurri ntâ crunuluggìa",
-       "history-show-deleted": "Sulu chiḍḍi cancillati",
+       "history-show-deleted": "Sulu chiddi cancillati",
        "histfirst": "i cchiu' vecchî",
        "histlast": "i cchiu' novi",
        "historysize": "({{PLURAL:$1|1 byte|$1 byte}})",
        "mergehistory-merge": "Si pònnu jùnciri li virsioni di [[:$1]] nnicati ccassutta â crunuluggìa di [[:$2]].\nAdòpira la culonna chî buttuni di opzioni pi' jùnciri sulu li virsioni fatti nfina â data e l'ura spicificati.\nGuàrditi ca s'adòpiri culligamenti di navigazzioni la culonna veni azzirata.",
        "mergehistory-go": "Vidi li canciamenti ca ponnu èssiri junciuti",
        "mergehistory-submit": "Junci li virsioni",
-       "mergehistory-empty": "Nuḍḍa virsioni di jùnciri.",
+       "mergehistory-empty": "Nudda virsioni di jùnciri.",
        "mergehistory-success": "$3 {{PLURAL:$3|virsioni di [[:$1]] fu' junciuta|$3 virsioni di [[:$1]] furu junciuti}} â crunuluggìa di [[:$2]].",
        "mergehistory-fail": "Nun fu' pussìbbili jùnciri li crunuluggìi, pi' favuri cuntrolla n'autra vota li paràmitri chi' spicìficunu li pàggini e li dati.",
        "mergehistory-fail-toobig": "Nun fu' pussìbbili jùnciri li crunuluggìi picchì s'avìssuru a' spustari cchiu' ssai virsioni dû limiti chi' è $1.",
        "mergehistory-no-destination": "La pàggina di distinazzioni $1 nun esisti.",
        "mergehistory-invalid-source": "La pàggina d'orìggini havi a' aviri nu tìtulu vàlidu.",
        "mergehistory-invalid-destination": "La pàggina di distinazzioni havi a' aviri nu tìtulu vàlidu.",
-       "mergehistory-autocomment": "Junciuta la crunuluggìa di [[:$1]] a' chiḍḍa di [[:$2]]",
-       "mergehistory-comment": "Junciuta la crunuluggìa di [[:$1]] a' chiḍḍa di [[:$2]]: $3",
+       "mergehistory-autocomment": "Junciuta la crunuluggìa di [[:$1]] a' chidda di [[:$2]]",
+       "mergehistory-comment": "Junciuta la crunuluggìa di [[:$1]] a' chidda di [[:$2]]: $3",
        "mergehistory-same-destination": "Li pàggini d'orìggini e di distinazioni nun ponnu èssiri la stissa",
        "mergehistory-reason": "Mutivu:",
        "mergelog": "Riggìstru dî junciuti",
        "revertmerge": "Annulla la junciuta",
-       "mergelogpagetext": "Appressu veni ammustrata na lista dî junciuti cchiu' ricenti dâ crunuluggìa di na pàggina cu' chiḍḍa di n'autra.",
+       "mergelogpagetext": "Appressu veni ammustrata na lista dî junciuti cchiu' ricenti dâ crunuluggìa di na pàggina cu' chidda di n'autra.",
        "history-title": "Crunuluggìa dî canciamenti di \"$1\"",
        "difference-title": "Cunfruntu tra virsioni di \"$1\"",
        "difference-title-multipage": "Cunfruntu tra dî pàggini \"$1\" e \"$2\"",
        "compareselectedversions": "Cunfronta li virsioni scigghiuti",
        "showhideselectedversions": "Cancia la visibbilità dî virsioni scigghiuti",
        "editundo": "annulla",
-       "diff-empty": "(Nuḍḍa diffirenza)",
+       "diff-empty": "(Nudda diffirenza)",
        "diff-multi-sameuser": "({{PLURAL:$1|Na diffirenza minzana|$1 diffirenzi minzani}} dû stissu utenti nun {{PLURAL:$1|mustrata|mustrati}})",
        "diff-multi-otherusers": "({{PLURAL:$1|Na diffirenza minzana|$1 diffirenzi minzani}} di {{PLURAL:$2|n'autru utenti|autri $2 utenti}} nun {{PLURAL:$1|mustrata|mustrati}})",
        "diff-multi-manyusers": "({{PLURAL:$1|Na diffirenza minzana|$1 diffirenzi minzani}} di cchiu' ssai di {{PLURAL:$2|n'autru utenti|autri $2 utenti}} nun {{PLURAL:$1|mustrata|mustrati}})",
        "searchresults-title": "Risurtati dâ risciduta di \"$1\"",
        "titlematches": "Currispunnenzi ntê tìtuli dî pàggini",
        "textmatches": "Currispunnenzi ntô testu dî pàggini",
-       "notextmatches": "Nuḍḍa currispunnenza ntô testu dî pàggini",
+       "notextmatches": "Nudda currispunnenza ntô testu dî pàggini",
        "prevn": "li pricidenti {{PLURAL:$1|$1}}",
        "nextn": "li pròssimi {{PLURAL:$1|$1}}",
        "prevn-title": "{{PLURAL:$1|Risultatu pricidenti|$1 risultati pricedenti}}",
        "powersearch-ns": "Cerca ntê namespace:",
        "powersearch-togglelabel": "Scègghîli:",
        "powersearch-toggleall": "Tutti",
-       "powersearch-togglenone": "Nuḍḍu",
+       "powersearch-togglenone": "Nuddu",
        "powersearch-remember": "Ricòrditi la scelta pî risciduti futuri",
        "search-external": "Ricerca sterna",
        "searchdisabled": "La circata nterna di {{SITENAME}} hà statu disabbilitata. Nta stu mentri, poi usari la circata supra Google o supra àutri muturi di circata. Accura ca li sò ìnnici dê cuntinuti di {{SITENAME}} ponnu nun èssiri aggiurnati.",
        "mypreferences": "Li me prifirenzi",
        "prefs-edits": "Nùmmiru di canciamenti:",
        "prefsnologintext2": "Hâ' tràsiri pi' canciari i to prifirenzi.",
-       "prefs-skin": "Peḍḍi",
+       "prefs-skin": "Peddi",
        "skin-preview": "Antiprima",
-       "datedefault": "Nuḍḍa prifirenza",
+       "datedefault": "Nudda prifirenza",
        "prefs-labs": "Funziunalità dî labburatorî",
        "prefs-user-pages": "Pàggini di l'utenti",
        "prefs-personal": "Prufilu di l'utenti",
        "timezoneuseserverdefault": "Adòpira l'ura pridifinuta dâ wiki ($1)",
        "timezoneuseoffset": "Àutru (spicificari diffirenza)",
        "servertime": "Ura dû server:",
-       "guesstimezone": "Pigghia chiḍḍa dû to browser",
+       "guesstimezone": "Pigghia chidda dû to browser",
        "timezoneregion-africa": "Àfrica",
        "timezoneregion-america": "Amèrica",
        "timezoneregion-antarctica": "Antàrtidi",
        "prefs-files": "File",
        "prefs-custom-css": "CSS pirsunalizzatu",
        "prefs-custom-js": "JavaScript pirsunalizzatu",
-       "prefs-common-css-js": "CSS/JavaScript cunnivisu tra tutti li peḍḍi:",
-       "prefs-reset-intro": "Poi adupirari sta pàggina pi' azzirari li to prifirenzi a' chiḍḍi pridifinuti dû situ.\nSt'opirazzioni nun si po' annullari doppu ch'è fatta.",
+       "prefs-common-css-js": "CSS/JavaScript cunnivisu tra tutti li peddi:",
+       "prefs-reset-intro": "Poi adupirari sta pàggina pi' azzirari li to prifirenzi a' chiddi pridifinuti dû situ.\nSt'opirazzioni nun si po' annullari doppu ch'è fatta.",
        "prefs-emailconfirm-label": "Cunvàlida dâ posta elittrònica:",
        "youremail": "Nnirizzu di posta elittrònica:",
        "username": "{{GENDER:$1|Nomu utenti}}:",
        "prefs-dateformat": "Furmatu dâ data",
        "prefs-timeoffset": "Diffirenza d'urariu",
        "prefs-advancedediting": "Opzioni ginirali",
-       "prefs-editor": "Caseḍḍa di canciamentu",
+       "prefs-editor": "Casedda di canciamentu",
        "prefs-preview": "Antiprima",
        "prefs-advancedrc": "Opzioni avanzati",
        "prefs-advancedrendering": "Opzioni avanzati",
        "saveusergroups": "Sarva li gruppi di l'utenti",
        "userrights-groupsmember": "Membru di:",
        "userrights-groupsmember-auto": "Membru implìcitu di:",
-       "userrights-groups-help": "Poi canciari li gruppi unni è assignatu l'utenti:\n* Na caseḍḍa scigghiuta voli diri chi' l'utenti fa' parti dû gruppu.\n* Na caseḍḍa nun scigghiuta voli diri chi' l'utenti nun fa' parti dû gruppu.\n* Lu sìmmulu * voli diri chi' nun si po' cchiu' luvari l'utenti dûn gruppu na vota chi' fu' agghiunciutu, o vici versa.",
+       "userrights-groups-help": "Poi canciari li gruppi unni è assignatu l'utenti:\n* Na casedda scigghiuta voli diri chi' l'utenti fa' parti dû gruppu.\n* Na casedda nun scigghiuta voli diri chi' l'utenti nun fa' parti dû gruppu.\n* Lu sìmmulu * voli diri chi' nun si po' cchiu' luvari l'utenti dûn gruppu na vota chi' fu' agghiunciutu, o vici versa.",
        "userrights-reason": "Mutivu:",
        "userrights-no-interwiki": "Nun hai lu pirmissu di canciari li dritti di l'utenti nta l'autri wiki.",
        "userrights-nodatabase": "La basi di dati $1 nun esisti o nun è lucali.",
        "right-hideuser": "Bluccari nu nomu utenti, ammucciannulu ô pùbblicu",
        "right-ipblock-exempt": "Sautari li blocchi di IP, autumàtici e di ntirvalli di IP",
        "right-proxyunbannable": "Sautari li blocchi autumàtici dî proxy",
-       "right-unblockself": "Sbluccàrisi iḍḍu stissu",
-       "right-protect": "Canciari li liveḍḍi di prutizzioni e mudificari pàggini prutetti a' cascata",
+       "right-unblockself": "Sbluccàrisi iddu stissu",
+       "right-protect": "Canciari li liveddi di prutizzioni e mudificari pàggini prutetti a' cascata",
        "right-editprotected": "Canciari pàggini cu' prutizzioni \"{{int:protect-level-sysop}}\"",
        "right-editsemiprotected": "Canciari pàggini cu' prutizzioni \"{{int:protect-level-autoconfirmed}}\"",
        "right-editcontentmodel": "Canciari u mudellu di cuntinutu di na pàggina",
        "right-patrol": "Marcari li canciamenti di l'autri utenti comu battugghiati",
        "right-autopatrol": "Marcari autumaticamenti li propî canciamenti comu battugghiati",
        "right-patrolmarks": "Vìdiri li marcaturi di battugghia nta l'ùrtimi canciamenti",
-       "right-unwatchedpages": "Vìdiri na lista dî pàggini chi' nuḍḍu talìa",
+       "right-unwatchedpages": "Vìdiri na lista dî pàggini chi' nuddu talìa",
        "right-mergehistory": "Jùnciri la crunuluggìa dî pàggini",
        "right-userrights": "Canciari tutti li dritti di l'utenti",
        "right-userrights-interwiki": "Canciari li dritti di l'utenti di autri wiki",
        "right-siteadmin": "Bluccari e sbluccari la basi di dati",
-       "right-override-export-depth": "Espurtari pàggini cu li pàggini culligati nfina ô quintu liveḍḍu",
+       "right-override-export-depth": "Espurtari pàggini cu li pàggini culligati nfina ô quintu liveddu",
        "right-sendemail": "Mannari missaggi di posta elittrònica a' l'autri utenti",
        "right-passwordreset": "Talïari li missaggi di posta elittrònica d'azziramentu dî password",
        "newuserlogpage": "Riggistru di l'utenti novi",
        "action-suppressrevision": "rivìdiri e ripristinari sta virsioni ammucciata",
        "action-suppressionlog": "vìdiri stu riggìstru privatu",
        "action-block": "bluccari st'utenti pi' nun fàricci fari canciamenti",
-       "action-protect": "canciari li liveḍḍa di prutizzioni di sta pàggina",
+       "action-protect": "canciari li livedda di prutizzioni di sta pàggina",
        "action-rollback": "canciari lestu n'arreri li mudìfichi di l'ùltimu utenti chi' canciau na certa pàggina",
        "action-import": "mpurtari pàggini di n'àutra wiki",
        "action-importupload": "mpurtari pàggini di nu carricamentu di file",
        "action-patrol": "marcari li canciamenti di l'autri utenti comu battugghiati",
        "action-autopatrol": "marcari li tò canci comu battugghiati",
-       "action-unwatchedpages": "vìdiri la lista dî pàggini chi' nuḍḍu talìa",
+       "action-unwatchedpages": "vìdiri la lista dî pàggini chi' nuddu talìa",
        "action-mergehistory": "jùnciri la crunuluggìa di sta pàggina",
        "action-userrights": "canciari tutti li dritti di l'utenti",
        "action-userrights-interwiki": "canciari li dritti di l'utenti supra a autri wiki",
        "recentchanges": "Ùrtimi canciamenti",
        "recentchanges-legend": "Opzioni pi' l'ùrtimi canciamenti",
        "recentchanges-summary": "Sta pàggina prisenta li canciamenti cchiu' ricenti ê cuntinuti dâ wiki.",
-       "recentchanges-noresult": "Nuḍḍu canciamentu ntô pirìudu spicificatu currispunni a' sti criteria.",
+       "recentchanges-noresult": "Nuddu canciamentu ntô pirìudu spicificatu currispunni a' sti criteria.",
        "recentchanges-feed-description": "Stu feed prisenta li canciamenti cchiu' ricenti ê cuntinuti dâ wiki.",
        "recentchanges-label-newpage": "Stu canciamentu crïau na pàggina nova",
        "recentchanges-label-minor": "Chistu è nu canciamentu nicu",
        "recentchangeslinked-title": "Canciamenti culligati a \"$1\"",
        "recentchangeslinked-summary": "Chista pàggina spiciali ammustra li canciamenti cchiù ricenti ê pàggini culligati a chidda spicificata. Li pàggini taliati ni la tou [[Special:Watchlist|lista taliata]] sunu evidenziati 'n '''grassettu'''.",
        "recentchangeslinked-page": "Nomu dâ pàggina:",
-       "recentchangeslinked-to": "Ammustra sulu li canciamenti ê pàggini culligati a' chiḍḍa spicificata",
+       "recentchangeslinked-to": "Ammustra sulu li canciamenti ê pàggini culligati a' chidda spicificata",
        "upload": "Càrrica nu file",
        "uploadbtn": "Càrrica",
        "reuploaddesc": "Annulla lu carricamentu e torna a lu mòdulu dî carricamenti",
        "upload_directory_missing": "La cartella dî carricamenti ($1) nun esisti lu server web nun riniscìu a' crïàrila.",
        "upload_directory_read_only": "La cartella dî carricamenti ($1) nun è scrivìbbili dû server web.",
        "uploaderror": "Erruri ntô carricamentu",
-       "upload-recreate-warning": "<strong>Accura: Nu file cu' ḍḍu nomu fu' cancillatu o spustatu.</strong>\n\nPi' cummudità ccassutta cci su' li riggistra dî cancillazzioni e dî spustamenti di sta pàggina:",
+       "upload-recreate-warning": "<strong>Accura: Nu file cu' ddu nomu fu' cancillatu o spustatu.</strong>\n\nPi' cummudità ccassutta cci su' li riggistra dî cancillazzioni e dî spustamenti di sta pàggina:",
        "uploadtext": "Usa lu mòdulu ccà sutta pi carricari file novi. Pi vìdiri o circari li file già carricati, talìa lu [[Special:FileList|log dî file carricati]]. Carricamenti di file e di virsioni novi di file sunnu riggistrati ntô [[Special:Log/upload|log di l'upload]], li cancillazzioni di file sunnu\nriggistrati [[Special:Log/delete|ccà]].\n\nPi nziriri nu file nta na pàggina, fai nu lijami accussì:\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.jpg]]</nowiki></code>''' p'usari la virsioni ntera dû file\n* '''<code><nowiki>[[</nowiki>{{ns:file}}<nowiki>:File.png|200px|thumb|left|testu altirnativu]]</nowiki></code>''' p'usari na virsioni làrica 200 pixel nziruta nta nu box, alliniata a manu manca e cu 'testu altirnativu' comu didascalìa\n* '''<code><nowiki>[[</nowiki>{{ns:media}}<nowiki>:File.ogg]]</nowiki></code>''' pi culligari direttamenti a lu file senza vidìrilu.",
        "upload-permitted": "Tipi di file cunsintuti: $1.",
        "upload-preferred": "Tipi di file cunsigghiati: $1.",
        "emptyfile": "Lu file chi' carricasti pari vacanti.\nChistu putissi èssiri pruvucatu di nu sbagghiu ntô nomu dû file.\nCuntrolla ca pi' davera voi carricari stu file.",
        "windows-nonascii-filename": "Sta wiki nun supporta i nomi di file cu' caràttiri spiciali.",
        "fileexists": "Nu file cu' stu nomu già esisti, pi' favuri cuntrolla <strong>[[:$1]]</strong> si' nun si' {{GENDER:|sicuru|sicura}} ch'u voi canciari.\n[[$1|thumb]]",
-       "filepageexists": "La pàggina dâ discrizzioni di stu file fu' ggià crïata ô nnirizzu <strong>[[:$1]]</strong>, ma pi' com'ora nun c'è nuḍḍu file cu' stu nomu.\nU riassuntu chi' immetti nun cumpariravi ntâ pàggina dâ discrizzioni.\nPi' fàrilu cumpàriri, avirrai a' mudificari a' manu ḍḍa pàggina.\n[[$1|thumb]]",
+       "filepageexists": "La pàggina dâ discrizzioni di stu file fu' ggià crïata ô nnirizzu <strong>[[:$1]]</strong>, ma pi' com'ora nun c'è nuddu file cu' stu nomu.\nU riassuntu chi' immetti nun cumpariravi ntâ pàggina dâ discrizzioni.\nPi' fàrilu cumpàriri, avirrai a' mudificari a' manu dda pàggina.\n[[$1|thumb]]",
        "fileexists-extension": "Nu file cûn nomu simili già esisti: [[$2|thumb]]\n* Nomu dû file carricannu: <strong>[[:$1]]</strong>\n* Nomu dû file esistenti: <strong>[[:$2]]</strong>\nForsi voi scègghîri un nomu cchiù' distintivu?",
        "fileexists-thumbnail-yes": "Lu file carricato sembra èssiri lu risurtatu di n'antiprima ''(thumbnail)''. [[$1|thumb]]\nVirificari, pi cunfruntu, lu file <strong>[[:$1]]</strong>.\nSiduu si tratta dâ stissa mmagini, nte dimenzioni urigginali, nun è nicissariu carricara àutri antiprimi.",
        "file-thumbnail-no": "Lu nomu dô file accumenza cu <strong>$1</strong>.\nPari quinni èssiri lu risurtatu di n'antiprima ''(thumbnail)''.\nSiddu si disponi dâ mmàggini ntâ risuluzzioni urigginali, si prega di carricàrila. 'N casu cuntrariu, si prega di canciari lu nomu dô file.",
        "zip-bad": "Lu file è nu file ZIP chi' è ruïnatu o è illiggìbbili pi' quarchi' n'autru mutivu.\nNun si po' cuntrullari bona la so sicurizza.",
        "zip-unsupported": "Lu file è nu file ZIP chi' cunteni carattirìstichi ZIP chi' nun su' suppurtati dâ MediaWiki.\nNun si po' cuntrullari bona la so sicurizza.",
        "uploadstash": "Ammucciàgghia dî carricamenti",
-       "uploadstash-summary": "Sta pàggina duna accessu ê file chi' furu carricati, o si stannu carricannu, però ancora nun hannu statu pubblicati ntâ wiki. Sti file nun su' visìbbili a' nuḍḍu sparti di cu li carricau.",
+       "uploadstash-summary": "Sta pàggina duna accessu ê file chi' furu carricati, o si stannu carricannu, però ancora nun hannu statu pubblicati ntâ wiki. Sti file nun su' visìbbili a' nuddu sparti di cu li carricau.",
        "uploadstash-clear": "Cancella li file nta l'ammucciagghia",
-       "uploadstash-nofiles": "Nun hai nuḍḍu file nta l'ammucciagghia.",
+       "uploadstash-nofiles": "Nun hai nuddu file nta l'ammucciagghia.",
        "uploadstash-badtoken": "St'azzioni nun riniscìu, forsi picchì li to cridinziali di mudìfica scaderu. Prova n'autra vota.",
        "uploadstash-errclear": "La cancillazzioni dî file nun riniscìu.",
        "uploadstash-refresh": "Aggiorna la lista dî file",
        "upload-curl-error28-text": "Lu situ rimotu cci stesi troppu tempu a' rispùnniri.\nPi' favuri cuntrolla ca lu situ funziona, aspetta un pocu e ppoi prova n'autra vota.\nPoi cunsiddirari di pruvari ntôn mumentu quannu c'è cchiu' picca tràficu.",
        "license": "Licenza d'usu:",
        "license-header": "Licenza",
-       "nolicense": "Nuḍḍa spicificata",
+       "nolicense": "Nudda spicificata",
        "licenses-edit": "Cancia l'opzioni dâ licenza",
        "license-nopreview": "(Antiprima nun dispunìbbili)",
        "upload_source_url": "(lu file chi' scigghîsti di n'URL vàlida e pubblicamenti accissìbbili)",
        "filehist-datetime": "Data/Ura",
        "filehist-thumb": "Miniatura",
        "filehist-thumbtext": "Miniatura di la virsioni dû $1",
-       "filehist-nothumb": "Nuḍḍa miniatura",
+       "filehist-nothumb": "Nudda miniatura",
        "filehist-user": "Utenti",
        "filehist-dimensions": "Diminsioni",
        "filehist-filesize": "Dimensioni dû file",
        "imagelinks": "Usu dû file",
        "linkstoimage": "{{PLURAL:$1|La pàggina siquenti richiàma|Li $1 pàggini siquenti richiàmanu}} stu file:",
        "linkstoimage-more": "Cci su' cchiu' ssai di $1 {{PLURAL:$1|pàggina|pàggini}} ca richiàmunu stu file.\nLa lista ccassutta ammustra sulu {{PLURAL:$1|la prima pàggina|li primi $1 pàggini}}.\nSi po' puru a' vìdiri [[Special:WhatLinksHere/$2|na lista cumpleta]].",
-       "nolinkstoimage": "Nuḍḍa pàggina richiama stu file.",
+       "nolinkstoimage": "Nudda pàggina richiama stu file.",
        "morelinkstoimage": "Ammustra [[Special:WhatLinksHere/$1|autri culligamenti]] a' stu file.",
        "linkstoimage-redirect": "$1 (rimannu ô file) $2",
        "duplicatesoffile": "{{PLURAL:$1|Stu|Sti $1}} file {{PLURAL:$1|è nu dupppiuni|sunnu duppiuni}} di st'autru file ([[Special:FileDuplicateSearch/$2|cchiù dittagli]]):",
        "sharedupload": "Stu file veni di $1 e purrìa èssiri adupiratu di autri pruggetti.",
        "sharedupload-desc-there": "Stu file veni di $1 e purrìa èssiri adupiratu di autri pruggetti.\nTalìari la so [$2 pàggina di discrizzioni] pi' autri nfurmazzioni.",
        "sharedupload-desc-here": "Stu file veni di $1 e purrìa èssiri adupiratu di autri pruggetti.\nAppressu veni ammustrata la discrizioni prisenti ntâ so [$2 pàggina di discrizzioni].",
-       "sharedupload-desc-edit": "Stu file veni di $1 e purrìa èssiri adupiratu di autri pruggetti.\nForsi ti cunveni canciari la so discrizzioni ntâ so [$2 pàggina di discrizzioni] ḍḍa.",
-       "sharedupload-desc-create": "Stu file veni di $1 e purrìa èssiri adupiratu di autri pruggetti.\nForsi ti cunveni canciari a so discrizzioni ntâ so [$2 pàggina di discrizzioni] ḍḍa.",
-       "filepage-nofile": "Nun esisti nuḍḍu file cu' stu nomu.",
-       "filepage-nofile-link": "Nun esisti nuḍḍu file cu' stu nomu, però [$1 lu poi carricari].",
+       "sharedupload-desc-edit": "Stu file veni di $1 e purrìa èssiri adupiratu di autri pruggetti.\nForsi ti cunveni canciari la so discrizzioni ntâ so [$2 pàggina di discrizzioni] dda.",
+       "sharedupload-desc-create": "Stu file veni di $1 e purrìa èssiri adupiratu di autri pruggetti.\nForsi ti cunveni canciari a so discrizzioni ntâ so [$2 pàggina di discrizzioni] dda.",
+       "filepage-nofile": "Nun esisti nuddu file cu' stu nomu.",
+       "filepage-nofile-link": "Nun esisti nuddu file cu' stu nomu, però [$1 lu poi carricari].",
        "uploadnewversion-linktext": "Càrrica na virsioni nova di stu file",
        "shared-repo-from": "di $1",
        "shared-repo": "nu dipòsitu cunnivisu",
        "filedelete-success": "Lu file <strong>$1</strong> fu' cancillatu.",
        "filedelete-success-old": "La virsioni dû file <strong>[[Media:$1|$1]]</strong> dû $2 ê $3 fu' cancillata.",
        "filedelete-nofile": "<strong>$1</strong> nun esisti.",
-       "filedelete-nofile-old": "Nun cc'è archiviata nuḍḍa virsioni di <strong>$1</strong> chi' havi l'attribbuta spicificati.",
+       "filedelete-nofile-old": "Nun cc'è archiviata nudda virsioni di <strong>$1</strong> chi' havi l'attribbuta spicificati.",
        "filedelete-otherreason": "Autru o ultiriuri mutivu:",
        "filedelete-reason-otherlist": "Autru mutivu",
        "filedelete-reason-dropdown": "*Mutivi cchiu' cumuni pâ cancillazzioni\n** Viulazzioni dû drittu d'auturi\n** File duppiuni",
        "listduplicatedfiles-summary": "Chista è na lista dî file unni la virsioni cchiu' nova è nu duppiuni dâ virsioni cchiu' nova di quarchi' autru file. Sulu li file lucali su' pigghiati a' cunsiddirazzioni.",
        "listduplicatedfiles-entry": "[[:File:$1|$1]] havi [[$3|{{PLURAL:$2|nu duppiuni|$2 duppiuna}}]].",
        "unusedtemplates": "Template nun usati",
-       "unusedtemplatestext": "Sta pàggina elenca tutti li pàggini nto namespace {{ns:template}} ca nun sunnu nclusi nta nuḍḍa autra pàggina.\nPrima di cancillàrili è megghiu cuntrullari ca nun hannu autri culligamenti ca cci tràsunu.",
+       "unusedtemplatestext": "Sta pàggina elenca tutti li pàggini nto namespace {{ns:template}} ca nun sunnu nclusi nta nudda autra pàggina.\nPrima di cancillàrili è megghiu cuntrullari ca nun hannu autri culligamenti ca cci tràsunu.",
        "unusedtemplateswlh": "autri culligamenti",
        "randompage": "Na pàggina a' muzzu",
        "randompage-nopages": "Nun cci su' pàggini {{PLURAL:$2|nta stu namespace|nta sti namespace}}: $1.",
        "randomincategory-category": "Catigurìa:",
        "randomincategory-legend": "Pàggina a' muzzu nta na catigurìa",
        "randomredirect": "Nu rimannu a' muzzu",
-       "randomredirect-nopages": "Nun cc'è nuḍḍu rimannu ntô namespace \"$1\".",
+       "randomredirect-nopages": "Nun cc'è nuddu rimannu ntô namespace \"$1\".",
        "statistics": "Statìstichi",
        "statistics-header-pages": "Statìstichi dî pàggini",
        "statistics-header-edits": "Statìstichi dî canciamenti",
        "statistics-header-hooks": "Autri statìstichi",
        "statistics-articles": "Pàggini di cuntinutu",
        "statistics-pages": "Pàggini",
-       "statistics-pages-desc": "Tutti li pàggini dâ wiki, cu' puru chiḍḍi di discussioni, li rimanni, etc.",
+       "statistics-pages-desc": "Tutti li pàggini dâ wiki, cu' puru chiddi di discussioni, li rimanni, etc.",
        "statistics-files": "File carricati",
        "statistics-edits": "Pàggini canciati di quannu {{SITENAME}} fu' armatu",
        "statistics-edits-average": "Media dî canciamenti pi' pàggina",
        "protectedpages-summary": "Sta pàggina elenca li pàggini già esistenti chi' comu ad ora su' prutetti. Pi' na lista dî tìtuli prutetti, chî quali vèni prüibbutu crïari pàggini novi, talìa [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-cascade": "Sulu prutizzioni a' cascata",
        "protectedpages-noredirect": "Ammuccia li rimanni",
-       "protectedpagesempty": "Pi' com'ora nun cc'è nuḍḍa pàggina prutetta cu' sti paràmitri.",
+       "protectedpagesempty": "Pi' com'ora nun cc'è nudda pàggina prutetta cu' sti paràmitri.",
        "protectedpages-timestamp": "Data e ura",
        "protectedpages-page": "Pàggina",
        "protectedpages-expiry": "Scadenza",
        "protectedpages-unknown-performer": "Utenti scanusciutu",
        "protectedtitles": "Tìtuli prutetti",
        "protectedtitles-summary": "Sta pàggina elenca li tìtuli prutetti, chî quali vèni prüibbutu crïari pàggini novi. Pi' na lista dî pàggini già esistenti chi' su' prutetti, talìa [[{{#special:ProtectedPages}}|{{int:protectedpages}}]].",
-       "protectedtitlesempty": "Pi' com'ora nun cc'è nuḍḍu tìtulu prutettu cu' sti paràmitri.",
+       "protectedtitlesempty": "Pi' com'ora nun cc'è nuddu tìtulu prutettu cu' sti paràmitri.",
        "listusers": "Lista di l'utenti",
        "listusers-editsonly": "Ammustra sulu l'utenti ca hannu cuntribbuti",
        "listusers-creationsort": "Òrdina pi' data di crïazzioni",
        "ancientpages": "Pàggini cchiu' vecchî",
        "move": "Sposta",
        "movethispage": "Sposta sta pàggina",
-       "unusedimagestext": "Li file ccassutta esìstunu però nun sunnu ncurpurati nta nuḍḍa pàggina.\nAccura: autri siti web ponnu aviri culligamenti ôn file pi' menzu di URL diretti; li file addupirati a' sta manera putìssiru èssiri elincati ccassutta puru si' si nni fa' usu.",
-       "unusedcategoriestext": "Li siguenti pàggini di catigurìi esìstunu, però nuḍḍa autra pàggina o catigurìa nni fa' usu.",
-       "notargettitle": "Nuḍḍa distinazzioni",
+       "unusedimagestext": "Li file ccassutta esìstunu però nun sunnu ncurpurati nta nudda pàggina.\nAccura: autri siti web ponnu aviri culligamenti ôn file pi' menzu di URL diretti; li file addupirati a' sta manera putìssiru èssiri elincati ccassutta puru si' si nni fa' usu.",
+       "unusedcategoriestext": "Li siguenti pàggini di catigurìi esìstunu, però nudda autra pàggina o catigurìa nni fa' usu.",
+       "notargettitle": "Nudda distinazzioni",
        "notargettext": "Nun spicificasti na pàggina o puru n'utenti comu distinazzioni di st'opirazzioni.",
        "nopagetitle": "La pàggina di distinazzioni nun esisti",
        "nopagetext": "La pàggina ca spicificasti comu distinazzioni nun esisti.",
        "log": "Riggistra",
        "all-logs-page": "Tutti li riggistra pubblici",
        "alllogstext": "Prisintazzioni cumminata di tutti li riggistra dispunìbbili di {{SITENAME}}.\nPoi ristrìnciri la visuali silizziunannu nu tipu di riggistru, l'utenti ca fici l'azzioni (cuntunu majusculi e minusculi), o la pàggina ntirissata (cuntunu majusculi e minusculi puru).",
-       "logempty": "Nuḍḍa vuci currispunnenti ntô riggistru.",
+       "logempty": "Nudda vuci currispunnenti ntô riggistru.",
        "log-title-wildcard": "Attrova tituli chi ncignanu cu",
        "showhideselectedlogentries": "Cancia la visibbilità dî vuci di riggistru scigghiuti",
        "allpages": "Tutti li pàggini",
        "linksearch-pat": "Esprissioni di risciduta:",
        "linksearch-ns": "Namespace:",
        "linksearch-ok": "Arriscedi",
-       "linksearch-text": "Si ponnu adupirari li caràttiri matta, ad esempiu \"*.wikipedia.org\".\nCci voli almenu nu duminiu di primu liveḍḍu, ad esempiu \"*.org\".<br />\n{{PLURAL:$2|Protucollu suppurtatu|Protucolli suppurtati}}: <code>$1</code> (è pridifinutu http:// si' nun si nni spicìfica)",
+       "linksearch-text": "Si ponnu adupirari li caràttiri matta, ad esempiu \"*.wikipedia.org\".\nCci voli almenu nu duminiu di primu liveddu, ad esempiu \"*.org\".<br />\n{{PLURAL:$2|Protucollu suppurtatu|Protucolli suppurtati}}: <code>$1</code> (è pridifinutu http:// si' nun si nni spicìfica)",
        "linksearch-line": "$1 è culligatu dâ pàggina $2",
        "linksearch-error": "Li caràttiri matta ponnu appariri sulu ô principiu dû nomu host.",
        "listusersfrom": "Ammustra l'utenti a' pàrtiri di:",
        "listusers-submit": "Ammustra",
-       "listusers-noresult": "Nuḍḍu utenti attruvatu.",
+       "listusers-noresult": "Nuddu utenti attruvatu.",
        "listusers-blocked": "(bluccatu)",
        "activeusers": "Lista di l'utenti attivi",
        "activeusers-intro": "Chista è na lista di l'utenti chi' fìciru na quarchi' attività {{PLURAL:$1|nta l'ùltimu jornu|nta l'ùltimi $1 jorna}}.",
        "activeusers-from": "Ammustra l'utenti a' pàrtiri di:",
        "activeusers-hidebots": "Ammuccia li bot",
        "activeusers-hidesysops": "Ammuccia l'amministratura",
-       "activeusers-noresult": "Nuḍḍu utenti truvatu.",
+       "activeusers-noresult": "Nuddu utenti truvatu.",
        "listgrouprights": "Dritti di gruppa d'utenti",
        "listgrouprights-summary": "Ccà sutta sunnu elincati li gruppa d'utenti difinuti nta sta wiki, cu li so dritti d'accessu.\nCci ponnu èssiri [[{{MediaWiki:Listgrouprights-helppage}}|autri nfurmazzioni]] a' prupòsitu di ciascunu drittu.",
        "listgrouprights-key": "Legenda:\n* <span class=\"listgrouprights-granted\">Drittu cuncidutu</span>\n* <span class=\"listgrouprights-revoked\">Drittu rivucatu</span>",
        "expensive-parserfunction-category-desc": "Sta pàggina adòpira troppi funzioni di l'analizzaturi sintatticu custusi (comu <code>#ifexist</code>). Talìa [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgExpensiveParserFunctionLimit Manual:$wgExpensiveParserFunctionLimit].",
        "broken-file-category-desc": "Sta pàggina cunteni nu culligamentu a' file ruttu (nu culligamentu a' nu file chi' nun esisti).",
        "hidden-category-category-desc": "Sta catigurìa cunteni <code><nowiki>__HIDDENCAT__</nowiki></code> ntô corpu dâ so pàggina, cosa chi' nâ fa' spuntari supra ê pàggini ntô riquatru dî culligamenti ê catigurìi comu mpustazzioni pridifinuta.",
-       "trackingcategories-nodesc": "Nuḍḍa discrizzioni dispunìbbili.",
+       "trackingcategories-nodesc": "Nudda discrizzioni dispunìbbili.",
        "trackingcategories-disabled": "Sta catigurìa è disattivata",
-       "mailnologin": "Nuḍḍu nnirizzu pi' mannari",
+       "mailnologin": "Nuddu nnirizzu pi' mannari",
        "mailnologintext": "Hâ' [[Special:UserLogin|tràsiri]] e aviri riggistratu nu nnirizzu di posta elittrònica vàlidu ntê to [[Special:Preferences|prifirenzi]] pi' putiri mannari posta elittrònica a' l'àutri utenti.",
        "emailuser": "Manna nu missaggiu di posta elittrònica a' st'utenti",
        "emailuser-title-target": "Mannari nu missaggiu di posta elittrònica a' {{GENDER:$1|stu utenti|sta utenti}}",
        "defemailsubject": "Missaggiu di {{SITENAME}} di l'utenti \"$1\"",
        "usermaildisabled": "Missaggi di posta elittrònica a' l'utenti disattivati",
        "usermaildisabledtext": "Nta sta wiki nun si ponnu mannari missaggi di posta elittrònica a' l'autri utenti",
-       "noemailtitle": "Nuḍḍu nnirizzu di posta elittrònica",
+       "noemailtitle": "Nuddu nnirizzu di posta elittrònica",
        "noemailtext": "St'utenti nun havi spicificatu nu nnirizzu di posta elittrònica vàlidu.",
        "nowikiemailtext": "St'utenti scigghìu di nun ricèviri missaggi di posta elittrònica di l'autri utenti.",
        "emailnotarget": "Spicificatu comu distinatariu un nomu utenti nun esistenti o nun vàlidu.",
        "watchlist": "Lista talïata",
        "mywatchlist": "La me lista talïata",
        "watchlistfor2": "Di $1, $2",
-       "nowatchlist": "Nun hai nuḍḍa vuci ntâ to lista talïata.",
+       "nowatchlist": "Nun hai nudda vuci ntâ to lista talïata.",
        "watchlistanontext": "Pi' vìdiri e canciari li vuci dâ to lista talïata hâ' tràsiri.",
        "watchnologin": "Nun hai trasutu",
        "addwatch": "Agghiunci â lista talïata",
        "enotif_lastvisited": "Cunzurta $1 pi vìdiri tutti li canciamenti dâ tò ùrtima vìsita.",
        "enotif_lastdiff": "Vidi $1 pi' talïari lu canciamentu.",
        "enotif_anon_editor": "utenti anonimu $1",
-       "enotif_body": "Gintili $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nRiassuntu fattu di l'auturi: $PAGESUMMARY $PAGEMINOREDIT\n\nPi' cuntattari l'auturi:\nmail: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nNun ti mannamu autri nutìfichi 'n casu di ultiriuri attività a' menu ca nun vìsiti ḍḍa pàggina mentri chi' si' trasutu. Poi puru mpustari dâ to lista talïata l'avvisu di nutìfica pi' tutti li pàggini chi' cunteni.\n\nLu sistema di nutìfica di {{SITENAME}}, ô to sirvizziu\n\n--\nPi' canciari li to mpustazzioni di nutìfica via e-mail, vìsita\n{{canonicalurl:{{#special:Preferences}}}}\n\nPi' canciari li mpustazzioni dâ to lista talïata, vìsita\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nPi' livari sta pàggina dâ to lista talïata, vìsita\n$UNWATCHURL\n\nPi' lassari cummenti e arricèviri ultiriuri assistenza:\n$HELPPAGE",
+       "enotif_body": "Gintili $WATCHINGUSERNAME,\n\n$PAGEINTRO $NEWPAGE\n\nRiassuntu fattu di l'auturi: $PAGESUMMARY $PAGEMINOREDIT\n\nPi' cuntattari l'auturi:\nmail: $PAGEEDITOR_EMAIL\nwiki: $PAGEEDITOR_WIKI\n\nNun ti mannamu autri nutìfichi 'n casu di ultiriuri attività a' menu ca nun vìsiti dda pàggina mentri chi' si' trasutu. Poi puru mpustari dâ to lista talïata l'avvisu di nutìfica pi' tutti li pàggini chi' cunteni.\n\nLu sistema di nutìfica di {{SITENAME}}, ô to sirvizziu\n\n--\nPi' canciari li to mpustazzioni di nutìfica via e-mail, vìsita\n{{canonicalurl:{{#special:Preferences}}}}\n\nPi' canciari li mpustazzioni dâ to lista talïata, vìsita\n{{canonicalurl:{{#special:EditWatchlist}}}}\n\nPi' livari sta pàggina dâ to lista talïata, vìsita\n$UNWATCHURL\n\nPi' lassari cummenti e arricèviri ultiriuri assistenza:\n$HELPPAGE",
        "created": "criatu",
        "changed": "canciatu",
        "deletepage": "Cancella la pàggina",
        "protectlogpage": "Riggistru dî prutizzioni",
        "protectlogtext": "Ccassutta c'è nu riggistru dî canciamenti â prutizzioni dî pàggini.\nVidi la [[Special:ProtectedPages|lista dî pàggini prutetti]] pi' canùsciri tutti i prutizzioni di pàggini chi' su' in viguri.",
        "protectedarticle": "prutiggìu [[$1]]",
-       "modifiedarticleprotection": "canciau lu liveḍḍu di prutizzioni di \"[[$1]]\"",
+       "modifiedarticleprotection": "canciau lu liveddu di prutizzioni di \"[[$1]]\"",
        "unprotectedarticle": "livau la prutizzioni di \"[[$1]]\"",
        "movedarticleprotection": "spustau la prutizzioni di \"[[$2]]\" a' \"[[$1]]\"",
-       "protect-title": "Canciamentu dû liveḍḍu di prutizzioni di \"$1\"",
-       "protect-title-notallowed": "Vista dû liveḍḍu di prutizzioni di \"$1\"",
+       "protect-title": "Canciamentu dû liveddu di prutizzioni di \"$1\"",
+       "protect-title-notallowed": "Vista dû liveddu di prutizzioni di \"$1\"",
        "prot_1movedto2": "spustau [[$1]] nta [[$2]]",
        "protect-badnamespace-title": "Namespace unni nun si po' prutèggiri",
        "protect-badnamespace-text": "Li pàggini nta stu namespace nun si ponnu prutèggiri.",
-       "protect-norestrictiontypes-text": "Sta pàggina nun si po' prutèggiri picchì nun cc'è nuḍḍa sorta di ristrizzioni dispunìbbili.",
+       "protect-norestrictiontypes-text": "Sta pàggina nun si po' prutèggiri picchì nun cc'è nudda sorta di ristrizzioni dispunìbbili.",
        "protect-norestrictiontypes-title": "Pàggina chi' nun si po' prutèggiri",
        "protect-legend": "Cunfirma la prutizzioni",
        "protectcomment": "Mutivu:",
        "protect_expiry_invalid": "L'ura di scadenza nun è vàlida.",
        "protect_expiry_old": "L'ura di scadenza già havi passatu.",
        "protect-unchain-permissions": "Sblocca autri opzioni di prutizzioni",
-       "protect-text": "Cca poi a' vìdiri e canciari lu liveḍḍu di prutizzioni dâ pàggina <strong>$1</strong>.",
-       "protect-locked-blocked": "Nun si ponnu canciari li liveḍḍi di prutizzioni quannu unu è bluccatu.\nCca cci su' li mpustazzioni attuali dâ pàggina <strong>$1</strong>:",
-       "protect-locked-dblock": "Nun si ponnu canciari li liveḍḍi di prutizzioni picchì cc'è attivatu un bloccu dâ basi di dati.\nCca cci su' li mpustazzioni attuali dâ pàggina <strong>$1</strong>:",
-       "protect-locked-access": "Lu to cuntu nun havi lu pirmissu di canciari li liveḍḍi di prutizzioni.\nCca cci su' li mpustazzioni attuali dâ pàggina <strong>$1</strong>:",
-       "protect-cascadeon": "Com'ad ora sta pàggina è prutetta picchi' veni nclusa {{PLURAL:$1|ntâ pàggina innicata di sèquitu, supra â quali|ntê pàggini innicati di sèquitu, supra ê quali}} è attivata la prutizzioni a' cascata.\nI canciamenti fatti ô liveḍḍu di prutizzioni di sta pàggina nun vannu a' canciari la prutizzioni a' cascata.",
+       "protect-text": "Cca poi a' vìdiri e canciari lu liveddu di prutizzioni dâ pàggina <strong>$1</strong>.",
+       "protect-locked-blocked": "Nun si ponnu canciari li livedda di prutizzioni quannu unu è bluccatu.\nCca cci su' li mpustazzioni attuali dâ pàggina <strong>$1</strong>:",
+       "protect-locked-dblock": "Nun si ponnu canciari li livedda di prutizzioni picchì cc'è attivatu un bloccu dâ basi di dati.\nCca cci su' li mpustazzioni attuali dâ pàggina <strong>$1</strong>:",
+       "protect-locked-access": "Lu to cuntu nun havi lu pirmissu di canciari li livedda di prutizzioni.\nCca cci su' li mpustazzioni attuali dâ pàggina <strong>$1</strong>:",
+       "protect-cascadeon": "Com'ad ora sta pàggina è prutetta picchi' veni nclusa {{PLURAL:$1|ntâ pàggina innicata di sèquitu, supra â quali|ntê pàggini innicati di sèquitu, supra ê quali}} è attivata la prutizzioni a' cascata.\nI canciamenti fatti ô liveddu di prutizzioni di sta pàggina nun vannu a' canciari la prutizzioni a' cascata.",
        "protect-default": "Cunsenti a' tutti l'utenti",
        "protect-fallback": "Cunsenti sulu a' l'utenti cû pirmissu \"$1\"",
        "protect-level-autoconfirmed": "Cunsenti sulu a' l'utenti autu-cunfirmati",
        "protect-expiring-local": "scadi lu $1",
        "protect-expiry-indefinite": "a' tempu nditirminatu",
        "protect-cascade": "Pruteggi li pàggini nclusi nta chista (prutizzioni a' cascata)",
-       "protect-cantedit": "Nun poi canciari li liveḍḍi di prutizzioni di sta pàggina picchì nun hai lu pirmissu di canciàrila.",
+       "protect-cantedit": "Nun poi canciari li livedda di prutizzioni di sta pàggina picchì nun hai lu pirmissu di canciàrila.",
        "protect-othertime": "Autra scadenza:",
        "protect-othertime-op": "autra scadenza",
        "protect-existing-expiry": "Scadenza attuali: $3 dû $3",
        "protect-edit-reasonlist": "Cancia li mutivi pâ prutizzioni",
        "protect-expiry-options": "1 ura:1 hour,1 jornu:1 day,1 simana:1 week,2 simani:2 weeks,1 misi:1 month,3 misi:3 months,6 misi:6 months,1 annu:1 year,infinitu:infinite",
        "restriction-type": "Pirmissu:",
-       "restriction-level": "Liveḍḍu di ristrizzioni:",
+       "restriction-level": "Liveddu di ristrizzioni:",
        "minimum-size": "Grannizza mìnima",
        "maximum-size": "Grannizza màssima:",
        "pagesize": "(byte)",
        "restriction-upload": "Carricamentu",
        "restriction-level-sysop": "prutetta",
        "restriction-level-autoconfirmed": "semi-prutetta",
-       "restriction-level-all": "tutti li liveḍḍi",
+       "restriction-level-all": "tutti li liveddi",
        "undelete": "Talìa li pàggini cancillati",
        "undeletepage": "Talìa e ricùpira li pàggini cancillati",
        "undeletepagetitle": "<strong>Quantu segui è cumpostu di virsioni cancillati di [[:$1|$1]]</strong>.",
        "viewdeletedpage": "Talìa li pàggini cancillati",
        "undeletepagetext": "{{PLURAL:$1|La siguenti pàggina fu' cancillata|Li siguenti $1 pàggini foru cancillati}}, però {{PLURAL:$1|è|sunnu}} ancora nta l'archiviu e pi' chistu si {{PLURAL:$1|po|ponnu}} ancora ricupirari.\nPiriudicamenti l'archìviu po' vèniri svacantatu.",
        "undelete-fieldset-title": "Ricùpira virsioni",
-       "undeleteextrahelp": "Pi' ricupirari la storia sana dâ pàggina, cliccari <strong><em>{{int:undeletebtn}}</em></strong> senza scegghîri nuḍḍa caseḍḍa.\nPi' fari nu ricùpiru silittivu, scegghîri li caseḍḍi currispunnenti ê virsioni di ripigghiari, e cliccari <strong><em>{{int:undeletebtn}}</em></strong>.",
+       "undeleteextrahelp": "Pi' ricupirari la storia sana dâ pàggina, cliccari <strong><em>{{int:undeletebtn}}</em></strong> senza scegghîri nudda casedda.\nPi' fari nu ricùpiru silittivu, scegghîri li caseddi currispunnenti ê virsioni di ripigghiari, e cliccari <strong><em>{{int:undeletebtn}}</em></strong>.",
        "undeleterevisions": "$1 {{PLURAL:$1|virsioni|virsioni}} nta l'archiviu",
-       "undeletehistory": "Siddu ricùpiri sta pàggina, tutti li so virsioni vèninu ricupirati ntâ crunuluggìa.\nSiddu na pàggina nova havi statu crïata cû stissu tìtulu di chiḍḍa di ricupirari doppu dâ so cancillazzioni, li virsioni ricupirati vannu a' finiri ntâ crunuluggìa passata.",
+       "undeletehistory": "Siddu ricùpiri sta pàggina, tutti li so virsioni vèninu ricupirati ntâ crunuluggìa.\nSiddu na pàggina nova havi statu crïata cû stissu tìtulu di chidda di ricupirari doppu dâ so cancillazzioni, li virsioni ricupirati vannu a' finiri ntâ crunuluggìa passata.",
        "undeleterevdel": "Lu ricùpiru nun veni fattu siddu pròvuca la cancillazzioni parziali dâ virsioni currenti dâ pàggina o dû file.\nNta stu casu, hai a' livari lu signu di spunta o l'ammucciamentu dâ virsioni cancillata cchiu' ricenti.",
        "undeletehistorynoadmin": "Sta pàggina fu' cancillata.\nLu mutivu dâ cancillazzioni è ammustratu ccà sutta, nzèmmula ê dittagghî di l'utenti ca canciaru sta pàggina prima dâ so cancillazzioni.\nLu testu cuntinutu ntê virsioni cancillati è dispunìbbili sulu a' l'amministratura.",
        "undelete-revision": "Virsioni cancillata di $1 (dû $4 ê $5) di $3:",
        "undeleterevision-missing": "Virsioni nun vàlida o mancanti.\nPo' èssiri chi' hai un culligamentu sbagghiatu, o puru la virsioni hâ statu già ricupirata o livata di l'archiviu.",
-       "undelete-nodiff": "Nun fu' attruvata nuḍḍa virsioni passata.",
+       "undelete-nodiff": "Nun fu' attruvata nudda virsioni passata.",
        "undeletebtn": "Ricùpira",
        "undeletelink": "talìa/ricùpira",
        "undeleteviewlink": "talìa",
        "undelete-search-box": "Cerca li pàggini cancillati",
        "undelete-search-prefix": "Ammustra li pàggini unni lu tìtulu accumènza cu':",
        "undelete-search-submit": "Cerca",
-       "undelete-no-results": "Nuḍḍa pàggina currispunnentu fu' attruvata nta l'archiviu dî pàggini cancillati.",
+       "undelete-no-results": "Nudda pàggina currispunnentu fu' attruvata nta l'archiviu dî pàggini cancillati.",
        "undelete-filename-mismatch": "Nun si po' annullari la cancillazzioni dâ virsioni dû file cu' data e ura $1: Nomu di file nun currispunnenti.",
        "undelete-bad-store-key": "Nun si po' annullari la cancillazzioni dâ virsioni dû file cu' data e ura $1: Lu file mancava avanti dâ cancillazzioni.",
        "undelete-cleanup-error": "Erruri ntâ cancillazzioni dû file d'archiviu nun adupiratu \"$1\".",
        "undelete-show-file-submit": "Si",
        "namespace": "Namespace:",
        "invert": "Inverti la silizzioni",
-       "tooltip-invert": "Scègghî sta caseḍḍa p'ammucciari li canciamenti chi' su' fatti a' pàggini dû namespace silizzunatu (e macari dû so namespace assuciatu, si' la caseḍḍa rilativa è scigghiuta)",
+       "tooltip-invert": "Scègghî sta casedda p'ammucciari li canciamenti chi' su' fatti a' pàggini dû namespace silizzunatu (e macari dû so namespace assuciatu, si' la casedda rilativa è scigghiuta)",
        "namespace_association": "Namespace assuciatu",
-       "tooltip-namespace_association": "Scègghî sta caseḍḍa pi' nclùdiri macari u namespace di discussioni o principali assuciatu ô namespace silizzunatu",
+       "tooltip-namespace_association": "Scègghî sta casedda pi' nclùdiri macari u namespace di discussioni o principali assuciatu ô namespace silizzunatu",
        "blanknamespace": "(Principali)",
        "contributions": "Cuntribbuta di l'{{GENDER:$1|utenti}}",
        "contributions-title": "Cuntribbuta di l'utenti $1",
        "mycontris": "Li me cuntribbuta",
        "contribsub2": "Di {{GENDER:$3|$1}} ($2)",
        "contributions-userdoesnotexist": "Lu cuntu utenti \"$1\" nun è riggistratu.",
-       "nocontribs": "Nuḍḍu canciamentu fu' truvatu chi' currispunni a' sti criterî.",
+       "nocontribs": "Nuddu canciamentu fu' truvatu chi' currispunni a' sti criterî.",
        "uctop": "(attuali)",
        "month": "A' pàrtiri dû misi (e pricidenti):",
        "year": "A' pàrtiri di l'annu (e pricidenti):",
        "blockipsuccesstext": "[[Special:Contributions/$1|$1]] fu' bluccatu.<br />\nTalìa la [[Special:BlockList|lista dî blocchi]] pi' rivìdiri li blocchi.",
        "ipb-blockingself": "Stai bluccannu a' tia stissu! Si' sicuru chi' voi fari sta cosa?",
        "ipb-confirmhideuser": "Stai bluccannu n'utenti chi' havi l'opzioni \"ammuccia utenti\" attivata. A' sta manera u nomu di st'utenti veni supprimutu nta tutti i listi e tutti i riggìstri. Si' sicuru chi' voi fari sta cosa?",
-       "ipb-confirmaction": "Si' si' pi' davera sicuru chi' voi fari sta cosa, scegghî a caseḍḍa \"{{int:ipb-confirm}}\" ccassutta.",
+       "ipb-confirmaction": "Si' si' pi' davera sicuru chi' voi fari sta cosa, scegghî a casedda \"{{int:ipb-confirm}}\" ccassutta.",
        "ipb-edit-dropdown": "Cancia li mutivi dû bloccu",
        "ipb-unblock-addr": "Sblocca a' $1",
        "ipb-unblock": "Sblocca a' n'utenti o nu nnirizzu IP",
        "ipbnounblockself": "Nun hai u pirmissu di sbluccari a' tia stissu.",
        "lockdb": "Blocca lu database",
        "unlockdb": "Sblocca lu database",
-       "lockdbtext": "Lu bloccu dû database cumporta la suspinsioni pi' tutti l'utenti dâ pussibbilitati di canciari li pàggini, mpustari li so prifirenzi, mudificari li so listi talïati, e 'n ginirali di cùmpiri tutti l'upirazzioni ca richièdinu canciamenti a lu database.\nPi' favuri cunfirma ca chistu è chiḍḍu chi' hai ntinzioni di fari, e ca a lu tèrmini dâ manutinzzioni pruvidi a lu sbloccu dû database.",
-       "unlockdbtext": "Lu sbloccu dû database cunzenti di novu a tutti l'utenti di canciari li pàggini, mpustari li so prifirenzi, mudificari li so listi talïati, e 'n ginirali di cùmpiri tutti l'upirazzioni ca richièdinu canciamenti a lu database.\nPi' favuri cunfirma ca chistu è chiḍḍu chi' hai ntinzioni di fari.",
+       "lockdbtext": "Lu bloccu dû database cumporta la suspinsioni pi' tutti l'utenti dâ pussibbilitati di canciari li pàggini, mpustari li so prifirenzi, mudificari li so listi talïati, e 'n ginirali di cùmpiri tutti l'upirazzioni ca richièdinu canciamenti a lu database.\nPi' favuri cunfirma ca chistu è chiddu chi' hai ntinzioni di fari, e ca a lu tèrmini dâ manutinzzioni pruvidi a lu sbloccu dû database.",
+       "unlockdbtext": "Lu sbloccu dû database cunzenti di novu a tutti l'utenti di canciari li pàggini, mpustari li so prifirenzi, mudificari li so listi talïati, e 'n ginirali di cùmpiri tutti l'upirazzioni ca richièdinu canciamenti a lu database.\nPi' favuri cunfirma ca chistu è chiddu chi' hai ntinzioni di fari.",
        "lockconfirm": "Sì, ntennu effittivamenti bluccari lu database.",
        "unlockconfirm": "Sì, effittivamenti ntennu, sutta la mè rispunzabbilitati, sbluccari lu database.",
        "lockbtn": "Blocca lu database",
        "unlockbtn": "Sblocca lu database",
-       "locknoconfirm": "Nun scigghîsti a caseḍḍa di cunfirma.",
+       "locknoconfirm": "Nun scigghîsti a casedda di cunfirma.",
        "lockdbsuccesssub": "Bloccu dû database esiquitu",
        "unlockdbsuccesssub": "Sbloccu dû database esiquitu",
        "lockdbsuccesstext": "Lu database hà statu bluccatu.\n<br />Arricorda di [[Special:UnlockDB|rimòviri lu bloccu]] doppu aviri accabbatu l'upirazzioni di manutinzioni.",
        "lockedbyandtime": "(di {{GENDER:$1|$1}} u $2 ê $3)",
        "move-page": "Spustamentu di $1",
        "move-page-legend": "Sposta la pàggina",
-       "movepagetext": "Adupirannu lu mòdulu ccassutta si cancia lu nomu dâ pàggina, spustannu tutta la sò crunuluggìa nta la pàggina nova.\nLu tìtulu vecchiu addiventa nu rimannu versu lu tìtulu novu.\nSi pònnu aggiurnari autumaticamenti i rimanni chi' puntàvunu ô tìtulu origginali.\nMa si' scegghî di nun fàrilu, t'hai a' assicurari ca lu spustamentu nun crea [[Special:DoubleRedirects|rimanni duppî]] o puru [[Special:BrokenRedirects|rimanni rutti]].\nE' to rispunsabbilità ch'i lïami cuntinuunu a' puntari â pàggina bona.\n\nVidi chi' la pàggina <strong>nun veni spustata</strong> siddu cc'è già na pàggina chi havi lu tìtulu novu, tranni siddu la pàggina 'n quistioni è nu rimannu e nun havi crunuluggìa di canciamenti passati.\nChistu voli diri chi' si po' canciari n'autra vota u nomu di la pàggina a' chiḍḍu ch'avìa prima siddu si fa' nu sbagghiu, e chi nun si po' suprascrìviri na pàggina chi già esisti.\n\n<strong>Accura!</strong>\nChistu po' èssiri nu canciamentu dràsticu pi na pàggina friquintata; aviti a' èssiri sicuri di capiri li cunziquenzi prima di cuntinuari.",
+       "movepagetext": "Adupirannu lu mòdulu ccassutta si cancia lu nomu dâ pàggina, spustannu tutta la sò crunuluggìa nta la pàggina nova.\nLu tìtulu vecchiu addiventa nu rimannu versu lu tìtulu novu.\nSi pònnu aggiurnari autumaticamenti i rimanni chi' puntàvunu ô tìtulu origginali.\nMa si' scegghî di nun fàrilu, t'hai a' assicurari ca lu spustamentu nun crea [[Special:DoubleRedirects|rimanni duppî]] o puru [[Special:BrokenRedirects|rimanni rutti]].\nE' to rispunsabbilità ch'i lïami cuntinuunu a' puntari â pàggina bona.\n\nVidi chi' la pàggina <strong>nun veni spustata</strong> siddu cc'è già na pàggina chi havi lu tìtulu novu, tranni siddu la pàggina 'n quistioni è nu rimannu e nun havi crunuluggìa di canciamenti passati.\nChistu voli diri chi' si po' canciari n'autra vota u nomu di la pàggina a' chiddu ch'avìa prima siddu si fa' nu sbagghiu, e chi nun si po' suprascrìviri na pàggina chi già esisti.\n\n<strong>Accura!</strong>\nChistu po' èssiri nu canciamentu dràsticu pi na pàggina friquintata; aviti a' èssiri sicuri di capiri li cunziquenzi prima di cuntinuari.",
        "movepagetext-noredirectfixer": "Usannu lu mòdulu ccà sutta vui canciati lu nomu dâ pàggina, e spustati tutta la sò storia versu la pàggina nova. Lu tìtulu vecchiu addiventa na pàggina di rinnirizzamentu versu lu tìtulu novu. \nAssicuràtivi ca lu spustamentu nun criau [[Special:DoubleRedirects|redirect duppi]] o [[Special:BrokenRedirects|redirect rumputi]]. Vui siti rispunzàbbili dî liami chi avìssiru a puntari â pàggina giusta.\n\nLa pàggina '''nun''' è spustata siddu cc'è già na pàggina cu lu tìtulu novu, tranni chi la pàggina 'n chistioni è vacanti o è na pàggina di ''redirect'' e nun havi n'archiviu di canciamenti.\nChistu signìfica chi vui putiti rinuminari la pàggina cu lu nomu vecchiu si aviti sbagghiatu, e chi nun putiti suprascrìviri nta na pàggina chi esisti già.\n\n'''Accura!'''\nChistu pò èssiri nu canciamentu dràsticu pi na pàggina pupulari; aviti a èssiri sicuri di capiri li cunziquenzi prima di cuntinuari.",
-       "movepagetalktext": "La pàggina di discussioni sarravi autumaticamenti spustata cud iḍḍa <strong>a' menu chi':</strong>\n*Na pàggina di discussioni nun vacanti già esisti cu lu nomu novu, o puru\n*Nun scegghî la caseḍḍa ccassutta.\n\nNta sti casi, si' voi, hâ' spustari o jùnciri la pàggina di discussioni a' manu.",
+       "movepagetalktext": "La pàggina di discussioni sarravi autumaticamenti spustata cud idda <strong>a' menu chi':</strong>\n*Na pàggina di discussioni nun vacanti già esisti cu lu nomu novu, o puru\n*Nun scegghî la casedda ccassutta.\n\nNta sti casi, si' voi, hâ' spustari o jùnciri la pàggina di discussioni a' manu.",
        "movearticle": "Sposta la pàggina",
        "moveuserpage-warning": "<strong>Accura:</strong> Stai spustannu a pàggina di n'utenti. Hâ' sapìri chi' sulu a pàggina sarravi spustata, l'utenti <em>nun sarravi</em> canciatu di nomu.",
-       "movecategorypage-warning": "<strong>Accura:</strong> Stai spustannu a pàggina di na catigurìa. Hâ' sapìri chi' sulu a pàggina sarravi spustata, i pàggini chi' si tròvunu ntâ catigurìa vecchia <em>nun sarrannu</em> catigurizzati nta chiḍḍa nova.",
+       "movecategorypage-warning": "<strong>Accura:</strong> Stai spustannu a pàggina di na catigurìa. Hâ' sapìri chi' sulu a pàggina sarravi spustata, i pàggini chi' si tròvunu ntâ catigurìa vecchia <em>nun sarrannu</em> catigurizzati nta chidda nova.",
        "movenologintext": "Lu spustamentu dî pàggini è cunzintitu sulu a l'utenti riggistrati c'hannu esiquitu l'[[Special:UserLogin|accessu]] a lu situ.",
        "movenotallowed": "Nun hai li pirmessi nicissari a lu spustamentu dê pàggini.",
        "movenotallowedfile": "Nun ci su' li pirmessi nicissàrii pi spustari file.",
        "immobile-target-page": "Nun pòi spustari nti stu tìtulu.",
        "bad-target-model": "A distinazzioni vuluta adòpira nu mudellu di cuntinutu diffirenti. Nun si po' cunvèrtiri dû $1 ô $2.",
        "imagenocrossnamespace": "Nun pòi spustari na mmàggini fora dû namespace Mmàggini.",
-       "nonfile-cannot-move-to-file": "Nun si po' spustari ntô namespace file chiḍḍu chi' nun è nu file.",
+       "nonfile-cannot-move-to-file": "Nun si po' spustari ntô namespace file chiddu chi' nun è nu file.",
        "imagetypemismatch": "La estensioni nova dû file cun currispunni â sò estensioni riali",
        "imageinvalidfilename": "Lu nomu dû file di distinazzioni nun è validu",
        "fix-double-redirects": "Aggiorna tutti li redirect chi puntanu ô titulu urigginali",
        "importuploaderrortemp": "Caricamentu dû file pi la mpurtazzioni non arrinisciutu. Manca na cartedda timpurània.",
        "import-parse-failure": "Sbagghiu d'anàlisi ntâ mpurtazzioni XML",
        "import-noarticle": "Nudda pàggina di mpurtari.",
-       "import-nonewrevisions": "Nuḍḍa virsioni fu' mpurtata (o già c'èrunu tutti, o furu sautati tutti picchì mmatteru erruri).",
+       "import-nonewrevisions": "Nudda virsioni fu' mpurtata (o già c'èrunu tutti, o furu sautati tutti picchì mmatteru erruri).",
        "xml-error-string": "$1 a riga $2, culonna $3 (byte $4): $5",
        "import-upload": "Càrrica dati XML",
        "import-token-mismatch": "Si pèrsiru li dati rilativi a la sissioni. Pi piaciri, prova n'àutra vota.",
        "import-error-special": "A pàggina \"$1\" nun fu' mpurtata picchì apparteni a' nu namespace spiciali chi' nun cunsenti pàggini.",
        "import-error-invalid": "A pàggina \"$1\" nun fu' mpurtata picchì u nomu unni sarrìa mpurtata nun è vàlidu supra a' sta wiki.",
        "import-error-unserialize": "A virsioni $2 dâ pàggina \"$1\" nun si potti di-sirializzari. Era signatu chi' sta virsioni adupirava u mudellu di cuntinutu $3 sirializzatu comu $4.",
-       "import-error-bad-location": "A virsioni $2 chi' adòpira u mudellu di cuntinutu $3 nun si po' mimurizzari nta \"$1\" supra a' sta wiki, picchì ḍḍu mudellu nun è suppurtatu nta ḍḍa pàggina.",
+       "import-error-bad-location": "A virsioni $2 chi' adòpira u mudellu di cuntinutu $3 nun si po' mimurizzari nta \"$1\" supra a' sta wiki, picchì ddu mudellu nun è suppurtatu nta dda pàggina.",
        "import-options-wrong": "{{PLURAL:$2|Opzioni sbagghiata|Opzioni sbagghiati}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "A pàggina ràdica spicificata nun è vàlida comu tìtulu.",
        "import-rootpage-nosubpage": "U namespace \"$1\" dâ pàggina ràdica nun cunsenti suttapàggini.",
        "import-logentry-interwiki": "hà trasfiritu di àutra wiki la pàggina $1",
        "import-logentry-interwiki-detail": "{{PLURAL:$1|na virsioni mpurtata|$1 virsioni mpurtati}} di $2",
        "javascripttest": "Virìfichi JavaScript",
-       "javascripttest-title": "Esicuzzioni dî virìfichi di $1",
        "javascripttest-pagetext-noframework": "Sta pàggina è risirvata pi' l'esicuzzioni dî virìfichi JavaScript.",
        "javascripttest-pagetext-unknownframework": "Framework di virìfica \"$1\" scanusciutu.",
        "javascripttest-pagetext-frameworks": "Pi' favuri scegghî unu dî siguenti framework di virìfica: $1",
-       "javascripttest-pagetext-skins": "Scegghî na peḍḍi câ quali esiguìri i virìfichi:",
+       "javascripttest-pagetext-skins": "Scegghî na peddi câ quali esiguìri i virìfichi:",
        "javascripttest-qunit-intro": "Talìa [$1 a ducumintazzioni a' prupositu dî virìfichi] supra a' mediawiki.org.",
-       "javascripttest-qunit-heading": "Pachettu di virìfichi JavaScript QUnit di MediaWiki",
        "tooltip-pt-userpage": "La tò pàggina utenti",
        "tooltip-pt-anonuserpage": "La pàggina utenti di stu ndirizzu IP",
        "tooltip-pt-mytalk": "La to' pàggina di discussioni",
        "siteusers": "$1, {{PLURAL:$2|utenti|utenti}} di {{SITENAME}}",
        "anonusers": "{{PLURAL:$2|utenti anònimu|utenti anònimi}} di {{SITENAME}} $1",
        "creditspage": "Autura dâ pàggina",
-       "nocredits": "Nun cc'è nuḍḍa nfurmazzioni supra a' l'autura di sta pàggina.",
+       "nocredits": "Nun cc'è nudda nfurmazzioni supra a' l'autura di sta pàggina.",
        "spamprotectiontitle": "Filtru anti-spam",
        "spamprotectiontext": "La pàggina ca vulevi sarvari hà statu bluccata dû filtru anti-spam. Chistu è prubbabbirmenti duvutu â prisenza di nu liami a nu situ sternu bluccatu.",
        "spamprotectionmatch": "Lu nostru filtru anti-spam hà ndividuatu lu testu siquenti: $1",
        "exif-gpslatitude-s": "Latitùtini Sud",
        "exif-gpslongitude-e": "Lungitùtini Est",
        "exif-gpslongitude-w": "Lungitùtini Ovest",
-       "exif-gpsaltitude-above-sealevel": "$1 {{PLURAL:$1|metru|metri}} supra ô liveḍḍu dû mari",
-       "exif-gpsaltitude-below-sealevel": "$1 {{PLURAL:$1|metru|metri}} sutta ô liveḍḍu dû mari",
+       "exif-gpsaltitude-above-sealevel": "$1 {{PLURAL:$1|metru|metri}} supra ô liveddu dû mari",
+       "exif-gpsaltitude-below-sealevel": "$1 {{PLURAL:$1|metru|metri}} sutta ô liveddu dû mari",
        "exif-gpsstatus-a": "Misurazzioni n cursu",
        "exif-gpsstatus-v": "Misurazzioni nteropiràbbili",
        "exif-gpsmeasuremode-2": "Misurazzioni bidiminziunali",
        "monthsall": "tutti",
        "confirmemail": "Cunfirma dû nnirizzu di posta elittrònica",
        "confirmemail_noemail": "Nun hà statu ndicatu un ndirizzu e-mail vàlidu ntê propi [[Special:Preferences|prifirenzi]].",
-       "confirmemail_text": "{{SITENAME}} dumanna la cunvàlida dû to nnirizzu di posta elittrònica pi' putìri adupirari li funziunalità assuciati.\nCalca lu buttuni ccassutta pi' mannari nu missaggiu e-mail di cunfirma a lu to nnirizzu.\nNtô missaggiu cci sarravi nu culligamentu cuntinenti un còdici;\ncàrrica ḍḍu culligamentu cu lu to browser pi' cunfirmari ca lu to nnirizzu di posta elittrònica è vàlidu.",
+       "confirmemail_text": "{{SITENAME}} dumanna la cunvàlida dû to nnirizzu di posta elittrònica pi' putìri adupirari li funziunalità assuciati.\nCalca lu buttuni ccassutta pi' mannari nu missaggiu e-mail di cunfirma a lu to nnirizzu.\nNtô missaggiu cci sarravi nu culligamentu cuntinenti un còdici;\ncàrrica ddu culligamentu cu lu to browser pi' cunfirmari ca lu to nnirizzu di posta elittrònica è vàlidu.",
        "confirmemail_pending": "Già nu còdici di cunfirma t'havi statu mannatu via e-mail;\nsiddu hai crïatu u to cuntu di picca tempu, è mègghiu ch'aspètti l'arrivu dû còdici pi' quarchi minutu prima di pruvari a' addumannàrinni unu novu.",
        "confirmemail_send": "Manna un còdici di cunfirma via e-mail",
        "confirmemail_sent": "Missaggiu e-mail di cunfirma mannatu.",
        "lag-warn-high": "A càusa di nu ritardu eccissivu nta l'aggiurnamentu dô server di databbasi, li canciamenti appurtati {{PLURAL:$1|nta l'ùrtimu secundu|nta l'ùrtimi $1 secundi}} ponnu nun èssiri nta sta lista.",
        "watchlistedit-normal-title": "Cancia pàggini taliati",
        "watchlistedit-normal-legend": "Eliminazzioni di pàggini dâ lista dê pàggini taliati",
-       "watchlistedit-normal-explain": "Ccassutta cci su' li tìtuli ntâ to lista talïata.\nPi' livàrinni unu, scegghî la caseḍḍa a' latu d'iḍḍu, e clicca \"{{int:Watchlistedit-normal-submit}}\".\nPoi puru [[Special:EditWatchlist/raw|canciari la lista 'n forma testuali]].",
+       "watchlistedit-normal-explain": "Ccassutta cci su' li tìtuli ntâ to lista talïata.\nPi' livàrinni unu, scegghî la casedda a' latu d'iddu, e clicca \"{{int:Watchlistedit-normal-submit}}\".\nPoi puru [[Special:EditWatchlist/raw|canciari la lista 'n forma testuali]].",
        "watchlistedit-normal-submit": "Elìmina pàggini",
        "watchlistedit-normal-done": "Dâ lista dê pàggini taliati hà{{PLURAL:$1|&nbsp;stata eliminata na pàggina|nnu stati eliminati $1 pàggini}}:",
        "watchlistedit-raw-title": "Cancia li pàggini taliati 'n forma testuali",
        "invalid-indicator-name": "<strong>Erruri:</strong> L'attribbutu <code>name</code> di l'innicaturi di statu dâ pàggina nun havi a' èssiri vacanti.",
        "version": "Virsioni",
        "version-extensions": "Estenzioni nstallati",
-       "version-skins": "Peḍḍi installati",
+       "version-skins": "Peddi installati",
        "version-specialpages": "Pàggini spiciali",
        "version-parserhooks": "Hook dû parser",
        "version-variables": "Variabili",
        "version-hook-name": "Nomu di l'hook",
        "version-hook-subscribedby": "Suttascrizzioni",
        "version-version": "(Virsioni $1)",
-       "version-no-ext-name": "[nuḍḍu nomu]",
+       "version-no-ext-name": "[nuddu nomu]",
        "version-license": "Licenza di MediaWiki",
        "version-ext-license": "Licenza",
        "version-ext-colheader-name": "Estinsioni",
-       "version-skin-colheader-name": "Peḍḍi",
+       "version-skin-colheader-name": "Peddi",
        "version-ext-colheader-version": "Virsioni",
        "version-ext-colheader-license": "Licenza",
        "version-ext-colheader-description": "Discrizzioni",
        "version-ext-colheader-credits": "Auturi",
        "version-license-title": "Licenza di $1",
-       "version-license-not-found": "Pi' st'estinsioni nun fu' truvata nuḍḍa nfurmazzioni a' prupòsitu dâ licenza.",
+       "version-license-not-found": "Pi' st'estinsioni nun fu' truvata nudda nfurmazzioni a' prupòsitu dâ licenza.",
        "version-credits-title": "Ricanuscimenti pi' $1",
-       "version-credits-not-found": "Pi' st'estinsioni nun fu' truvata nuḍḍa nfurmazzioni a' prupòsitu dî ricanuscimenti.",
+       "version-credits-not-found": "Pi' st'estinsioni nun fu' truvata nudda nfurmazzioni a' prupòsitu dî ricanuscimenti.",
        "version-poweredby-credits": "Sta wiki funziona cu' <strong>[https://www.mediawiki.org/ MediaWiki]</strong>, copyright © 2001-$1 $2.",
        "version-poweredby-others": "autri",
        "version-poweredby-translators": "i tradutturi di translatewiki.net",
        "version-credits-summary": "Vulemu ricanusciri u cuntribbutu di sti pirsuni a' [[Special:Version|MediaWiki]].",
-       "version-license-info": "MediaWiki è software lìbbiru; si po' ri-distribbüiri e/o mudificari sutta ê tèrmini dâ GNU General Public License comu pubblicata dâ Free Software Foundation; o la virsioni 2 dâ Licenza, o (a' propia scelta) na virsioni succissiva quali è jè.\n\nMediaWiki veni distribuùtu ntâ spiranza chi' sia ùtili, però SENZA NUḌḌA GARANZÌA; mancu chiḍḍa implìcita di NIGUZZIABBILITÀ o di APPLICABBILITÀ PI' NU SCOPU PARTICULARI. Si talïassi la GNU General Public License pi' maggiuri dittagghî.\n\nS'avissi a' avìri ricivutu [{{SERVER}}{{SCRIPTPATH}}/COPYING na copia dâ GNU General Public License] nsèmmula a' stu prugramma; si' no, si po' scrìviri â Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA o [//www.gnu.org/licenses/old-licenses/gpl-2.0.html la si po' lèggiri in linia].",
+       "version-license-info": "MediaWiki è software lìbbiru; si po' ri-distribbüiri e/o mudificari sutta ê tèrmini dâ GNU General Public License comu pubblicata dâ Free Software Foundation; o la virsioni 2 dâ Licenza, o (a' propia scelta) na virsioni succissiva quali è jè.\n\nMediaWiki veni distribuùtu ntâ spiranza chi' sia ùtili, però SENZA NUDDA GARANZÌA; mancu chidda implìcita di NIGUZZIABBILITÀ o di APPLICABBILITÀ PI' NU SCOPU PARTICULARI. Si talïassi la GNU General Public License pi' maggiuri dittagghî.\n\nS'avissi a' avìri ricivutu [{{SERVER}}{{SCRIPTPATH}}/COPYING na copia dâ GNU General Public License] nsèmmula a' stu prugramma; si' no, si po' scrìviri â Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA o [//www.gnu.org/licenses/old-licenses/gpl-2.0.html la si po' lèggiri in linia].",
        "version-software": "Software nstallatu",
        "version-software-product": "Prodottu",
        "version-software-version": "Virsioni",
        "fileduplicatesearch-info": "$1 × $2 pixel<br />Diminzioni: $3<br />Tipu MIME: $4",
        "fileduplicatesearch-result-1": "Non ci sunnu duppiuni li stissi dû file \"$1\".",
        "fileduplicatesearch-result-n": "{{PLURAL:$2|C'è ggià nu duppiuni lu stissu|Ci sunnu ggià $2 duppiuni li stissi}} dû file \"$1\".",
-       "fileduplicatesearch-noresults": "Nuḍḍu file chiamatu \"$1\" fu' truvatu.",
+       "fileduplicatesearch-noresults": "Nuddu file chiamatu \"$1\" fu' truvatu.",
        "specialpages": "Pàggini spiciali",
        "specialpages-note-top": "Legenda",
        "specialpages-note": "* Pàggini spiciali nurmali.\n* <span class=\"mw-specialpagerestricted\">Pàggini spiciali risirvati.</strong>",
        "specialpages-group-developer": "Stigghi dû sviluppaturi",
        "blankpage": "Pàggina vacanti",
        "intentionallyblankpage": "Sta pàggina è lassata vacanti apposta e è usata pi benchmark, ecc.",
-       "external_image_whitelist": " #Lassari sta riga pi' com'è ora, senza tuccàrila<pre>\n#Mèttiri li frammenti dî sprissioni rigulari (sulu la parti ca va' mmenzu ê //) ccassutta\n#Sarrannu cunfruntati cu l'URL dî mmàggini esterni (hotlinked)\n#Chiḍḍi ca currispùnnunu sarrannu ammustrati comu mmàggini, pi' l'autri veniravi ammustratu sulu nu culligamentu a la mmàggini\n#Li righi ca accumencianu cu' # sunnu trattati comu cummenti\n#Nun cc'è diffirenza tra majusculi e minusculi\n\n#Mèttiri tutti li frammenti di sprissioni rigulari supra a' sta riga. Lassa sta riga pi' com'è ora, senza tuccàrila</pre>",
+       "external_image_whitelist": " #Lassari sta riga pi' com'è ora, senza tuccàrila<pre>\n#Mèttiri li frammenti dî sprissioni rigulari (sulu la parti ca va' mmenzu ê //) ccassutta\n#Sarrannu cunfruntati cu l'URL dî mmàggini esterni (hotlinked)\n#Chiddi ca currispùnnunu sarrannu ammustrati comu mmàggini, pi' l'autri veniravi ammustratu sulu nu culligamentu a la mmàggini\n#Li righi ca accumencianu cu' # sunnu trattati comu cummenti\n#Nun cc'è diffirenza tra majusculi e minusculi\n\n#Mèttiri tutti li frammenti di sprissioni rigulari supra a' sta riga. Lassa sta riga pi' com'è ora, senza tuccàrila</pre>",
        "tags": "Tag di canciamenti validi",
        "tag-filter": "Filtru dô [[Special:Tags|Tag]]",
        "tag-filter-submit": "Filtra",
        "feedback-adding": "Agghiuncimentu dû cummentu â pàggina...",
        "feedback-error1": "Erruri: Risultatu di l'API nun ricanusciutu",
        "feedback-error2": "Erruri: A mudìfica nun riniscìu",
-       "feedback-error3": "Erruri: Nuḍḍa risposta di l'API",
+       "feedback-error3": "Erruri: Nudda risposta di l'API",
        "feedback-thanks": "Grazzî! U to cummentu fu' affissu ntâ pàggina \"[$2 $1]\".",
        "feedback-close": "Finutu",
        "feedback-bugcheck": "Bonu! Sulu cuntrolla chi' nun è unu dî [$1 bug già canusciuti].",
        "api-error-missingresult": "Erruri nternu: Nun fu' pussìbbili capiri s'a copia riniscìu.",
        "api-error-mustbeloggedin": "Hâ' jèssiri trasutu pi' carricari file.",
        "api-error-mustbeposted": "Erruri nternu: A richiesta havi bisognu di POST HTTP.",
-       "api-error-noimageinfo": "U carricamentu riniscìu, però u server nun nni desi nuḍḍa nfurmazzioni a' prupòsitu dû file.",
+       "api-error-noimageinfo": "U carricamentu riniscìu, però u server nun nni desi nudda nfurmazzioni a' prupòsitu dû file.",
        "api-error-nomodule": "Erruri nternu: nun fu mpustatu lu mòdulu di carricamentu",
        "api-error-ok-but-empty": "Erruri ntenru: nudda risposta dû server",
        "api-error-overwrite": "Suprascriviri nu file ca nun esisti nun è cunsitutu",
        "limitreport-expansiondepth": "Màssimu funnu d'espansioni",
        "limitreport-expensivefunctioncount": "Cuntìggiu dî funzioni di l'analizzaturi sintatticu spisusi",
        "expandtemplates": "Espansioni dî template",
-       "expand_templates_intro": "Sta pàggina spiciali pigghia un testu e espanni tutti i template chi' cunteni, di manera ricursiva.\nEspanni macari i funzioni di l'analizzaturi sintatticu chi' su suppurtati, comu <code><nowiki>{{</nowiki>#language:…}}</code>, e i variàbbili, comu <code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nIn pratica, espanni cchiu' o menu tuttu chiḍḍu chi' si trova mmenzu a' duppî parèntisi graffi.",
+       "expand_templates_intro": "Sta pàggina spiciali pigghia un testu e espanni tutti i template chi' cunteni, di manera ricursiva.\nEspanni macari i funzioni di l'analizzaturi sintatticu chi' su suppurtati, comu <code><nowiki>{{</nowiki>#language:…}}</code>, e i variàbbili, comu <code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nIn pratica, espanni cchiu' o menu tuttu chiddu chi' si trova mmenzu a' duppî parèntisi graffi.",
        "expand_templates_title": "Tìtulu dû cuntestu, pi' {{FULLPAGENAME}} etc.:",
        "expand_templates_input": "Testu a' espànniri:",
        "expand_templates_output": "Risultatu",
        "log-name-pagelang": "Riggistru dî canci di lingua",
        "log-description-pagelang": "Chistu è nu riggistru dî canciamenti â lingua dî pàggini.",
        "logentry-pagelang-pagelang": "$1 {{GENDER:$2|canciau}} a lingua dâ pàggina $3 di $4 a' $5.",
-       "default-skin-not-found": "Whoops! A peḍḍi pridifinuta dâ to wiki, mpustata nta <code dir=\"ltr\">$wgDefaultSkin</code> comu <code>$1</code>, nun è dispunìbbili.\n\nA' quantu pari a to installazzioni ncludi i peḍḍi ccasutta. Talìa [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manüali: Cunfigurazzioni dî peḍḍi] p'istruzzioni supra a' comu s'attìvunu e comu si scegghî chiḍḍa pridifinuta.\n\n$2\n\n; Si' hai installatu MediaWiki ora ora:\n: E' prubbàbbili chi' l'installasti dû git, o direttamenti dû còdici surgenti nta quarchi' autra manera. Allura sta cosa è privista. Prova e installa quarchi' peḍḍi di [https://www.mediawiki.org/wiki/Category:All_skins l'archìviu dî peḍḍi di mediawiki.org], a na manera di chisti:\n:* Scàrrica [https://www.mediawiki.org/wiki/Download u prugramma d'installazzioni in furmatu tar], chi' cunteni tanti peḍḍi ed estinsioni. Poi cupiari e ncuḍḍari a cartella <code>skins/</code> di ḍḍadintra.\n:* Scàrrica a' una a' una quarchi' peḍḍi in furmatu tar di [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* Clona via git unu dî dipòsiti <code>mediawiki/skins/*</code> ntâ cartella <code dir=\"ltr\">skins/</code> dâ to installazzioni di MediaWiki.\n: Fari accussì' nun avissi a' ntirfirìri cû to dipòsitu git si' si' nu sviluppaturi di MediaWiki.\n\n; Si' hai aggiurnatu MediaWiki ora ora:\n: MediaWiki virsioni 1.24 e succissivi nun attìvunu cchiu' di manera autumàtica i peḍḍi installati (talìa [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manüali: Scuperta autumatica dî peḍḍi]). Poi cupiari e ncuḍḍari sti righi nta <code>LocalSettings.php</code> p'attivari tutti i peḍḍi chi' sunnu pi' com'ora installati:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Si' hai mudificatu <code>LocalSettings.php</code> ora ora:\n: Cuntrolla chi' nun sbagghiasti a' scriviri i nomi dî peḍḍi.",
-       "default-skin-not-found-no-skins": "Whoops! A peḍḍi pridifinuta dâ to wiki, mpustata nta <code dir=\"ltr\">$wgDefaultSkin</code> comu <code>$1</code>, nun è dispunìbbili.\n\nNun hai nuḍḍa peḍḍi installata.\n\n; Si' hai installatu o puru aggiurnatu MediaWiki ora ora:\n: E' prubbàbbili chi' l'installasti dû git, o direttamenti dû còdici surgenti nta quarchi' autra manera. Allura sta cosa è privista. MediaWiki virsioni 1.24 e succissivi nun cuntènunu nuḍḍa peḍḍi ntô dipòsitu principali. Prova e installa quarchi' peḍḍi di [https://www.mediawiki.org/wiki/Category:All_skins l'archìviu dî peḍḍi di mediawiki.org], a na manera di chisti:\n:* Scàrrica [https://www.mediawiki.org/wiki/Download u prugramma d'installazzioni in furmatu tar], chi' cunteni tanti peḍḍi ed estinsioni. Poi cupiari e ncuḍḍari a cartella <code>skins/</code> di ḍḍadintra.\n:* Scàrrica a' una a' una quarchi' peḍḍi in furmatu tar di [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* Clona via git unu dî dipòsiti <code>mediawiki/skins/*</code> ntâ cartella <code dir=\"ltr\">skins/</code> dâ to installazzioni di MediaWiki.\n: Fari accussì' nun avissi a' ntirfirìri cû to dipòsitu git si' si' nu sviluppaturi di MediaWiki. Talìa [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manüali: Cunfigurazzioni dî peḍḍi] p'istruzzioni supra a' comu s'attìvunu i peḍḍi e comu si scegghî chiḍḍa pridifinuta.",
+       "default-skin-not-found": "Whoops! A peddi pridifinuta dâ to wiki, mpustata nta <code dir=\"ltr\">$wgDefaultSkin</code> comu <code>$1</code>, nun è dispunìbbili.\n\nA' quantu pari la to installazzioni ncludi i peddi ccasutta. Talìa [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manüali: Cunfigurazzioni dî peddi] p'istruzzioni supra a' comu s'attìvunu e comu si scegghî chidda pridifinuta.\n\n$2\n\n; Si' hai installatu MediaWiki ora ora:\n: E' prubbàbbili chi' l'installasti dû git, o direttamenti dû còdici surgenti nta quarchi' autra manera. Allura sta cosa è privista. Prova e installa quarchi' peddi di [https://www.mediawiki.org/wiki/Category:All_skins l'archìviu dî peddi di mediawiki.org], a na manera di chisti:\n:* Scàrrica [https://www.mediawiki.org/wiki/Download u prugramma d'installazzioni in furmatu tar], chi' cunteni tanti peddi ed estinsioni. Poi cupiari e ncuddari a cartella <code>skins/</code> di ddadintra.\n:* Scàrrica a' una a' una quarchi' peddi in furmatu tar di [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* Clona via git unu dî dipòsiti <code>mediawiki/skins/*</code> ntâ cartella <code dir=\"ltr\">skins/</code> dâ to installazzioni di MediaWiki.\n: Fari accussì' nun avissi a' ntirfirìri cû to dipòsitu git si' si' nu sviluppaturi di MediaWiki.\n\n; Si' hai aggiurnatu MediaWiki ora ora:\n: MediaWiki virsioni 1.24 e succissivi nun attìvunu cchiu' di manera autumàtica i peddi installati (talìa [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manüali: Scuperta autumatica dî peddi]). Poi cupiari e ncuddari sti righi nta <code>LocalSettings.php</code> p'attivari tutti i peddi chi' sunnu pi' com'ora installati:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Si' hai mudificatu <code>LocalSettings.php</code> ora ora:\n: Cuntrolla chi' nun sbagghiasti a' scriviri i nomi dî peddi.",
+       "default-skin-not-found-no-skins": "Whoops! La peddi pridifinuta dâ to wiki, mpustata nta <code dir=\"ltr\">$wgDefaultSkin</code> comu <code>$1</code>, nun è dispunìbbili.\n\nNun hai nudda peddi installata.\n\n; Si' hai installatu o puru aggiurnatu MediaWiki ora ora:\n: E' prubbàbbili chi' l'installasti dû git, o direttamenti dû còdici surgenti nta quarchi' autra manera. Allura sta cosa è privista. MediaWiki virsioni 1.24 e succissivi nun cuntènunu nudda peddi ntô dipòsitu principali. Prova e installa quarchi' peddi di [https://www.mediawiki.org/wiki/Category:All_skins l'archìviu dî peddi di mediawiki.org], a na manera di chisti:\n:* Scàrrica [https://www.mediawiki.org/wiki/Download u prugramma d'installazzioni in furmatu tar], chi' cunteni tanti peddi ed estinsioni. Poi cupiari e ncuddari a cartella <code>skins/</code> di ddadintra.\n:* Scàrrica a' una a' una quarchi' peddi in furmatu tar di [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n:* Clona via git unu dî dipòsiti <code>mediawiki/skins/*</code> ntâ cartella <code dir=\"ltr\">skins/</code> dâ to installazzioni di MediaWiki.\n: Fari accussì' nun avissi a' ntirfirìri cû to dipòsitu git si' si' nu sviluppaturi di MediaWiki. Talìa [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manüali: Cunfigurazzioni dî peddi] p'istruzzioni supra a' comu s'attìvunu i peddi e comu si scegghî chidda pridifinuta.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (attivata)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 ('''disattivata''')",
        "mediastatistics": "Statìstichi supra ê file multimidiali",
index 3d6a276..50073d8 100644 (file)
        "import-logentry-interwiki": "uveženo (\"transwikied\") $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revizija|revizije|revizija}} sa $2",
        "javascripttest": "Javaskript test",
-       "javascripttest-title": "Izvršavanje testova za $1",
        "javascripttest-pagetext-noframework": "Ova stranica je rezervisana za izvršavanje javaskript testova.",
        "javascripttest-pagetext-unknownframework": "Nepoznati radni okvir „$1“.",
        "javascripttest-pagetext-frameworks": "Izaberite jedan od sledećih radnih okvira: $1",
        "javascripttest-pagetext-skins": "Izaberite s kojim skinom (interfejsom) želite da pokrenete probu:",
        "javascripttest-qunit-intro": "Pogledajte [$1 dokumentaciju za testiranje] na mediawiki.org.",
-       "javascripttest-qunit-heading": "Medijavikijin paket za testiranje – QUnit",
        "tooltip-pt-userpage": "Vaša korisnička stranica",
        "tooltip-pt-anonuserpage": "Korisnička stranica za ip koju Vi uređujete kao",
        "tooltip-pt-mytalk": "Vaša stranica za razgovor",
index adf4fb8..ced5aca 100644 (file)
                        "아라",
                        "හරිත",
                        "Indunil Chamara",
-                       "Susith Chandira Gts"
+                       "Susith Chandira Gts",
+                       "Thanushka"
                ]
        },
        "tog-underline": "සබැඳි යටීර කිරීම:",
        "tog-hideminor": "මෑත වෙනස් කිරීම්වල සුළු සංස්කරණ සඟවන්න",
-       "tog-hidepatrolled": "මà·\91ත à·\80à·\99නà·\83à·\8a à¶\9aà·\92රà·\93මà·\8aà·\80ල à¶¸à·\94ර à·\83à¶\82චà·\8fරය à¶\9aරන ලද à·\83à¶\82à·\83à·\8aà¶\9aරණ à·\83à¶\9fවන්න",
-       "tog-newpageshidepatrolled": "විමසුමට ලක්කෙරුණු පිටු, අළුත් පිටු ලැයිස්තුවෙහි නොපෙන්වන්න",
+       "tog-hidepatrolled": "à·\80à·\92මà·\83à·\94මට à¶½à¶\9aà·\8aà¶\9aà·\99රà·\94ණà·\94 à·\83à¶\82à·\83à·\8aà¶\9aරණ, à¶¸à·\91ත à·\80à·\99නà·\83à·\8a à¶\9aà·\92රà·\93මà·\8a à¶­à·\94ල à¶±à·\9cපà·\99නà·\8aවන්න",
+       "tog-newpageshidepatrolled": "විමසුමට ලක්කෙරුණු පිටු, අළුත් පිටු ලැයිස්තුව තුල නොපෙන්වන්න",
        "tog-extendwatchlist": "මෑත වෙනස්වීම් පමණක් නොව, අදාළ සියළු වෙනස්වීම් දක්වා පෙන්වන අයුරින් මුර-ලැයිස්තුව පුළුල් කරන්න",
        "tog-usenewrc": "මෑත වෙනස්වීම් සහ මුර ලැයිස්තුව හී පිටුව අනුව සමූහ වෙනස්වීම් (ජාවාස්ක්‍රිප්ට් ඇවැසිය)",
        "tog-numberheadings": "ශීර්ෂ-නාම ස්වයංක්‍රීයව අංකනය කරන්න",
        "tog-shownumberswatching": "මුර කරනු ලබන පරිශීලකයන් සංඛ්‍යාව පෙන්වන්න",
        "tog-oldsig": "පවතින අත්සන:",
        "tog-fancysig": "අත්සන විකිපෙළ (ස්වයංක්‍රීය සබැඳියක් විරහිතව) ලෙසින් සලකන්න",
-       "tog-uselivepreview": "තත්කාල පෙර-දසුන භාවිතා කරන්න (ජාවාස්ක්‍රිප්ට්) (පරීක්ෂණාත්මක)",
+       "tog-uselivepreview": "තත්කාල පෙර-දසුන භාවිතා කරන්න",
        "tog-forceeditsummary": "හිස් සංස්කරණ සාරාංශයකට මා ඇතුළු වන විට මාහට ඉඟි කරන්න",
        "tog-watchlisthideown": "මුර-ලැයිස්තුවෙන් මාගේ සංස්කරණ සඟවන්න",
        "tog-watchlisthidebots": "මුර-ලැයිස්තුවෙන් රොබෝ සංස්කරණ සඟවන්න",
        "tog-watchlisthideminor": "මුර-ලැයිස්තුවෙන් සුළු සංස්කරණ සඟවන්න",
        "tog-watchlisthideliu": "ප්‍රවිෂ්ට වී ඇති පරිශීලකයන් විසින් සිදුකර ඇති සංස්කරණ මුර-ලැයිස්තුවෙන් සඟවන්න",
        "tog-watchlisthideanons": "නිර්නාමික පරිශීලකයන් විසින් සිදුකොට ඇති සංස්කරණ මුර-ලැයිස්තුවෙන් සඟවන්න",
-       "tog-watchlisthidepatrolled": "විමසුමට ලක්කෙරුණු සංස්කරණයන්, මෑත වෙනස්වීම් හී නොපෙන්වන්න",
+       "tog-watchlisthidepatrolled": "විමසුමට ලක්කෙරුණු සංස්කරණයන් මුර-ලැයිස්තුව තුල නොපෙන්වන්න",
        "tog-ccmeonemails": "මා විසින් අනෙකුත් පරිශීලකයන් හට යවන විද්‍යුත්-තැපෑලයන්හි පිටපත් මාහට එවන්න",
        "tog-diffonly": "“වෙනස් ”පදයන්ට පහළින්, පිටුවල අන්තර්ගතය   නොපෙන්වන්න",
        "tog-showhiddencats": "සැඟවුනු ප්‍රවර්ග පෙන්වන්න",
@@ -69,7 +70,7 @@
        "underline-always": "සැමවිටම කරන්න",
        "underline-never": "කිසිවිටෙක නොකරන්න",
        "underline-default": "සම හෝ ගවේෂකයෙහි පෙරනිමිය",
-       "editfont-style": "à\85à¶\9aà·\94රà·\94 à·\80à·\92ලà·\8fà·\83යනà·\8a à·\83à¶\82à·\83à·\8aà¶\9aරණ à¶´à·\99දà·\99à·\83:",
+       "editfont-style": "à·\83à¶\82à·\83à·\8aà¶\9aරණ à¶´à·\99දà·\99à·\83 à¶­à·\94ල à¶\85à¶\9aà·\94රà·\94 à·\80à·\92ලà·\8fà·\83ය:",
        "editfont-default": "පෙර නිමි බ්‍රව්සරය",
        "editfont-monospace": "ඒක අවකාශිත ෆොන්ට්",
        "editfont-sansserif": "සෙරිෆ්-විරහිත අකුරු",
        "pool-timeout": "අගුල සඳහා බලාපොරොත්තුවෙන් සිටීම කල් ඉකුත්වනලදී",
        "pool-queuefull": "පොරොත්තු ලේඛනය පිරී ඇත",
        "pool-errorunknown": "හඳුනා නොගත් දෝෂය",
+       "poolcounter-usage-error": "පරිශීලන දෝෂය: $1",
        "aboutsite": "{{SITENAME}} පිළිබඳ",
        "aboutpage": "Project:පිළිබඳ",
        "copyright": " අන්ලෙසකින් සඳහන්කර නැති සෑම විටෙකම අන්තර්ගතය $1 යටතේ ඇත.",
        "filerenameerror": "\"$1\" ගොනුව \"$2\" බවට යළි-නම්-කිරීම සිදු කල නොහැකි විය.",
        "filedeleteerror": "\"$1\" ගොනුව මකා-දැමිය නොහැකි විය.",
        "directorycreateerror": "\"$1\" නාමාවලිය තැනීම කල නොහැකි විය.",
+       "directoryreadonlyerror": "\"$1\" ගොණුව කියවීමට පමණයි.",
+       "directorynotreadableerror": "\"$1\" ගොණුව කියවීමට නොහැක.",
        "filenotfound": "\"$1\" ගොනුව සොයා ගත නොහැකි විය.",
        "unexpected": "අනපේක්‍ෂිත අගය: \"$1\"=\"$2\".",
        "formerror": "දෝෂය: ආකෘති-පත්‍රය ඉදිරිපත් කල නොහැකි විය",
        "viewsourcetext": "මෙම පිටුවෙහි මූලාශ්‍රය නැරඹීමට හා පිටපත් කිරීමට ඔබ හට හැකිය:",
        "viewyourtext": "'''ඔබගේ සංස්කරණ''' නැරඹීම සහ මූලාශ්‍රය පිටපත් කිරීම ඔබට කල හැක:",
        "protectedinterface": "මෙම පිටුව විසින්, මෘදුකාංගය සඳහා අතුරුමුව පෙළ සපයන අතර එබැවින් අපයෙදුම වැලැක්වීම සඳහා එය අවුරා ඇත.",
-       "editinginterface": "'''අවවාදයයි:''' මෘදුකාංගයට අතුරුමුව පෙළ සැපයීමට භාවිතා වන පිටුවක් ඔබ විසින් සංස්කරණය කරනු ලබයි.\nමෙම පිටුවට සිදු කරන වෙනස්වීම් විසින් අනෙකුත් පරිශීලකයන්ගේ පරිශීලක අතුරුමුවෙහි පෙනුමට බලපෑම් එල්ල කෙරෙනු ඇත.\nපරිවර්තන සඳහා, මීඩියාවිකි ප්‍රාදේශීයකරන ව්‍යාපෘතිය, [//translatewiki.net/wiki/Main_Page?setlang=si translatewiki.net], භාවිතා කිරීම සලකා බැලීමට කාරුණික වන්න.",
+       "editinginterface": "<strong>අවවාදයයි:</strong> මෘදුකාංගයට අතුරුමුව පෙළ සැපයීමට භාවිතා වන පිටුවක් ඔබ විසින් සංස්කරණය කරනු ලබයි.\nමෙම පිටුවට සිදු කරන වෙනස්වීම් විසින් අනෙකුත් පරිශීලකයන්ගේ පරිශීලක අතුරුමුවෙහි පෙනුමට බලපෑම් එල්ල කෙරෙනු ඇත.",
        "cascadeprotected": "\"තීරු දර්ශන\" විකල්පය සක්‍රීයනය කොට එමගින් ආරක්‍ෂණය කල පහත දැක්වෙන {{PLURAL:$1|පිටුව|පිටු}} අඩංගු කර ඇති බැවින්, මෙම පිටුව සංස්කරණය කිරීමෙන් වලකා ඇත:\n$2",
        "namespaceprotected": "'''$1''' නාමඅවකාශයෙහි පිටු සංස්කරණය කිරීමට ඔබහට අවසර නොමැත.",
        "customcssprotected": "මෙම CSS පිටුව සංස්කරණය කිරීමට ඔබට අවසර නොමැත්තේ එහි අනෙකුත් පරිශීලකයෙකුගේ පුද්ගලික පරිස්ථිතීන් අඩංගු බැවිනි.",
        "titleprotected": "මෙම ශීර්ෂ-නාමය තැනීම  [[User:$1|$1]] විසින් වාරණය කොට ඇත.\nමේ සඳහා  ''$2''  හේතුව දක්වා ඇත.",
        "filereadonlyerror": "\"$2\"දත්ත ගොනුවේ කියවීමට පමණක් ඇති ආකාරයට ඇති නිසා \"$1\" ගොනුව සංස්කරණය කල නොහැක.\n\nමෙය අගුලු දැමූ පරිගණක පරිපාලක \"$3\" හේතුව ඉදිරිපත්කර ඇත.",
        "exception-nologin": "ප්‍රවිෂ්ට වී නොමැත",
+       "exception-nologin-text": "මෙම පිටුවට ප්‍රවේශ වීමට හෝ ඉල්ලුම් කරන ලද ක්‍රියාව සිදුකිරීම සඳහා කරුණාකර ඔබගේ ගිණුමට ප්‍රවේශ වන්න.",
        "virus-badscanner": "අයෝග්‍ය වික්‍යාසයකි: අඥාත වයිරස සුපිරික්සකයකි: ''$1''",
        "virus-scanfailed": "පරිලෝකනය අසාර්ථක විය (කේතය $1)",
        "virus-unknownscanner": "නොහඳුනන ප්‍රතිවයිරසයක්:",
        "gotaccountlink": "පිවිසෙන්න",
        "userlogin-resetlink": "ඔබේ පිවිසුම් තොරතුරු අමතකද?",
        "userlogin-resetpassword-link": "ඔබේ මුරපදය නැති වුනාද?",
+       "userlogin-helplink2": "ගිණුම වෙත ප්‍රවේශ වීම සඳහා උදවු",
        "userlogin-loggedin": "ඔබ දැනටමත් {{GENDER:$1|}} ලෙස පිවිසී ඇත.\nනව පරිශීලකයෙකු ලෙස ඇතුළු වීමට පහත ආකෘතිය පුරවන්න.",
        "userlogin-createanother": "තවත් ගිණුමක් ආරම්භ කරන්න",
        "createacct-emailrequired": "වි-තැපෑල ලිපිනය",
        "createaccount-text": "කිසියම් අයෙකු, \"$2\" නමින් හා, \"$3\" යන මුර-පදය යොදමින්,  ඔබගේ විද්‍යුත්-තැපැල් ලිපිනය සඳහා {{SITENAME}} ($4) හි ගිණුමක් තනා ඇත.\nඔබ දැන් ගිණුම‍ට පිවිස, ඔබගේ මුර-පදය වෙනස් කල යුතුව ඇත.\n\nමෙම ගිණුම තැනී ඇත්තේ වැරදීමකින් නම්, මෙම පණිවුඩය නොසලකා හැරිය හැක.",
        "login-throttled": "ඔබ විසින් මෑතදී  පමණට වඩා වාර ගණනක් පිවිසීමෙහි උත්සාහයන් දරා ඇත.\nයළි උත්සාහ කිරීමට පෙර $1 වේලාවක් රැඳී සිටින්න.",
        "login-abort-generic": "ඔබගේ පිවිසීම අසාර්ථකයි - අතහැර දමනලදී",
+       "login-migrated-generic": "ඔබගේ ගිණුමේ ස්වරුපය වෙනස්කර ඇත. ඔබගේ පරිශීලක නාමය මෙම විකිය තුල තවදුරටත් භාවිත කල නොහැක.",
        "loginlanguagelabel": "භාෂාව: $1",
        "suspicious-userlogout": "නිෂ්ක්‍රමණය සඳහා ඔබගේ අයැදුම නිෂ්ප්‍රභා කෙරුනේ එය යොමු කොට ඇත්තේ භින්න(කැඩුනු) බ්‍රවුසරයකින් හෝ නිවේෂණය කෙරෙමින් පවතින ප්‍රොක්සියක් වෙතින් යැයි බැලූ බැල්මට පෙනෙන බැවිනි.",
        "createacct-another-realname-tip": "සැබෑ නාමය හෙළි කිරීම වෛකල්පිකයි.\nඔබ විසින් එය හෙළි කල හොත්, ඔබගේ කෘතීන් සඳහා ඔබහට කතෘ-බුහුමන් පිරිනැමීමට එය භාවිතා කරනු ඇත.",
        "resettokens": "සංකේත නැවත සකසන්න",
        "resettokens-legend": "සංකේත නැවත සකසන්න",
        "resettokens-tokens": "සංකේත:",
+       "resettokens-token-label": "$1 (පවතින අගය: $2)",
        "bold_sample": "තදකුරු පෙළ",
        "bold_tip": "තදකුරු පෙළ",
        "italic_sample": "ඇලකුරු පෙළ",
        "preview": "පෙරදසුන",
        "showpreview": "පෙරදසුන පෙන්වන්න",
        "showdiff": "වෙනස්කිරීම් පෙන්වන්න",
-       "anoneditwarning": "'''අවවාදයයි:''' ඔබ පරිශීලකයෙකු වශයෙන් පද්ධතියට ප්‍රවිෂ්ට වී නොමැත.\nඔබගේ අයිපී යොමුව මෙම පිටුවෙහි සංස්කරණ ඉතිහාසයෙහි වාර්තාගත වෙනු ඇත",
+       "anoneditwarning": "<strong>අවවාදයයි:</strong> ඔබ පරිශීලකයෙකු වශයෙන් පද්ධතියට ප්‍රවිෂ්ට වී නොමැත.\nඔබගේ අයිපී යොමුව මෙම පිටුවෙහි සංස්කරණ ඉතිහාසයෙහි වාර්තාගත වෙනු ඇත\nඔබ <strong>[$1 පිවිසීම]</strong> හෝ <strong>[$2 ගිණුමක් තැනීම]</strong> කලහොත්, ඔබගේ සංස්කරණයන් වෙනත් ප්‍රතිලාභ සමග, ඔබගේ පරිශීලක නාමය ඉදිරියේ දැක්වෙනු ඇත.",
        "anonpreviewwarning": "අවවාදයයි: ඔබ පරිශීලකයෙකු වශයෙන් පද්ධතියට ප්‍රවිෂ්ට වී නොමැත. එමනිසා මෙම පිටුවෙහි සංස්කරණ ඉතිහාසයෙහි, ඔබගේ අන්තර්ජාල ලිපිනය සටහන් කරගැනීමට සිදුවනු ඇත.",
        "missingsummary": "'''සිහිගැන්වීමයි:''' ඔබ විසින් සංස්කරණ සාරාංශයක් සපයා නොමැත.\nඔබ නැවතත් සුරැකීම ක්ලික් කලහොත්, ඔබගේ සංස්කරණය එවැන්නක් විරහිතවම සුරැකෙනු ඇත.",
        "missingcommenttext": "කරුණාකර පහතින් පරිකථනයක් ඇතුළු කරන්න.",
        "edit-gone-missing": "පිටුව යාවත්කාල කිරීම සිදුකල නොහැකි විය.\nඑය මකා දමා ඇති බවක් පෙනේ.",
        "edit-conflict": "සංස්කරණ ගැටුම.",
        "edit-no-change": "පෙළට කිසිදු වෙනසක් සිදු නොකල  බැවින් ඔබගේ සංස්කරණය නොසලකාහරින ලදි.",
+       "postedit-confirmation-created": "මෙම පිටුව නිර්මාණය කරන ලදී.",
+       "postedit-confirmation-restored": "මෙම පිටුව නැවත පිහිටුවන ලදී.",
        "postedit-confirmation-saved": "ඔබගේ සංස්කරණය සුරකින ලදී.",
        "edit-already-exists": "නව පිටුවක් තැනිය නොහැකි විය.\nඑය දැනටමත් පවතියි.",
        "defaultmessagetext": "සාමාන්‍ය පණිවුඩ පෙළ",
        "history-feed-empty": "අයැදුනු පිටුව නොපවතියි.\nඑය විකියෙන් මකා දමා හෝ නම-වෙනස් කොට ඇතිවා විය හැකිය.\nඅදාල නව පිටු සඳහා  [[Special:Search|විකිය තුල ගවේෂණය]] අත්හදා බලන්න.",
        "rev-deleted-comment": "(සංස්කරණ සාරාංශය ඉවත් කරන ලදි)",
        "rev-deleted-user": "(පරිශීලක-නාමය ඉවත් කරන ලදි)",
-       "rev-deleted-event": "(ලà¶\9dà·\94-à·\83ටà·\84නà·\8a à¶­à·\90බà·\93මà·\9a  à¶\9aà·\8aâ\80\8dරà·\92යà·\8fà·\80 à¶\85තà·\8aà·\84à·\92ටà·\94à·\80න à¶½à¶¯à·\92)",
+       "rev-deleted-event": "(ලà¶\9dà·\94-à·\83ටà·\84නà·\8a à¶\89à·\80තà·\8a à¶\9aරන à¶½à¶¯à·\93)",
        "rev-deleted-user-contribs": "[පරිශීපක නාමය හෝ ලිපිනය ඉවත් කළා - දායකත්ව මඟින් සඟවන ලද සංස්කරණය]",
        "rev-deleted-text-permission": "මෙම පිටු සංශෝධනය '''මකා දමා ඇත'''.\nවැඩි විස්තර බොහෝ විට [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} මකාදැමීම් ලඝු-සටහන] වෙත තිබීමට ඉඩ ඇත.",
        "rev-deleted-text-unhide": "මෙම පිටුව සංශෝධනය කිරීම '''මකා දමා ඇත'''.\nමේ පිලිබඳ විස්තර බොහෝවිට [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} මකා දැමීම් ලඝු-සටහනෙහි] තිබීමට ඉඩ ඇත.\nඔබට ඇවැසි නම් [$1 මෙම වෙනස නැරඹීම] තවමත් සිදුකල හැක.",
        "powersearch-togglelabel": "පිරික්සන්න:",
        "powersearch-toggleall": "සියල්ල",
        "powersearch-togglenone": "කිසිවක් නොමැත",
+       "powersearch-remember": "අනාගත සෙවිම් තුලදි මෙම තෝරාගැනීම් මතක තබාගන්න",
        "search-external": "බාහිර ගවේෂණය",
        "searchdisabled": "{{SITENAME}} ගවේෂණය අක්‍රීය කොට ඇත.\nමේ අතරතුර ඔබ හට ගූගල් ඔස්සේ ගවේෂණය කල හැක.\n{{SITENAME}} අන්තර්ගතය පිළිබඳ ඔවුන්ගේ සූචි යල් පැන ගොස් ඇතිවා විය හැකි බව සටහන් කර ගන්න.",
+       "search-error": "සෙවීම් සිදුකිරීමේදී වැරද්දක් මතුවී ඇත: $1",
        "preferences": "අභිරුචි",
        "mypreferences": "අභිරුචීන්",
        "prefs-edits": "සංස්කරණයන් සංඛ්‍යාව:",
        "right-editusercssjs": "අනෙකුත් පරිශීලකයන්ගේ  CSS හා JS ගොනු සංස්කරණය කරන්න",
        "right-editusercss": "අනෙකුත් පරිශීලකයන්ගේ  CSS ගොනු සංස්කරණය කරන්න",
        "right-edituserjs": "අනෙකුත් පරිශීලකයන්ගේ  JS ගොනු සංස්කරණය කරන්න",
+       "right-viewmywatchlist": "ඔබගේ මුර-ලැයිස්තුව පෙන්වන්න",
+       "right-viewmyprivateinfo": "ඔබගේ පෞද්ගලික දත්ත පෙන්වන්න (උදා. විද්‍යුත් තැපැල් ලිපිනය, නිවැරදි නම)",
+       "right-editmyprivateinfo": "ඔබගේ පෞද්ගලික දත්ත සංස්කරණය කරන්න (උදා. විද්‍යුත් තැපැල් ලිපිනය, නිවැරදි නම)",
+       "right-editmyoptions": "ඔබගේ අභිරුචියන් සංස්කරණය කරන්න",
        "right-rollback": "සුවිශේෂ පිටුවක් අවසන් වරට සංස්කරණය කල පරිශීලකයෙකුගේ සංස්කරණයන් විගසින් පුනරාවර්තනය කරන්න",
        "right-markbotedits": "පුනරාවර්තනය-කෙරුනු සංස්කරණයන් රොබෝ සංස්කරණයන් ලෙස සලකුණු කරන්න",
        "right-noratelimit": "‍සීඝ්‍රතා සීමාවන්ගෙක් බලපෑම් ඇතිනොවන්න",
        "action-createpage": "පිටු තනන්න",
        "action-createtalk": "සංවාද පිටු තනන්න",
        "action-createaccount": "මෙම පරිශීලක ගිණුම තනන්න",
+       "action-history": "මෙම පිටුවේ අතීතය පෙන්වන්න",
        "action-minoredit": "මෙම සංස්කරණය සුළු ලෙස සලකුණු කරන්න",
        "action-move": "මෙම පිටුව ගෙනයන්න",
        "action-move-subpages": "මෙම පිටුව හා එහි උප පිටු ගෙන යන්න",
        "action-userrights-interwiki": "අනෙකුත් විකියන්ගේ පරිශීලකයන්ගේ පරිශීලක හිමිකම් සංස්කරණය කරන්න",
        "action-siteadmin": "දත්ත-සංචිතය අවහිරකරන්න හෝ අවහිරය ඉවත් කරන්න",
        "action-sendemail": "ඊ-තැපැල් පණිවුඩ යවන්න",
+       "action-editmywatchlist": "ඔබගේ මුර-ලැයිස්තුව සංස්කරණය කරන්න",
+       "action-viewmywatchlist": "ඔබගේ මුර-ලැයිස්තුව පෙන්වන්න",
+       "action-viewmyprivateinfo": "ඔබගේ පෞද්ගලික තොරතුරු පෙන්වන්න",
+       "action-editmyprivateinfo": "ඔබගේ පෞද්ගලික තොරතුරු සංස්කරණය කරන්න",
        "nchanges": "$1 {{PLURAL:$1|වෙනස්වීම|වෙනස්වීම්}}",
        "enhancedrc-history": "ඉතිහාසය",
        "recentchanges": "මෑත වෙනස්කිරීම්",
        "import-logentry-interwiki": "$1 අන්තර්විකීකරණය කරන ලදි",
        "import-logentry-interwiki-detail": "$2 වෙතින් {{PLURAL:$1|එක් සංශෝධනයක්|සංශෝධන $1 ක්}}",
        "javascripttest": "ජාවාස්ක්‍රිප්ට් පරික්ෂාකරමින්",
-       "javascripttest-title": "$1 පරික්ෂණ සිදුකරමින්",
        "javascripttest-pagetext-noframework": "මෙම පිටුව ජාවාස්ක්‍රිප්ට් පරික්ෂණ සිදුකිරීම සඳහා වෙන්කර ඇත.",
        "tooltip-pt-userpage": "ඔබගේ පරිශීලක පිටුව",
        "tooltip-pt-anonuserpage": "සංස්කරණයට ඔබ භාවිතා කරමින් පවතින අන්තර්ජාල ලිපිනය සඳහා පරිශීලක පිටුව",
        "version-entrypoints": "නිවේශන ලක්ෂ්‍ය URL",
        "version-entrypoints-header-entrypoint": "නිවේශන ලක්ෂ්‍යය",
        "version-entrypoints-header-url": "URL",
+       "version-libraries": "ස්ථාපිත පුස්තකාල",
+       "version-libraries-library": "පුස්තකාලය",
+       "version-libraries-version": "අනුවාදය",
        "fileduplicatesearch": "අනුපිටපත් ගොනු සඳහා ගවේෂණය කරන්න",
        "fileduplicatesearch-summary": "එහි පූරක අගය පාදක කර ගෙන අනුපිටපත් ගොනු සඳහා ගවේෂණය කරන්න.",
        "fileduplicatesearch-legend": "අනුපිටපතක් සඳහා ගවේෂණය කරන්න",
        "compare-revision-not-exists": "ඔබ විසින් විශේෂණය කෙරූ සංශෝධනය නොපවතියි.",
        "dberr-problems": "සමාවන්න! මෙම අඩවිය තාක්ෂණික ගැටළු අත්දකියි.",
        "dberr-again": "විනාඩි කිහිපයක් කල්ගතකර යළි-බාගැනුම උත්සාහ කරන්න.",
-       "dberr-info": "(දත්තගබඩා සේවාදායකය හා සම්බන්ධ වීම‍ට නොහැක: $1)",
+       "dberr-info": "(දත්තගබඩාවට ඇතුළු වීම‍ට නොහැකිය: $1)",
+       "dberr-info-hidden": "(දත්තගබඩාවට ඇතුළු වීම‍ට නොහැකිය)",
        "dberr-usegoogle": "මේ අතරතුර ගූගල් ඔස්සේ ගවේෂණය කිරීමට ඔබ විසින් යත්න දැරිය හැක.",
        "dberr-outofdate": "අපගේ අන්තර්ගතයෙහි සූචියන් යල් පැන ගොස් තිබිය හැකි බව සටහන් කර ගන්න.",
        "dberr-cachederror": "මෙය ඉල්ලා ඇති පිටුවෙහි පූර්වාපේක්ෂිත සංචිත පිටුවක් වන අතර එය යාවත්කාලින නොවිය හැකි බව සලකන්න.",
index fb51256..636db89 100644 (file)
        "import-logentry-interwiki": "prenesel $1 med wikiji",
        "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.",
        "javascripttest-pagetext-unknownframework": "Neznano ogrodje za preizkušanje »$1«.",
+       "javascripttest-pagetext-unknownaction": "Neznano dejanje »$1«.",
        "javascripttest-pagetext-frameworks": "Prosimo, izberite enega od naslednjih ogrodjev za preizkušanje: $1",
        "javascripttest-pagetext-skins": "Izberite kožo, v kateri želite pognati preizkuse:",
        "javascripttest-qunit-intro": "Oglejte si [$1 dokumentacijo o preizkušanju] na mediawiki.org.",
-       "javascripttest-qunit-heading": "Preizkuševalni paket MediaWiki JavaScript QUnit",
        "tooltip-pt-userpage": "Vaša uporabniška stran",
        "tooltip-pt-anonuserpage": "Uporabniška stran IP-naslova, ki ga uporabljate",
        "tooltip-pt-mytalk": "Vaša pogovorna stran",
index 368eccc..07d68db 100644 (file)
        "parser-unstrip-loop-warning": "Утврђена је петља",
        "parser-unstrip-recursion-limit": "Прекорачено је ограничење рекурзије ($1)",
        "converter-manual-rule-error": "Пронађена је грешка у правилу за ручно претварање језика",
-       "undo-success": "Ð\98змена Ñ\81е Ð¼Ð¾Ð¶Ðµ Ð²Ñ\80атити.\nПроверите разлике испод, па сачувајте измене.",
+       "undo-success": "Ð\98змена Ñ\81е Ð¼Ð¾Ð¶Ðµ Ð¿Ð¾Ð½Ð¸Ñ\88тити.\nПроверите разлике испод, па сачувајте измене.",
        "undo-failure": "Ова измена се не може поништити због сукоба измена.",
        "undo-norev": "Не могу да вратим измену јер не постоји или је обрисана.",
        "undo-nochange": "Изгледа да је измена већ поништена.",
        "import-logentry-interwiki": "је увезао $1 с другог викија",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|измена увезена|измене увезене|измена увезено}} из $2",
        "javascripttest": "Јаваскрипт тест",
-       "javascripttest-title": "Извршавање тестова за $1",
        "javascripttest-pagetext-noframework": "Ова страница је резервисана за извршавање јаваскрипт тестова.",
        "javascripttest-pagetext-unknownframework": "Непознати радни оквир „$1“.",
        "javascripttest-pagetext-frameworks": "Изаберите један од следећих радних оквира: $1",
        "javascripttest-pagetext-skins": "Изаберите с којом темом желите да покренете пробу:",
        "javascripttest-qunit-intro": "Погледајте [$1 документацију за тестирање] на mediawiki.org.",
-       "javascripttest-qunit-heading": "Медијавикијин пакет за тестирање – QUnit",
        "tooltip-pt-userpage": "Ваша корисничка страница",
        "tooltip-pt-anonuserpage": "Корисничка страница за ИП адресу с које уређујете",
        "tooltip-pt-mytalk": "Ваша страница за разговор",
index 5cdf281..a308047 100644 (file)
        "error": "Greška",
        "databaseerror": "Greška u bazi podataka",
        "databaseerror-text": "Došlo je do greške u upitu baze podataka. Možda je u pitanju programska greška.",
+       "databaseerror-textcl": "Došlo je do greške u upitu baze podataka.",
        "databaseerror-query": "Upit: $1",
        "databaseerror-function": "Funkcija: $1",
        "databaseerror-error": "Greška: $1",
        "filerenameerror": "Ne mogu da preimenujem datoteku „$1“ u „$2“.",
        "filedeleteerror": "Ne mogu da obrišem datoteku „$1“.",
        "directorycreateerror": "Ne mogu da napravim fasciklu „$1“.",
+       "directoryreadonlyerror": "Direktorijum „$1“ je samo za čitanje.",
        "directorynotreadableerror": "Direktorijum „$1“ nije čitljiv.",
        "filenotfound": "Ne mogu da pronađem datoteku „$1“.",
        "unexpected": "Neočekivana vrednost: „$1“=„$2“.",
        "viewyourtext": "Možete da pogledate i umnožite izvor '''vaših izmena''' na ovoj stranici:",
        "protectedinterface": "Ova stranica sadrži tekst korisničkog okruženja za softver na ovom vikiju i zaštićena je radi sprečavanja zloupotrebe.\nDa biste dodali ili izmenili prevode svih vikija, posetite [//translatewiki.net/ Translejtviki], projekat za lokalizaciju Medijavikija.",
        "editinginterface": "<strong>Upozorenje:</strong> uređujete stranicu koja se koristi za prikazivanje teksta korisničkog okruženja.\nIzmene na ovoj stranici će uticati na sve korisnike ovog vikija.",
+       "translateinterface": "Da dodate ili promenite prevode za sve vikije, posetite [//translatewiki.net/ Translejtviki], projekat za lokalizaciju Medijavikija.",
        "cascadeprotected": "Ova stranica je zaključana jer sadrži {{PLURAL:$1|sledeću stranicu koja je zaštićena|sledeće stranice koje su zaštićene}} „prenosivom“ zaštitom:\n$2",
        "namespaceprotected": "Nemate dozvolu da uređujete stranice u imenskom prostoru '''$1'''.",
        "customcssprotected": "Nemate dozvolu da menjate ovu CSS stranicu jer sadrži lične postavke drugog korisnika.",
        "anoneditwarning": "<strong>Upozorenje:</strong> niste prijavljeni. Vaša IP adresa će biti javno vidljiva u istoriji ove stranice ako načinite bilo kakvu izmenu. Ako se <strong>[$1 prijavite]</strong> ili <strong>[$2 otvorite nalog]</strong> vaše izmene će biti pripisane vašem korisničkom imenu.",
        "anonpreviewwarning": "''Niste prijavljeni. Vaša IP adresa će biti zabeležena u istoriji ove stranice.''",
        "missingsummary": "'''Napomena:''' niste uneli opis izmene.\nAko ponovo kliknete na „{{int:savearticle}}“, vaša izmena će biti sačuvana bez opisa.",
+       "selfredirect": "<strong>Upozorenje:</strong> preusmeravate ovu stranicu na nju samu.\nMožda vam je odredišna stranica pogrešna ili uređujete pogrešnu stranicu.\nAko još jednom pritisnete „{{int:savearticle}}“ preusmerenje će svejedno biti napravljeno.",
        "missingcommenttext": "Unesite komentar ispod.",
        "missingcommentheader": "'''Napomena:''' niste uneli naslov ovog komentara.\nAko ponovo kliknete na „{{int:savearticle}}“, vaša izmena će biti sačuvana bez naslova.",
        "summary-preview": "Pregled opisa:",
        "parser-unstrip-loop-warning": "Utvrđena je petlja",
        "parser-unstrip-recursion-limit": "Prekoračeno je ograničenje rekurzije ($1)",
        "converter-manual-rule-error": "Pronađena je greška u pravilu za ručno pretvaranje jezika",
-       "undo-success": "Izmena se može vratiti.\nProverite razlike ispod, pa sačuvajte izmene.",
+       "undo-success": "Izmena se može poništiti.\nProverite razlike ispod, pa sačuvajte izmene.",
        "undo-failure": "Ova izmena se ne može poništiti zbog sukoba izmena.",
        "undo-norev": "Ne mogu da vratim izmenu jer ne postoji ili je obrisana.",
        "undo-nochange": "Izgleda da je izmena već poništena.",
        "search-result-category-size": "{{PLURAL:$1|1 član|$1 člana|$1 članova}}, ({{PLURAL:$2|1 potkategorija|$2 potkategorije|$2 potkategorija}}, {{PLURAL:$3|1 datoteka|$3 datoteke|$3 datoteka}})",
        "search-redirect": "(preusmerenje $1)",
        "search-section": "(odeljak $1)",
+       "search-category": "(kategorija $1)",
+       "search-file-match": "(podudara se sadržaj datoteke)",
        "search-suggest": "Da li ste mislili na: $1",
        "search-interwiki-caption": "Bratski projekti",
        "search-interwiki-default": "Rezultati sa $1:",
        "right-move": "premeštanje stranica",
        "right-move-subpages": "premeštanje stranica s njihovim podstranicama",
        "right-move-rootuserpages": "premeštanje osnovnih korisničkih stranica",
+       "right-move-categorypages": "premeštanje kategorija",
        "right-movefile": "premeštanje datoteka",
        "right-suppressredirect": "preskakanje stvaranja preusmerenja pri premeštanju stranica",
        "right-upload": "otpremanje datoteka",
        "right-browsearchive": "pretraga obrisanih stranica",
        "right-undelete": "vraćanje obrisanih stranica",
        "right-suppressrevision": "pregledanje, skrivanje i vraćanje određenih izmena stranica od svih korisnika",
+       "right-viewsuppressed": "pregledanje izmena skrivenih od svih korisnika",
        "right-suppressionlog": "gledanje privatnih dnevnika",
        "right-block": "blokiranje daljih izmena drugih korisnika",
        "right-blockemail": "onemogućavanje korisnicima da šalju e-poruke",
        "pager-older-n": "{{PLURAL:$1|stariji 1|starijih $1}}",
        "suppress": "Nadzor",
        "querypage-disabled": "Ova posebna stranica je onemogućena radi poboljšanja performansi.",
+       "apihelp": "API pomoć",
+       "apihelp-no-such-module": "Modul „$1“ nije pronađen.",
        "booksources": "Štampani izvori",
        "booksources-search-legend": "Traži književne izvore",
        "booksources-isbn": "ISBN:",
        "listgrouprights-removegroup-self": "uklanjanje {{PLURAL:$2|grupe|grupa}} sa svog naloga: $1",
        "listgrouprights-addgroup-self-all": "Dodaj sve grupe na sopstveni nalog",
        "listgrouprights-removegroup-self-all": "Ukloni sve grupe sa sopstvenog naloga",
+       "listgrouprights-namespaceprotection-header": "Ograničenja imenskih prostora",
        "listgrouprights-namespaceprotection-namespace": "Imenski prostor",
+       "listgrouprights-namespaceprotection-restrictedto": "Prava potrebna za uređivanje",
        "trackingcategories-name": "Ime poruke",
        "trackingcategories-nodesc": "Opis nije dostupan.",
        "trackingcategories-disabled": "Kategorija je onemogućena",
        "protect-othertime": "Drugo vreme:",
        "protect-othertime-op": "drugo vreme",
        "protect-existing-expiry": "Postojeće vreme isteka: $2 u $3",
+       "protect-existing-expiry-infinity": "Postojeće vreme isteka: trajno",
        "protect-otherreason": "Drugi/dodatni razlog:",
        "protect-otherreason-op": "Drugi razlog",
        "protect-dropdown": "* Najčešći razlozi zaštićivanja\n** Prekomerni vandalizam\n** Nepoželjne poruke\n** Neproduktivni rat izmena\n** Stranica velikog prometa",
        "import-logentry-interwiki": "je uvezao $1 s drugog vikija",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|izmena uvezena|izmene uvezene|izmena uvezeno}} iz $2",
        "javascripttest": "Javaskript test",
-       "javascripttest-title": "Izvršavanje testova za $1",
        "javascripttest-pagetext-noframework": "Ova stranica je rezervisana za izvršavanje javaskript testova.",
        "javascripttest-pagetext-unknownframework": "Nepoznati radni okvir „$1“.",
        "javascripttest-pagetext-frameworks": "Izaberite jedan od sledećih radnih okvira: $1",
        "javascripttest-pagetext-skins": "Izaberite s kojom temom želite da pokrenete probu:",
        "javascripttest-qunit-intro": "Pogledajte [$1 dokumentaciju za testiranje] na mediawiki.org.",
-       "javascripttest-qunit-heading": "Medijavikijin paket za testiranje – QUnit",
        "tooltip-pt-userpage": "Vaša korisnička stranica",
        "tooltip-pt-anonuserpage": "Korisnička stranica za IP adresu s koje uređujete",
        "tooltip-pt-mytalk": "Vaša stranica za razgovor",
        "tooltip-feed-atom": "Atom dovod ove stranice",
        "tooltip-t-contributions": "Pogledajte spisak doprinosa ovog korisnika",
        "tooltip-t-emailuser": "Pošaljite e-poruku ovom korisniku",
+       "tooltip-t-info": "Više informacija o ovoj stranici",
        "tooltip-t-upload": "Pošaljite datoteke",
        "tooltip-t-specialpages": "Spisak svih posebnih stranica",
        "tooltip-t-print": "Verzija ove stranice za štampanje",
        "revdelete-uname-unhid": "korisničko ime je otkriveno",
        "revdelete-restricted": "primenjena ograničenja za administratore",
        "revdelete-unrestricted": "uklonjena ograničenja za administratore",
+       "logentry-merge-merge": "$1 je {{GENDER:$2|spojio|spojila}} $3 u $4 (sve do izmene $5)",
        "logentry-move-move": "$1 je {{GENDER:$2|premestio|premestila}} stranicu $3 na $4",
        "logentry-move-move-noredirect": "$1 je {{GENDER:$2|premestio|premestila}} stranicu $3 na $4 bez ostavljanja preusmerenja",
        "logentry-move-move_redir": "$1 je {{GENDER:$2|premestio|premestila}} stranicu $3 na $4 preko preusmerenja",
        "pagelang-select-lang": "Izaberi jezik",
        "right-pagelang": "menjanje jezika stranice",
        "action-pagelang": "promenu jezika stranice",
+       "mediastatistics": "Statistika datoteka",
        "mediastatistics-summary": "Statistike o tipovima poslatih datoteka. Ovde su uračunate samo najnovije verzije datoteka. Stare ili obrisane verzije nisu uračunate.",
        "mediastatistics-table-mimetype": "MIME tip",
        "mediastatistics-table-extensions": "Moguće ekstenzije",
        "mediastatistics-header-audio": "Audio",
        "mediastatistics-header-video": "Video",
        "mediastatistics-header-office": "Kancelarija",
+       "mediastatistics-header-text": "Tekstualne",
+       "mediastatistics-header-executable": "Izvršne",
+       "mediastatistics-header-archive": "Kompresovane",
        "json-error-syntax": "Greška u sintaksi"
 }
index 36d42ce..b076ebf 100644 (file)
        "import-logentry-interwiki": "överförde $1 mellan wikier",
        "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.",
        "javascripttest-pagetext-unknownframework": "Okänd testmiljö \"$1\".",
+       "javascripttest-pagetext-unknownaction": "Okänd handling \"$1\".",
        "javascripttest-pagetext-frameworks": "Välj en av följande testmiljöer: $1",
        "javascripttest-pagetext-skins": "Välj ett utseende att köra tester med:",
        "javascripttest-qunit-intro": "Se [$1 testningsdokumentationen] på mediawiki.org.",
-       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit testsvit",
        "tooltip-pt-userpage": "Din användarsida",
        "tooltip-pt-anonuserpage": "Användarsida för ip-numret du redigerar från",
        "tooltip-pt-mytalk": "Din diskussionssida",
index e58f468..51a90b7 100644 (file)
@@ -65,7 +65,8 @@
                        "Kafkasmurat",
                        "Violetanka",
                        "Trockya",
-                       "Aşilleus"
+                       "Aşilleus",
+                       "BatuhanBensoy"
                ]
        },
        "tog-underline": "Bağlantıların altını çiz:",
        "search-result-category-size": "{{PLURAL:$1|1 üye|$1 üye}} ({{PLURAL:$2|1 altkategori|$2 altkategori}}, {{PLURAL:$3|1 dosya|$3 dosya}})",
        "search-redirect": "($1 sayfasından yönlendirme)",
        "search-section": "($1 bölümü)",
+       "search-category": "(kategori $1)",
        "search-file-match": "(dosya içeriğiyle eşleşiyor)",
        "search-suggest": "Bunu mu demek istediniz: $1",
        "search-interwiki-caption": "Kardeş projeler",
        "right-deletedtext": "Silinmiş metni ve silinmiş revizyonlar arasındaki değişiklikleri gör",
        "right-browsearchive": "Silinen sayfaları ara",
        "right-undelete": "Bir sayfanın silinmesini geri al",
-       "right-suppressrevision": "Sysoplardan gizlenmiş revizyonları gözden geçir ve geri yükle",
+       "right-suppressrevision": "Sysoplardan gizlenmiş revizyonlarını gizle ve göster",
        "right-suppressionlog": "Özel günlükleri gör",
        "right-block": "Diğer kullanıcıların değişiklik yapmalarını engelle",
        "right-blockemail": "Bir kullanıcının e-posta göndermesini engelle",
        "right-protect": "Koruma düzeylerini değiştir ve kademeli korumalı sayfaları düzenle",
        "right-editprotected": "\"{{int:protect-level-sysop}}\" olarak korunan sayfalarda değişiklik yap",
        "right-editsemiprotected": "\"{{int:protect-level-autoconfirmed}}\" olarak korunan sayfalarda değişiklik yap",
+       "right-editcontentmodel": "Sayfanın içerik modelini düzenle",
        "right-editinterface": "Kullanıcı arayüzünü değiştirmek",
        "right-editusercssjs": "Diğer kullanıcıların CSS ve JS dosyalarında değişiklik yap",
        "right-editusercss": "Diğer kullanıcıların CSS dosyalarında değişiklik yap",
        "pager-older-n": "$1 daha eski",
        "suppress": "Gözetim",
        "querypage-disabled": "Bu özel sayfa, performansa dayalı nedenlerle devre dışı bırakılır.",
+       "apihelp": "API yardımı",
        "apihelp-no-such-module": "\"$1\" modülü bulunamadı.",
        "booksources": "Kaynak kitaplar",
        "booksources-search-legend": "Kitap kaynaklarını ara",
        "listgrouprights-namespaceprotection-restrictedto": "Kullanıcının değişiklik yapmasına izin veren hak(lar)",
        "broken-file-category-desc": "Sayfa bozuk dosya bağlantısı (mevcut olmayan bir dosyayı kullanmaya çalışan bağlantı) içeriyor.",
        "trackingcategories-nodesc": "Açıklama yok.",
+       "trackingcategories-disabled": "Kategori devre dışı",
        "mailnologin": "Gönderi adresi yok.",
        "mailnologintext": "Diğer kullanıcılara e-posta gönderebilmeniz için [[Special:UserLogin|oturum aç]]malısınız ve [[Special:Preferences|tercihler]] sayfasında geçerli bir e-posta adresiniz olmalı.",
        "emailuser": "Bu kullanıcıya e-posta gönder",
        "import-logentry-interwiki": "$1 transvikileşmiş",
        "import-logentry-interwiki-detail": "$2 sayfasından $1 {{PLURAL:$1|revizyon|revizyon}} içe aktarıldı",
        "javascripttest": "JavaScript denemesi",
-       "javascripttest-title": "$1 testleri çalışıyor",
        "javascripttest-pagetext-noframework": "Bu sayfa JavaScript testleri çalıştırmak için ayrılmıştır.",
        "javascripttest-pagetext-unknownframework": "Bilinmeyen test çerçevesi \"$1\".",
+       "javascripttest-pagetext-unknownaction": "Bilinmeyen eylem \"$1\".",
        "javascripttest-pagetext-frameworks": "Lütfen aşağıdaki test çerçevelerinden birini seçin: $1",
        "javascripttest-pagetext-skins": "Testleri koşmak için bir tema seçin:",
        "javascripttest-qunit-intro": "mediawiki.org üzerinden [$1 deneme belgelerine] bakınız.",
-       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit deneme paketi",
        "tooltip-pt-userpage": "Kullanıcı sayfanız",
        "tooltip-pt-anonuserpage": "The user page for the ip you",
        "tooltip-pt-mytalk": "Mesaj sayfanız",
        "dberr-problems": "Üzgünüz! Bu site teknik zorluklar yaşıyor.",
        "dberr-again": "Bir kaç dakika bekleyip tekrar yüklemeyi deneyin.",
        "dberr-info": "(Veritabanı sunucusuyla irtibat kurulamıyor: $1)",
-       "dberr-info-hidden": "(Veritabanı sunucusuna bağlantı kurulamıyor)",
+       "dberr-info-hidden": "(Veritabanı sunucusuyla bağlantı kurulamıyor)",
        "dberr-usegoogle": "Bu zaman zarfında Google ile aramayı deneyebilirsiniz.",
        "dberr-outofdate": "İçeriğimizin onların dizinlerinde güncel olmayabileceğini dikkate alın.",
        "dberr-cachederror": "Aşağıdaki istenen sayfanın önbellekteki bir kopyasıdır, ve güncel olmayabilir.",
        "pagelang-select-lang": "Dil seçin",
        "right-pagelang": "Sayfa dilini değiştir",
        "action-pagelang": "sayfa dilini değiştir",
+       "log-name-pagelang": "Dil günlüğünü değiştir",
        "logentry-pagelang-pagelang": "$1, $3 sayfasının dilini $4 dilinden $5 diline {{GENDER:$2|çevirdi}}.",
        "mediastatistics": "Medya istatistikleri",
        "mediastatistics-summary": "Karşıya yüklenen dosya türlerine ilişkin istatistikler. Bu yalnızca bir dosyanın en son sürümünü içerir. Eski veya silinen dosyala sürümleri hariç tutulur.",
index 222d882..7ba7aad 100644 (file)
        "copyrightpage": "{{ns:project}}:Mualliflik huquqlari",
        "currentevents": "Joriy hodisalar",
        "currentevents-url": "Project:Joriy hodisalar",
-       "disclaimers": "Ogohlantirishlar",
-       "disclaimerpage": "Project:Umumiy ogohlantirish",
+       "disclaimers": "Masʼuliyatdan voz kechish",
+       "disclaimerpage": "Project:Masʼuliyatdan voz kechish",
        "edithelp": "Tahrirlash yordami",
        "mainpage": "Bosh sahifa",
        "mainpage-description": "Bosh sahifa",
        "editingcomment": "$1 tahrirlanmoqda (yangi mavzu)",
        "editconflict": "Tahrirlash toʻqnashuvi: $1",
        "yourtext": "Sizning matningiz",
+       "editingold": "<strong>Ogohlantirish: Siz sahifaning eski nusxasini tahrirlayapsiz.</strong>\nUni shunday holicha saqlasangiz, keyingi nusxalardagi oʻzgarishlar yoʻqotiladi.",
        "yourdiff": "Farqlar",
        "copyrightwarning": "Iltimos, {{SITENAME}}ga yuklangan har qanday axborot $2 ostida tarqatilishiga diqqat qiling (batafsil ma'lumot uchun $1ni ko'ring).\nAgar yozganlaringiz keyinchalik tahrir qilinishi va qayta tarqatilishiga rozi bo'lmasangiz, u holda bu yerga yozmang.<br />\nSiz shuningdek bu yozganlaringiz sizniki yoki erkin litsenziya ostida ekanligini va'da qilmoqdasiz.\n'''MUALLIFLIK HUQUQLARI BILAN HIMOYALANGAN ISHLARNI ZINHOR BERUXSAT YUBORMANG!'''",
        "copyrightwarning2": "Iltimos, shuni esda tutingki, {{SITENAME}} sahifalaridagi barcha matnlar boshqa foydalanuvchilar tomonidan tahrirlanishi, almashtirilishi yoki o'chirilishi mumkin. Agar siz yozgan ma'lumotlaringizni bunday tartibda tahrirlanishiga rozi bo'lmasangiz, unda uni bu yerga joylashtirmang.<br />\nBundan tashqari, siz ushbu ma'lumotlarni o'zingiz yozgan bo'lishingiz yoki ruxsat berilgan internet manzilidan yoki shu kabi erkin resursdan nusxa olgan bo'lishingiz lozim (Qo'shimcha ma'lumotlar uchun $1 sahifasiga murojaat qiling).\n'''MUALLIFLIK HUQUQI QO'YILGAN ISHLARNI RUXSATSIZ BU YERGA JOYLASHTIRMANG!'''",
index f88fb7e..786119e 100644 (file)
        "import-logentry-interwiki": "אריבערגעוויקיט $1",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|רעוויזיע|רעוויזיעס}} אימפארטירט פֿון $2",
        "javascripttest": "JavaScript טעסט",
-       "javascripttest-title": "דורכפירנדיק $1 בדיקות",
        "javascripttest-pagetext-noframework": " דער בלאט איז רעזערווירט פאר JavaScript. פרואוון.",
        "javascripttest-pagetext-unknownframework": "אומבאקאנטער טעסטן גערעם \"$1\".",
        "javascripttest-pagetext-frameworks": "ביטע קלויבט איינעם פון די פאלגנדע טעסטן־גערעם: $1",
        "javascripttest-pagetext-skins": "קלויבט א באניצער־אייבערפלאך מיט וואס דורכצופירן די בדיקות:",
        "javascripttest-qunit-intro": "זעט [$1 דאקומענטאציע פאר טעסטן] בײַ mediawiki.org.",
-       "javascripttest-qunit-heading": "מעדיעוויקי JavaScript QUnit קאנטראל־פראגראם",
        "tooltip-pt-userpage": "אייער באניצער בלאט",
        "tooltip-pt-anonuserpage": "באַניצער בלאַט פון דעם IP אַדרעס",
        "tooltip-pt-mytalk": "אייער שמועס בלאט",
index 69cb0bc..b8dc5e7 100644 (file)
        "import-logentry-interwiki": "跨wiki导入页面$1",
        "import-logentry-interwiki-detail": "来自$2的$1个{{PLURAL:$1|版本}}已导入",
        "javascripttest": "JavaScript测试",
-       "javascripttest-title": "运行$1测试",
        "javascripttest-pagetext-noframework": "本页面被保留进行JavaScript测试。",
        "javascripttest-pagetext-unknownframework": "未知的框架“$1”。",
+       "javascripttest-pagetext-unknownaction": "未知操作“$1”。",
        "javascripttest-pagetext-frameworks": "请选择以下的框架之一:$1",
        "javascripttest-pagetext-skins": "选择外观来运行测试:",
        "javascripttest-qunit-intro": "请见mediawiki.org的[$1 测试说明文件]。",
-       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit 测试套件",
        "tooltip-pt-userpage": "你的用户页面",
        "tooltip-pt-anonuserpage": "你用于编辑的IP地址的用户页面",
        "tooltip-pt-mytalk": "你的讨论页面",
        "version-ext-colheader-description": "说明",
        "version-ext-colheader-credits": "作者",
        "version-license-title": "$1的许可协议",
-       "version-license-not-found": "没æ\9c\89æ\89¾å\88°ä¸\8eæ­¤æ\8b\93å±\95ç\9b¸å\85³ç\9a\84授权信息。",
+       "version-license-not-found": "æ\9cªæ\89¾å\88°æ­¤æ\89©å±\95ç\9b¸å\85³ç\9a\84详ç»\86授权信息。",
        "version-credits-title": "$1贡献者名单",
-       "version-credits-not-found": "没æ\9c\89æ\89¾å\88°ä¸\8eæ­¤æ\8b\93å±\95ç\9b¸å\85³ç\9a\84ä¿¡ç\94¨信息。",
+       "version-credits-not-found": "æ\9cªæ\89¾å\88°æ­¤æ\89©å±\95ç\9b¸å\85³ç\9a\84详ç»\86å\88¶ä½\9c人信息。",
        "version-poweredby-credits": "本Wiki由'''[https://www.mediawiki.org/ MediaWiki]'''驱动,版权所有 © 2001-$1 $2。",
        "version-poweredby-others": "其他",
        "version-poweredby-translators": "translatewiki.net上的翻译者",
index 445b844..25a56ac 100644 (file)
@@ -62,7 +62,7 @@
                ]
        },
        "tog-underline": "底線標示連結:",
-       "tog-hideminor": "隱藏近期變更以來的小編輯",
+       "tog-hideminor": "在近期變更隱藏小編輯",
        "tog-hidepatrolled": "隱藏近期變更中巡查過的編輯",
        "tog-newpageshidepatrolled": "隱藏新頁面清單中巡查過的頁面",
        "tog-extendwatchlist": "展開監視清單顯示包含最近以外的所有變更",
        "pool-queuefull": "程序序列已滿",
        "pool-errorunknown": "不明錯誤",
        "pool-servererror": "無法使用程序計數服務 ($1)。",
+       "poolcounter-usage-error": "用法錯誤:$1",
        "aboutsite": "關於 {{SITENAME}}",
        "aboutpage": "Project:About",
        "copyright": "除非額外說明,否則本站內容均使用 $1 授權條款。",
        "cascadeprotectedwarning": "<strong>警告:</strong>本頁已經被保護,只有擁有管理員權限的使用者才可編輯,此頁面被下列頁面引用因此連鎖保護:",
        "titleprotectedwarning": "<strong>警告:本頁面已被保護,需要 [[Special:ListGroupRights|特殊權限]] 方可建立。</strong>\n以下提供最近的日誌以便參考:",
        "templatesused": "此頁面使用了以下{{PLURAL:$1|樣板}}:",
-       "templatesusedpreview": "此預覽使用了以下 {{PLURAL:$1|模板}} :",
+       "templatesusedpreview": "此預覽使用了以下{{PLURAL:$1|模板}}:",
        "templatesusedsection": "此頁面使用了以下 {{PLURAL:$1|模板}} :",
        "template-protected": "(受保護)",
        "template-semiprotected": "(受半保護)",
        "istemplate": "引用",
        "isimage": "檔案連結",
        "whatlinkshere-prev": "前 $1 筆",
-       "whatlinkshere-next": "後 $1 筆",
+       "whatlinkshere-next": "{{PLURAL:$1|後筆|後 $1 筆}}",
        "whatlinkshere-links": "← 連結",
        "whatlinkshere-hideredirs": "$1 重新導向頁面",
        "whatlinkshere-hidetrans": "$1 引用",
        "import-logentry-interwiki": "Transwiki 頁面 $1",
        "import-logentry-interwiki-detail": "已從 $2 匯入 $1 筆{{PLURAL:$1|修訂}}",
        "javascripttest": "JavaScript 測試",
-       "javascripttest-title": "執行 $1 測試。",
        "javascripttest-pagetext-noframework": "此頁面保留用來作為 JavaScript 測試使用。",
        "javascripttest-pagetext-unknownframework": "不明的測試 Framework \"$1\"。",
+       "javascripttest-pagetext-unknownaction": "未知操作「$1」。",
        "javascripttest-pagetext-frameworks": "請選擇下列一種測試 Framework:$1",
        "javascripttest-pagetext-skins": "選擇執行測試的外觀:",
        "javascripttest-qunit-intro": "請參考 mediawiki.org 的 [$1 測試說明文件]。",
-       "javascripttest-qunit-heading": "MediaWiki JavaScript QUnit 測試工具",
        "tooltip-pt-userpage": "您的使用者頁面",
        "tooltip-pt-anonuserpage": "您編輯使用的 IP 位址所對應的使用者頁面",
        "tooltip-pt-mytalk": "您的對話頁面",
        "version-entrypoints-header-url": "URL",
        "version-entrypoints-articlepath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgArticlePath 文章路徑]",
        "version-entrypoints-scriptpath": "[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgScriptPath Script 路徑]",
+       "version-libraries": "已安裝的庫",
+       "version-libraries-library": "庫",
        "version-libraries-version": "版本",
        "redirect": "重新導向至檔案、使用者、頁面或修訂 ID",
        "redirect-legend": "重新導向至檔案或頁面",
        "compare-revision-not-exists": "您所指定的修訂不存在。",
        "dberr-problems": "抱歉!這個網站出現了一些技術上的問題。",
        "dberr-again": "嘗試等候數分鐘後,然後再試。",
-       "dberr-info": "(無法連線資料庫伺服器:$1)",
-       "dberr-info-hidden": "(無法連線資料庫伺服器)",
+       "dberr-info": "(無法連接資料庫:$1)",
+       "dberr-info-hidden": "(無法連接資料庫)",
        "dberr-usegoogle": "您可以嘗試在此期間使用 Google 搜尋。",
        "dberr-outofdate": "注意,它們用來建立索引的內容可能不是最新的。",
        "dberr-cachederror": "這是請求面頁面的快取複本,可能不是最新的。",
index 8b23909..f66cd5a 100644 (file)
--- a/load.php
+++ b/load.php
@@ -31,7 +31,6 @@ if ( !function_exists( 'version_compare' ) || version_compare( PHP_VERSION, '5.3
 
 require __DIR__ . '/includes/WebStart.php';
 
-wfProfileIn( 'load.php' );
 
 // URL safety checks
 if ( !$wgRequest->checkUrlExtension() ) {
@@ -44,7 +43,6 @@ $configFactory = ConfigFactory::getDefaultInstance();
 $resourceLoader = new ResourceLoader( $configFactory->makeConfig( 'main' ) );
 $resourceLoader->respond( new ResourceLoaderContext( $resourceLoader, $wgRequest ) );
 
-wfProfileOut( 'load.php' );
 wfLogProfilingData();
 
 // Shut down the database.
index 2f8b7d2..4b07d2f 100644 (file)
@@ -1073,7 +1073,7 @@ abstract class Maintenance {
         *
         * @return DatabaseBase
         */
-       protected function &getDB( $db, $groups = array(), $wiki = false ) {
+       protected function getDB( $db, $groups = array(), $wiki = false ) {
                if ( is_null( $this->mDb ) ) {
                        return wfGetDB( $db, $groups, $wiki );
                } else {
@@ -1086,7 +1086,7 @@ abstract class Maintenance {
         *
         * @param DatabaseBase $db Database object to be used
         */
-       public function setDB( &$db ) {
+       public function setDB( $db ) {
                $this->mDb = $db;
        }
 
@@ -1094,7 +1094,7 @@ abstract class Maintenance {
         * Lock the search index
         * @param DatabaseBase &$db
         */
-       private function lockSearchindex( &$db ) {
+       private function lockSearchindex( $db ) {
                $write = array( 'searchindex' );
                $read = array( 'page', 'revision', 'text', 'interwiki', 'l10n_cache', 'user' );
                $db->lockTables( $read, $write, __CLASS__ . '::' . __METHOD__ );
@@ -1104,7 +1104,7 @@ abstract class Maintenance {
         * Unlock the tables
         * @param DatabaseBase &$db
         */
-       private function unlockSearchindex( &$db ) {
+       private function unlockSearchindex( $db ) {
                $db->unlockTables( __CLASS__ . '::' . __METHOD__ );
        }
 
@@ -1113,7 +1113,7 @@ abstract class Maintenance {
         * Since the lock is low-priority, queued reads will be able to complete
         * @param DatabaseBase &$db
         */
-       private function relockSearchindex( &$db ) {
+       private function relockSearchindex( $db ) {
                $this->unlockSearchindex( $db );
                $this->lockSearchindex( $db );
        }
diff --git a/maintenance/archives/patch-drop-page_counter.sql b/maintenance/archives/patch-drop-page_counter.sql
new file mode 100644 (file)
index 0000000..1d8e701
--- /dev/null
@@ -0,0 +1,2 @@
+-- field is deprecated and no longer updated as of 1.25
+ALTER TABLE /*_*/page DROP COLUMN page_counter;
diff --git a/maintenance/archives/patch-drop-ss_total_views.sql b/maintenance/archives/patch-drop-ss_total_views.sql
new file mode 100644 (file)
index 0000000..0059193
--- /dev/null
@@ -0,0 +1,2 @@
+-- field is deprecated and no longer updated as of 1.24
+ALTER TABLE /*_*/site_stats DROP COLUMN ss_total_views;
\ No newline at end of file
diff --git a/maintenance/convertExtensionToRegistration.php b/maintenance/convertExtensionToRegistration.php
new file mode 100644 (file)
index 0000000..cbdc1ba
--- /dev/null
@@ -0,0 +1,113 @@
+<?php
+
+require_once __DIR__ . '/Maintenance.php';
+
+class ConvertExtensionToRegistration extends Maintenance {
+
+       protected $custom = array(
+               'MessagesDirs' => 'removeAbsolutePath',
+               'ExtensionMessagesFiles' => 'removeAbsolutePath',
+               'AutoloadClasses' => 'removeAbsolutePath',
+               'ExtensionCredits' => 'handleCredits',
+               'ResourceModules' => 'handleResourceModules',
+               'Hooks' => 'handleHooks',
+               'ExtensionFunctions' => 'handleExtensionFunctions',
+       );
+
+       private $json, $dir;
+
+       public function __construct() {
+               parent::__construct();
+               $this->mDescription = 'Converts extension entry points to the new JSON registration format';
+       }
+
+       public function execute() {
+               require $this->getArg( 0 );
+               // Try not to create any local variables before this line
+               $vars = get_defined_vars();
+               unset( $vars['this'] );
+               $this->dir = dirname( realpath( $this->getArg( 0 ) ) );
+               $this->json = array();
+               $processor = new ReflectionClass( 'ExtensionProcessor' );
+               $settings = $processor->getProperty( 'globalSettings' );
+               $settings->setAccessible( true );
+               $globalSettings = $settings->getValue();
+               foreach ( $vars as $name => $value ) {
+                       $realName = substr( $name, 2 ); // Strip 'wg'
+                       if ( isset( $this->custom[$realName] ) ) {
+                               call_user_func_array( array( $this, $this->custom[$realName] ), array( $realName, $value ) );
+                       } elseif ( in_array( $realName, $globalSettings ) ) {
+                               $this->json[$realName] = $value;
+                       } elseif ( strpos( $name, 'wg' ) === 0 ) {
+                               // Most likely a config setting
+                               $this->json['config'][$realName] = $value;
+                       }
+               }
+
+               $fname = "{$this->dir}/extension.json";
+               $prettyJSON = FormatJson::encode( $this->json, "\t" );
+               file_put_contents( $fname, $prettyJSON . "\n" );
+               $this->output( "Wrote output to $fname.\n" );
+       }
+
+       protected function handleExtensionFunctions( $realName, $value ) {
+               foreach ( $value as $func ) {
+                       if ( $func instanceof Closure ) {
+                               $this->error( "Error: Closures cannot be converted to JSON. Please move your extension function somewhere else.", 1 );
+                       }
+               }
+
+               $this->json[$realName] = $value;
+       }
+
+       private function stripPath( $val, $dir ) {
+               if ( strpos( $val, $dir ) === 0 ) {
+                       // +1 is for the trailing / that won't be in $this->dir
+                       $val = substr( $val, strlen( $dir ) + 1 );
+               }
+
+               return $val;
+       }
+
+       protected function removeAbsolutePath( $realName, $value ) {
+               $out = array();
+               foreach ( $value as $key => $val ) {
+                       $out[$key] = $this->stripPath( $val, $this->dir );
+               }
+               $this->json[$realName] = $out;
+       }
+
+       protected function handleCredits( $realName, $value) {
+               $keys = array_keys( $value );
+               $this->json['type'] = $keys[0];
+               $values = array_values( $value );
+               foreach ( $values[0][0] as $name => $val ) {
+                       if ( $name !== 'path' ) {
+                               $this->json[$name] = $val;
+                       }
+               }
+       }
+
+       public function handleHooks( $realName, $value ) {
+               foreach ( $value as $hookName => $handlers ) {
+                       foreach ( $handlers as $func ) {
+                               if ( $func instanceof Closure ) {
+                                       $this->error( "Error: Closures cannot be converted to JSON. Please move the handler for $hookName somewhere else.", 1 );
+                               }
+                       }
+               }
+               $this->json[$realName] = $value;
+       }
+
+       protected function handleResourceModules( $realName, $value ) {
+               foreach ( $value as $name => $data ) {
+                       if ( isset( $data['localBasePath'] ) ) {
+                               $data['localBasePath'] = $this->stripPath( $data['localBasePath'], $this->dir );
+                       }
+                       $this->json[$realName][$name] = $data;
+               }
+       }
+}
+
+$maintClass = 'ConvertExtensionToRegistration';
+require_once RUN_MAINTENANCE_IF_MAIN;
index c6281fd..dd27c8c 100644 (file)
@@ -1811,7 +1811,6 @@ historysubmit
 historywarning
 hit
 hitcount
-hitcounter
 hits
 hlist
 hmac
index e4380a7..c93a971 100644 (file)
@@ -68,6 +68,7 @@ if ( file_exists( "$IP/StartProfiler.php" ) ) {
 // Some other requires
 require_once "$IP/includes/Defines.php";
 require_once "$IP/includes/DefaultSettings.php";
+require_once "$IP/includes/GlobalFunctions.php";
 
 # Load composer's autoloader if present
 if ( is_readable( "$IP/vendor/autoload.php" ) ) {
@@ -113,7 +114,7 @@ try {
        $factory = wfGetLBFactory();
        $factory->commitMasterChanges();
        $factory->shutdown();
-} catch ( MWException $mwe ) {
+} catch ( Exception $mwe ) {
        echo $mwe->getText();
        exit( 1 );
 }
index 25ecc09..e20c477 100644 (file)
@@ -49,9 +49,6 @@ if ( isset( $options['d'] ) ) {
                        $lb->setServerInfo( $i, $server );
                }
        }
-       if ( $d > 2 ) {
-               $wgDebugFunctionEntry = true;
-       }
 }
 
 $__useReadline = function_exists( 'readline_add_history' )
index ec6e122..bd9f9af 100644 (file)
@@ -29,6 +29,6 @@ $cli = new CheckLanguageCLI( $options );
 
 try {
        $cli->execute();
-} catch ( MWException $e ) {
+} catch ( Exception $e ) {
        print 'Error: ' . $e->getMessage() . "\n";
 }
index b9cd715..5b09ffd 100644 (file)
@@ -111,7 +111,6 @@ CREATE TABLE /*_*/page (
    page_namespace INT          NOT NULL,
    page_title     NVARCHAR(255)  NOT NULL,
    page_restrictions NVARCHAR(255) NOT NULL,
-   page_counter BIGINT            NOT NULL DEFAULT 0,
    page_is_redirect BIT           NOT NULL DEFAULT 0,
    page_is_new BIT                NOT NULL DEFAULT 0,
    page_random real     NOT NULL DEFAULT RAND(),
@@ -422,9 +421,6 @@ CREATE TABLE /*_*/site_stats (
   -- The single row should contain 1 here.
   ss_row_id int NOT NULL,
 
-  -- Total number of page views, if hit counters are enabled.
-  ss_total_views bigint default 0,
-
   -- Total number of edits performed.
   ss_total_edits bigint default 0,
 
@@ -452,18 +448,6 @@ CREATE TABLE /*_*/site_stats (
 CREATE UNIQUE INDEX /*i*/ss_row_id ON /*_*/site_stats (ss_row_id);
 
 
---
--- Stores an ID for every time any article is visited;
--- depending on $wgHitcounterUpdateFreq, it is
--- periodically cleared and the page_counter column
--- in the page table updated for all the articles
--- that have been visited.)
---
-CREATE TABLE /*_*/hitcounter (
-  hc_id int NOT NULL
-);
-
-
 --
 -- The internet is full of jerks, alas. Sometimes it's handy
 -- to block a vandal or troll account.
index 36be16e..12f6518 100644 (file)
@@ -69,7 +69,6 @@ CREATE TABLE &mw_prefix.page (
   page_namespace     NUMBER       DEFAULT 0 NOT NULL,
   page_title         VARCHAR2(255)           NOT NULL,
   page_restrictions  VARCHAR2(255),
-  page_counter       NUMBER         DEFAULT 0 NOT NULL,
   page_is_redirect   CHAR(1)           DEFAULT '0' NOT NULL,
   page_is_new        CHAR(1)           DEFAULT '0' NOT NULL,
   page_random        NUMBER(15,14) NOT NULL,
@@ -247,7 +246,6 @@ CREATE UNIQUE INDEX &mw_prefix.iwlinks_ui02 ON &mw_prefix.iwlinks (iwl_prefix, i
 
 CREATE TABLE &mw_prefix.site_stats (
   ss_row_id         NUMBER  NOT NULL ,
-  ss_total_views    NUMBER            DEFAULT 0,
   ss_total_edits    NUMBER            DEFAULT 0,
   ss_good_articles  NUMBER            DEFAULT 0,
   ss_total_pages    NUMBER            DEFAULT -1,
@@ -257,10 +255,6 @@ CREATE TABLE &mw_prefix.site_stats (
 );
 CREATE UNIQUE INDEX &mw_prefix.site_stats_u01 ON &mw_prefix.site_stats (ss_row_id);
 
-CREATE TABLE &mw_prefix.hitcounter (
-  hc_id  NUMBER  NOT NULL
-);
-
 CREATE SEQUENCE ipblocks_ipb_id_seq;
 CREATE TABLE &mw_prefix.ipblocks (
   ipb_id                NUMBER      NOT NULL,
index f06b56b..b401db0 100644 (file)
@@ -153,7 +153,7 @@ class PopulateRevisionSha1 extends LoggedUpdateMaintenance {
                                ? Revision::newFromArchiveRow( $row )
                                : new Revision( $row );
                        $text = $rev->getSerializedData();
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        $this->output( "Data of revision with {$idCol}={$row->$idCol} unavailable!\n" );
 
                        return false; // bug 22624?
@@ -182,7 +182,7 @@ class PopulateRevisionSha1 extends LoggedUpdateMaintenance {
                $db = $this->getDB( DB_MASTER );
                try {
                        $rev = Revision::newFromArchiveRow( $row );
-               } catch ( MWException $e ) {
+               } catch ( Exception $e ) {
                        $this->output( "Text of revision with timestamp {$row->ar_timestamp} unavailable!\n" );
 
                        return false; // bug 22624?
index 53aeb14..bb08237 100755 (executable)
@@ -395,7 +395,6 @@ ss_active_users  bigint INTEGER
 ss_good_articles bigint INTEGER
 ss_total_edits   bigint INTEGER
 ss_total_pages   bigint INTEGER
-ss_total_views   bigint INTEGER
 ss_users         bigint INTEGER
 
 ## True IP - keep an eye on these, coders tend to make textual assumptions
index 400050e..5391bd9 100644 (file)
@@ -81,7 +81,6 @@ CREATE TABLE page (
   page_namespace     SMALLINT       NOT NULL,
   page_title         TEXT           NOT NULL,
   page_restrictions  TEXT,
-  page_counter       BIGINT         NOT NULL  DEFAULT 0,
   page_is_redirect   SMALLINT       NOT NULL  DEFAULT 0,
   page_is_new        SMALLINT       NOT NULL  DEFAULT 0,
   page_random        NUMERIC(15,14) NOT NULL  DEFAULT RANDOM(),
@@ -262,7 +261,6 @@ CREATE INDEX langlinks_lang_title    ON langlinks (ll_lang,ll_title);
 
 CREATE TABLE site_stats (
   ss_row_id         INTEGER  NOT NULL  UNIQUE,
-  ss_total_views    INTEGER            DEFAULT 0,
   ss_total_edits    INTEGER            DEFAULT 0,
   ss_good_articles  INTEGER            DEFAULT 0,
   ss_total_pages    INTEGER            DEFAULT -1,
@@ -272,10 +270,6 @@ CREATE TABLE site_stats (
   ss_images         INTEGER            DEFAULT 0
 );
 
-CREATE TABLE hitcounter (
-  hc_id  BIGINT  NOT NULL
-);
-
 
 CREATE SEQUENCE ipblocks_ipb_id_seq;
 CREATE TABLE ipblocks (
index cb55f0f..e1710c1 100644 (file)
@@ -64,7 +64,7 @@ class PPFuzzTester {
                                self::$currentTest = new PPFuzzTest( $this );
                                self::$currentTest->execute();
                                $passed = 'passed';
-                       } catch ( MWException $e ) {
+                       } catch ( Exception $e ) {
                                $testReport = self::$currentTest->getReport();
                                $exceptionReport = $e->getText();
                                $hash = md5( $testReport );
index 93aacde..88d9f87 100755 (executable)
@@ -15,6 +15,7 @@ NPM_DIR=$(mktemp -d 2>/dev/null || mktemp -d -t 'update-oojs-ui') # e.g. /tmp/up
 
 # Prepare working tree
 cd "$REPO_DIR" &&
+git reset composer.json && git checkout composer.json &&
 git reset $TARGET_DIR && git checkout $TARGET_DIR && git fetch origin &&
 git checkout -B upstream-oojs-ui origin/master || exit 1
 
@@ -58,5 +59,8 @@ Release notes:
 END
 )
 
+# Update composer.json as well
+composer require oojs/oojs-ui $OOJSUI_VERSION --no-update
+
 # Stage deletion, modification and creation of files. Then commit.
-git add --update $TARGET_DIR && git add $TARGET_DIR && git commit -m "$COMMITMSG" || exit 1
+git add --update $TARGET_DIR && git add $TARGET_DIR && git add composer.json && git commit -m "$COMMITMSG" || exit 1
index 954c85d..f322a03 100644 (file)
@@ -69,7 +69,6 @@ CREATE TABLE /*_*/page_tmp (
   page_namespace int NOT NULL,
   page_title varchar(255) binary NOT NULL,
   page_restrictions tinyblob NOT NULL,
-  page_counter bigint unsigned NOT NULL default 0,
   page_is_redirect tinyint unsigned NOT NULL default 0,
   page_is_new tinyint unsigned NOT NULL default 0,
   page_random real unsigned NOT NULL,
@@ -164,7 +163,6 @@ CREATE INDEX /*i*/ll_lang_title ON /*_*/langlinks_tmp (ll_lang, ll_title);
 
 CREATE TABLE /*_*/site_stats_tmp (
   ss_row_id int unsigned NOT NULL,
-  ss_total_views bigint unsigned default 0,
   ss_total_edits bigint unsigned default 0,
   ss_good_articles bigint unsigned default 0,
   ss_total_pages bigint default '-1',
diff --git a/maintenance/sqlite/archives/patch-drop-page_counter.sql b/maintenance/sqlite/archives/patch-drop-page_counter.sql
new file mode 100644 (file)
index 0000000..ac8151d
--- /dev/null
@@ -0,0 +1,31 @@
+-- field is deprecated and no longer updated as of 1.25
+CREATE TABLE /*_*/page_tmp (
+  page_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  page_namespace int NOT NULL,
+  page_title varchar(255) binary NOT NULL,
+  page_restrictions tinyblob NOT NULL,
+  page_is_redirect tinyint unsigned NOT NULL default 0,
+  page_is_new tinyint unsigned NOT NULL default 0,
+  page_random real unsigned NOT NULL,
+  page_touched binary(14) NOT NULL default '',
+  page_links_updated varbinary(14) NULL default NULL,
+  page_latest int unsigned NOT NULL,
+  page_len int unsigned NOT NULL,
+  page_content_model varbinary(32) DEFAULT NULL,
+  page_lang varbinary(35) DEFAULT NULL
+) /*$wgDBTableOptions*/;
+
+INSERT INTO /*_*/page_tmp
+  SELECT page_id, page_namespace, page_title, page_restrictions, page_is_redirect,
+    page_is_new, page_random, page_touched, page_links_updated, page_latest, page_len,
+    page_content_model, page_lang
+  FROM /*_*/page;
+
+DROP TABLE /*_*/page;
+
+ALTER TABLE /*_*/page_tmp RENAME TO /*_*/page;
+
+CREATE UNIQUE INDEX /*i*/name_title ON /*_*/page (page_namespace,page_title);
+CREATE INDEX /*i*/page_random ON /*_*/page (page_random);
+CREATE INDEX /*i*/page_len ON /*_*/page (page_len);
+CREATE INDEX /*i*/page_redirect_namespace_len ON /*_*/page (page_is_redirect, page_namespace, page_len);
index 9951e17..3960663 100644 (file)
@@ -1,7 +1,6 @@
 -- field is deprecated and no longer updated as of 1.5
 CREATE TABLE /*_*/site_stats_tmp (
   ss_row_id int unsigned NOT NULL,
-  ss_total_views bigint unsigned default 0,
   ss_total_edits bigint unsigned default 0,
   ss_good_articles bigint unsigned default 0,
   ss_total_pages bigint default '-1',
@@ -11,7 +10,7 @@ CREATE TABLE /*_*/site_stats_tmp (
 ) /*$wgDBTableOptions*/;
 
 INSERT INTO /*_*/site_stats_tmp
-       SELECT ss_row_id, ss_total_views, ss_total_edits, ss_good_articles,
+       SELECT ss_row_id, ss_total_edits, ss_good_articles,
                ss_total_pages, ss_users, ss_active_users, ss_images
                FROM /*_*/site_stats;
 
diff --git a/maintenance/sqlite/archives/patch-drop-ss_total_views.sql b/maintenance/sqlite/archives/patch-drop-ss_total_views.sql
new file mode 100644 (file)
index 0000000..ad80988
--- /dev/null
@@ -0,0 +1,21 @@
+-- field is deprecated and no longer updated as of 1.25
+CREATE TABLE /*_*/site_stats_tmp (
+  ss_row_id int unsigned NOT NULL,
+  ss_total_edits bigint unsigned default 0,
+  ss_good_articles bigint unsigned default 0,
+  ss_total_pages bigint default '-1',
+  ss_users bigint default '-1',
+  ss_active_users bigint default '-1',
+  ss_images int default 0
+) /*$wgDBTableOptions*/;
+
+INSERT INTO /*_*/site_stats_tmp
+  SELECT ss_row_id, ss_total_edits, ss_good_articles, ss_total_pages,
+    ss_users, ss_active_users, ss_images
+  FROM /*_*/site_stats;
+
+DROP TABLE /*_*/site_stats;
+
+ALTER TABLE /*_*/site_stats_tmp RENAME TO /*_*/site_stats;
+
+CREATE UNIQUE INDEX /*i*/ss_row_id ON /*_*/site_stats (ss_row_id);
index caf8ecc..112ac05 100644 (file)
@@ -241,9 +241,6 @@ CREATE TABLE /*_*/page (
   -- can move or edit the page.
   page_restrictions tinyblob NOT NULL,
 
-  -- Number of times this page has been viewed.
-  page_counter bigint unsigned NOT NULL default 0,
-
   -- 1 indicates the article is a redirect.
   page_is_redirect tinyint unsigned NOT NULL default 0,
 
@@ -704,9 +701,6 @@ CREATE TABLE /*_*/site_stats (
   -- The single row should contain 1 here.
   ss_row_id int unsigned NOT NULL,
 
-  -- Total number of page views, if hit counters are enabled.
-  ss_total_views bigint unsigned default 0,
-
   -- Total number of edits performed.
   ss_total_edits bigint unsigned default 0,
 
@@ -733,19 +727,6 @@ CREATE TABLE /*_*/site_stats (
 -- Pointless index to assuage developer superstitions
 CREATE UNIQUE INDEX /*i*/ss_row_id ON /*_*/site_stats (ss_row_id);
 
-
---
--- Stores an ID for every time any article is visited;
--- depending on $wgHitcounterUpdateFreq, it is
--- periodically cleared and the page_counter column
--- in the page table updated for all the articles
--- that have been visited.)
---
-CREATE TABLE /*_*/hitcounter (
-  hc_id int unsigned NOT NULL
-) ENGINE=MEMORY MAX_ROWS=25000;
-
-
 --
 -- The internet is full of jerks, alas. Sometimes it's handy
 -- to block a vandal or troll account.
diff --git a/maintenance/validateRegistrationFile.php b/maintenance/validateRegistrationFile.php
new file mode 100644 (file)
index 0000000..e764661
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+
+require_once __DIR__ . '/Maintenance.php';
+
+class ValidateRegistrationFile extends Maintenance {
+       public function __construct() {
+               parent::__construct();
+               $this->addArg( 'path', 'Path to extension.json/skin.json file.', true );
+       }
+       public function execute() {
+               if ( !class_exists( 'JsonSchema\Uri\UriRetriever' ) ) {
+                       $this->error( 'The JsonSchema library cannot be found, please install it through composer.', 1 );
+               }
+
+               $retriever = new JsonSchema\Uri\UriRetriever();
+               $schema = $retriever->retrieve('file://' . dirname( __DIR__ ) . '/docs/extension.schema.json' );
+               $path = $this->getArg( 0 );
+               $data = json_decode( file_get_contents( $path ) );
+               if ( !is_object( $data ) ) {
+                       $this->error( "$path is not a valid JSON file.", 1 );
+               }
+
+               $validator = new JsonSchema\Validator();
+               $validator->check( $data, $schema );
+               if ( $validator->isValid() ) {
+                       $this->output( "$path validates against the schema!\n" );
+               } else {
+                       foreach ( $validator->getErrors() as $error ) {
+                               $this->output( "[{$error['property']}] {$error['message']}\n" );
+                       }
+                       $this->error( "$path does not validate.", 1 );
+               }
+       }
+}
+
+$maintClass = 'ValidateRegistrationFile';
+require_once RUN_MAINTENANCE_IF_MAIN;
diff --git a/resources/lib/jquery.ui/themes/smoothness/PATCHES b/resources/lib/jquery.ui/themes/smoothness/PATCHES
new file mode 100644 (file)
index 0000000..53fbe1f
--- /dev/null
@@ -0,0 +1,3 @@
+jquery.ui.theme.css
+* Removed ".ui-widget-content a { color: #222222; }" and
+  ".ui-widget-header a { color: #222222; }" due to bug T85857.
index d170081..1d8b8a8 100644 (file)
@@ -18,9 +18,7 @@
 .ui-widget .ui-widget { font-size: 1em; }
 .ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
 .ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x; color: #222222; }
-.ui-widget-content a { color: #222222; }
 .ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x; color: #222222; font-weight: bold; }
-.ui-widget-header a { color: #222222; }
 
 /* Interaction states
 ----------------------------------*/
 
 /* Overlays */
 .ui-widget-overlay { background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); }
-.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
\ No newline at end of file
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
index 93026e3..385a1ce 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * QUnit 1.14.0
+ * QUnit 1.16.0
  * http://qunitjs.com/
  *
- * Copyright 2013 jQuery Foundation and other contributors
+ * Copyright 2006, 2014 jQuery Foundation and other contributors
  * Released under the MIT license
  * http://jquery.org/license
  *
- * Date: 2014-01-31T16:40Z
+ * Date: 2014-12-03T16:32Z
  */
 
 /** Font Family and Sizes */
 }
 
 #qunit-testrunner-toolbar {
-       padding: 0.5em 0 0.5em 2em;
+       padding: 0.5em 1em 0.5em 1em;
        color: #5E740B;
        background-color: #EEE;
        overflow: hidden;
 }
 
 #qunit-userAgent {
-       padding: 0.5em 0 0.5em 2.5em;
+       padding: 0.5em 1em 0.5em 1em;
        background-color: #2B81AF;
        color: #FFF;
        text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
 }
 
 #qunit-tests li {
-       padding: 0.4em 0.5em 0.4em 2.5em;
+       padding: 0.4em 1em 0.4em 1em;
        border-bottom: 1px solid #FFF;
        list-style-position: inside;
 }
 
+#qunit-tests > li {
+       display: none;
+}
+
+#qunit-tests li.pass, #qunit-tests li.running, #qunit-tests li.fail {
+       display: list-item;
+}
+
 #qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {
        display: none;
 }
        cursor: pointer;
 }
 
+#qunit-tests li.skipped strong {
+       cursor: default;
+}
+
 #qunit-tests li a {
        padding: 0.5em;
        color: #C2CCD1;
 
 #qunit-banner.qunit-fail                    { background-color: #EE5757; }
 
+/*** Skipped tests */
+
+#qunit-tests .skipped {
+       background-color: #EBECE9;
+}
+
+#qunit-tests .qunit-skipped-label {
+       background-color: #F4FF77;
+       display: inline-block;
+       font-style: normal;
+       color: #366097;
+       line-height: 1.8em;
+       padding: 0 0.5em;
+       margin: -0.4em 0.4em -0.4em 0;
+}
 
 /** Result */
 
 #qunit-testresult {
-       padding: 0.5em 0.5em 0.5em 2.5em;
+       padding: 0.5em 1em 0.5em 1em;
 
        color: #2B81AF;
        background-color: #D2E0E6;
index 0e279fd..82020d4 100644 (file)
@@ -1,38 +1,42 @@
 /*!
- * QUnit 1.14.0
+ * QUnit 1.16.0
  * http://qunitjs.com/
  *
- * Copyright 2013 jQuery Foundation and other contributors
+ * Copyright 2006, 2014 jQuery Foundation and other contributors
  * Released under the MIT license
  * http://jquery.org/license
  *
- * Date: 2014-01-31T16:40Z
+ * Date: 2014-12-03T16:32Z
  */
 
 (function( window ) {
 
 var QUnit,
-       assert,
        config,
        onErrorFnPrev,
-       testId = 0,
-       fileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\d+)+\)?/, "").replace(/.+\//, ""),
+       loggingCallbacks = {},
+       fileName = ( sourceFromStacktrace( 0 ) || "" ).replace( /(:\d+)+\)?/, "" ).replace( /.+\//, "" ),
        toString = Object.prototype.toString,
        hasOwn = Object.prototype.hasOwnProperty,
        // Keep a local reference to Date (GH-283)
        Date = window.Date,
+       now = Date.now || function() {
+               return new Date().getTime();
+       },
+       globalStartCalled = false,
+       runStarted = false,
        setTimeout = window.setTimeout,
        clearTimeout = window.clearTimeout,
        defined = {
-               document: typeof window.document !== "undefined",
-               setTimeout: typeof window.setTimeout !== "undefined",
+               document: window.document !== undefined,
+               setTimeout: window.setTimeout !== undefined,
                sessionStorage: (function() {
                        var x = "qunit-test-string";
                        try {
                                sessionStorage.setItem( x, x );
                                sessionStorage.removeItem( x );
                                return true;
-                       } catch( e ) {
+                       } catch ( e ) {
                                return false;
                        }
                }())
@@ -74,147 +78,18 @@ var QUnit,
         * @return {Object} New object with only the own properties (recursively).
         */
        objectValues = function( obj ) {
-               // Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.
-               /*jshint newcap: false */
                var key, val,
                        vals = QUnit.is( "array", obj ) ? [] : {};
                for ( key in obj ) {
                        if ( hasOwn.call( obj, key ) ) {
-                               val = obj[key];
-                               vals[key] = val === Object(val) ? objectValues(val) : val;
+                               val = obj[ key ];
+                               vals[ key ] = val === Object( val ) ? objectValues( val ) : val;
                        }
                }
                return vals;
        };
 
-
-// Root QUnit object.
-// `QUnit` initialized at top of scope
-QUnit = {
-
-       // call on start of module test to prepend name to all tests
-       module: function( name, testEnvironment ) {
-               config.currentModule = name;
-               config.currentModuleTestEnvironment = testEnvironment;
-               config.modules[name] = true;
-       },
-
-       asyncTest: function( testName, expected, callback ) {
-               if ( arguments.length === 2 ) {
-                       callback = expected;
-                       expected = null;
-               }
-
-               QUnit.test( testName, expected, callback, true );
-       },
-
-       test: function( testName, expected, callback, async ) {
-               var test,
-                       nameHtml = "<span class='test-name'>" + escapeText( testName ) + "</span>";
-
-               if ( arguments.length === 2 ) {
-                       callback = expected;
-                       expected = null;
-               }
-
-               if ( config.currentModule ) {
-                       nameHtml = "<span class='module-name'>" + escapeText( config.currentModule ) + "</span>: " + nameHtml;
-               }
-
-               test = new Test({
-                       nameHtml: nameHtml,
-                       testName: testName,
-                       expected: expected,
-                       async: async,
-                       callback: callback,
-                       module: config.currentModule,
-                       moduleTestEnvironment: config.currentModuleTestEnvironment,
-                       stack: sourceFromStacktrace( 2 )
-               });
-
-               if ( !validTest( test ) ) {
-                       return;
-               }
-
-               test.queue();
-       },
-
-       // Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don't slip through.
-       expect: function( asserts ) {
-               if (arguments.length === 1) {
-                       config.current.expected = asserts;
-               } else {
-                       return config.current.expected;
-               }
-       },
-
-       start: function( count ) {
-               // QUnit hasn't been initialized yet.
-               // Note: RequireJS (et al) may delay onLoad
-               if ( config.semaphore === undefined ) {
-                       QUnit.begin(function() {
-                               // This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first
-                               setTimeout(function() {
-                                       QUnit.start( count );
-                               });
-                       });
-                       return;
-               }
-
-               config.semaphore -= count || 1;
-               // don't start until equal number of stop-calls
-               if ( config.semaphore > 0 ) {
-                       return;
-               }
-               // ignore if start is called more often then stop
-               if ( config.semaphore < 0 ) {
-                       config.semaphore = 0;
-                       QUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) );
-                       return;
-               }
-               // A slight delay, to avoid any current callbacks
-               if ( defined.setTimeout ) {
-                       setTimeout(function() {
-                               if ( config.semaphore > 0 ) {
-                                       return;
-                               }
-                               if ( config.timeout ) {
-                                       clearTimeout( config.timeout );
-                               }
-
-                               config.blocking = false;
-                               process( true );
-                       }, 13);
-               } else {
-                       config.blocking = false;
-                       process( true );
-               }
-       },
-
-       stop: function( count ) {
-               config.semaphore += count || 1;
-               config.blocking = true;
-
-               if ( config.testTimeout && defined.setTimeout ) {
-                       clearTimeout( config.timeout );
-                       config.timeout = setTimeout(function() {
-                               QUnit.ok( false, "Test timed out" );
-                               config.semaphore = 1;
-                               QUnit.start();
-                       }, config.testTimeout );
-               }
-       }
-};
-
-// We use the prototype to distinguish between properties that should
-// be exposed as globals (and in exports) and those that shouldn't
-(function() {
-       function F() {}
-       F.prototype = QUnit;
-       QUnit = new F();
-       // Make F QUnit's constructor so that we can add to the prototype later
-       QUnit.constructor = F;
-}());
+QUnit = {};
 
 /**
  * Config object: Maintain internal state
@@ -248,31 +123,40 @@ config = {
        // add checkboxes that are persisted in the query-string
        // when enabled, the id is set to `true` as a `QUnit.config` property
        urlConfig: [
+               {
+                       id: "hidepassed",
+                       label: "Hide passed tests",
+                       tooltip: "Only show tests and assertions that fail. Stored as query-strings."
+               },
                {
                        id: "noglobals",
                        label: "Check for Globals",
-                       tooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings."
+                       tooltip: "Enabling this will test if any test introduces new properties on the " +
+                               "`window` object. Stored as query-strings."
                },
                {
                        id: "notrycatch",
                        label: "No try-catch",
-                       tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings."
+                       tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " +
+                               "exceptions in IE reasonable. Stored as query-strings."
                }
        ],
 
        // Set of all modules.
-       modules: {},
-
-       // logging callback queues
-       begin: [],
-       done: [],
-       log: [],
-       testStart: [],
-       testDone: [],
-       moduleStart: [],
-       moduleDone: []
+       modules: [],
+
+       // The first unnamed module
+       currentModule: {
+               name: "",
+               tests: []
+       },
+
+       callbacks: {}
 };
 
+// Push a loose unnamed module to the modules collection
+config.modules.push( config.currentModule );
+
 // Initialize more QUnit.config and QUnit.urlParams
 (function() {
        var i, current,
@@ -301,17 +185,13 @@ config = {
        // String search anywhere in moduleName+testName
        config.filter = urlParams.filter;
 
-       // Exact match of the module name
-       config.module = urlParams.module;
-
-       config.testNumber = [];
-       if ( urlParams.testNumber ) {
+       config.testId = [];
+       if ( urlParams.testId ) {
 
-               // Ensure that urlParams.testNumber is an array
-               urlParams.testNumber = [].concat( urlParams.testNumber );
-               for ( i = 0; i < urlParams.testNumber.length; i++ ) {
-                       current = urlParams.testNumber[ i ];
-                       config.testNumber.push( parseInt( current, 10 ) );
+               // Ensure that urlParams.testId is an array
+               urlParams.testId = [].concat( urlParams.testId );
+               for ( i = 0; i < urlParams.testId.length; i++ ) {
+                       config.testId.push( urlParams.testId[ i ] );
                }
        }
 
@@ -319,75 +199,132 @@ config = {
        QUnit.isLocal = location.protocol === "file:";
 }());
 
+// Root QUnit object.
+// `QUnit` initialized at top of scope
 extend( QUnit, {
 
-       config: config,
+       // call on start of module test to prepend name to all tests
+       module: function( name, testEnvironment ) {
+               var currentModule = {
+                       name: name,
+                       testEnvironment: testEnvironment,
+                       tests: []
+               };
 
-       // Initialize the configuration options
-       init: function() {
-               extend( config, {
-                       stats: { all: 0, bad: 0 },
-                       moduleStats: { all: 0, bad: 0 },
-                       started: +new Date(),
-                       updateRate: 1000,
-                       blocking: false,
-                       autostart: true,
-                       autorun: false,
-                       filter: "",
-                       queue: [],
-                       semaphore: 1
-               });
+               // DEPRECATED: handles setup/teardown functions,
+               // beforeEach and afterEach should be used instead
+               if ( testEnvironment && testEnvironment.setup ) {
+                       testEnvironment.beforeEach = testEnvironment.setup;
+                       delete testEnvironment.setup;
+               }
+               if ( testEnvironment && testEnvironment.teardown ) {
+                       testEnvironment.afterEach = testEnvironment.teardown;
+                       delete testEnvironment.teardown;
+               }
 
-               var tests, banner, result,
-                       qunit = id( "qunit" );
+               config.modules.push( currentModule );
+               config.currentModule = currentModule;
+       },
 
-               if ( qunit ) {
-                       qunit.innerHTML =
-                               "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
-                               "<h2 id='qunit-banner'></h2>" +
-                               "<div id='qunit-testrunner-toolbar'></div>" +
-                               "<h2 id='qunit-userAgent'></h2>" +
-                               "<ol id='qunit-tests'></ol>";
+       // DEPRECATED: QUnit.asyncTest() will be removed in QUnit 2.0.
+       asyncTest: function( testName, expected, callback ) {
+               if ( arguments.length === 2 ) {
+                       callback = expected;
+                       expected = null;
                }
 
-               tests = id( "qunit-tests" );
-               banner = id( "qunit-banner" );
-               result = id( "qunit-testresult" );
+               QUnit.test( testName, expected, callback, true );
+       },
 
-               if ( tests ) {
-                       tests.innerHTML = "";
-               }
+       test: function( testName, expected, callback, async ) {
+               var test;
 
-               if ( banner ) {
-                       banner.className = "";
+               if ( arguments.length === 2 ) {
+                       callback = expected;
+                       expected = null;
                }
 
-               if ( result ) {
-                       result.parentNode.removeChild( result );
-               }
+               test = new Test({
+                       testName: testName,
+                       expected: expected,
+                       async: async,
+                       callback: callback
+               });
+
+               test.queue();
+       },
+
+       skip: function( testName ) {
+               var test = new Test({
+                       testName: testName,
+                       skip: true
+               });
+
+               test.queue();
+       },
+
+       // DEPRECATED: The functionality of QUnit.start() will be altered in QUnit 2.0.
+       // In QUnit 2.0, invoking it will ONLY affect the `QUnit.config.autostart` blocking behavior.
+       start: function( count ) {
+               var globalStartAlreadyCalled = globalStartCalled;
+
+               if ( !config.current ) {
+                       globalStartCalled = true;
+
+                       if ( runStarted ) {
+                               throw new Error( "Called start() outside of a test context while already started" );
+                       } else if ( globalStartAlreadyCalled || count > 1 ) {
+                               throw new Error( "Called start() outside of a test context too many times" );
+                       } else if ( config.autostart ) {
+                               throw new Error( "Called start() outside of a test context when " +
+                                       "QUnit.config.autostart was true" );
+                       } else if ( !config.pageLoaded ) {
+
+                               // The page isn't completely loaded yet, so bail out and let `QUnit.load` handle it
+                               config.autostart = true;
+                               return;
+                       }
+               } else {
+
+                       // If a test is running, adjust its semaphore
+                       config.current.semaphore -= count || 1;
+
+                       // Don't start until equal number of stop-calls
+                       if ( config.current.semaphore > 0 ) {
+                               return;
+                       }
 
-               if ( tests ) {
-                       result = document.createElement( "p" );
-                       result.id = "qunit-testresult";
-                       result.className = "result";
-                       tests.parentNode.insertBefore( result, tests );
-                       result.innerHTML = "Running...<br/>&nbsp;";
+                       // throw an Error if start is called more often than stop
+                       if ( config.current.semaphore < 0 ) {
+                               config.current.semaphore = 0;
+
+                               QUnit.pushFailure(
+                                       "Called start() while already started (test's semaphore was 0 already)",
+                                       sourceFromStacktrace( 2 )
+                               );
+                               return;
+                       }
                }
+
+               resumeProcessing();
        },
 
-       // Resets the test setup. Useful for tests that modify the DOM.
-       /*
-       DEPRECATED: Use multiple tests instead of resetting inside a test.
-       Use testStart or testDone for custom cleanup.
-       This method will throw an error in 2.0, and will be removed in 2.1
-       */
-       reset: function() {
-               var fixture = id( "qunit-fixture" );
-               if ( fixture ) {
-                       fixture.innerHTML = config.fixture;
+       // DEPRECATED: QUnit.stop() will be removed in QUnit 2.0.
+       stop: function( count ) {
+
+               // If there isn't a test running, don't allow QUnit.stop() to be called
+               if ( !config.current ) {
+                       throw new Error( "Called stop() outside of a test context" );
                }
+
+               // If a test is running, adjust its semaphore
+               config.current.semaphore += count || 1;
+
+               pauseProcessing();
        },
 
+       config: config,
+
        // Safe object type checking
        is: function( type, obj ) {
                return QUnit.objectType( obj ) === type;
@@ -403,12 +340,12 @@ extend( QUnit, {
                        return "null";
                }
 
-               var match = toString.call( obj ).match(/^\[object\s(.*)\]$/),
-                       type = match && match[1] || "";
+               var match = toString.call( obj ).match( /^\[object\s(.*)\]$/ ),
+                       type = match && match[ 1 ] || "";
 
                switch ( type ) {
                        case "Number":
-                               if ( isNaN(obj) ) {
+                               if ( isNaN( obj ) ) {
                                        return "nan";
                                }
                                return "number";
@@ -426,517 +363,161 @@ extend( QUnit, {
                return undefined;
        },
 
-       push: function( result, actual, expected, message ) {
-               if ( !config.current ) {
-                       throw new Error( "assertion outside test context, was " + sourceFromStacktrace() );
-               }
-
-               var output, source,
-                       details = {
-                               module: config.current.module,
-                               name: config.current.testName,
-                               result: result,
-                               message: message,
-                               actual: actual,
-                               expected: expected
-                       };
-
-               message = escapeText( message ) || ( result ? "okay" : "failed" );
-               message = "<span class='test-message'>" + message + "</span>";
-               output = message;
-
-               if ( !result ) {
-                       expected = escapeText( QUnit.jsDump.parse(expected) );
-                       actual = escapeText( QUnit.jsDump.parse(actual) );
-                       output += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + expected + "</pre></td></tr>";
-
-                       if ( actual !== expected ) {
-                               output += "<tr class='test-actual'><th>Result: </th><td><pre>" + actual + "</pre></td></tr>";
-                               output += "<tr class='test-diff'><th>Diff: </th><td><pre>" + QUnit.diff( expected, actual ) + "</pre></td></tr>";
-                       }
-
-                       source = sourceFromStacktrace();
+       url: function( params ) {
+               params = extend( extend( {}, QUnit.urlParams ), params );
+               var key,
+                       querystring = "?";
 
-                       if ( source ) {
-                               details.source = source;
-                               output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
+               for ( key in params ) {
+                       if ( hasOwn.call( params, key ) ) {
+                               querystring += encodeURIComponent( key );
+                               if ( params[ key ] !== true ) {
+                                       querystring += "=" + encodeURIComponent( params[ key ] );
+                               }
+                               querystring += "&";
                        }
-
-                       output += "</table>";
                }
-
-               runLoggingCallbacks( "log", QUnit, details );
-
-               config.current.assertions.push({
-                       result: !!result,
-                       message: output
-               });
+               return location.protocol + "//" + location.host +
+                       location.pathname + querystring.slice( 0, -1 );
        },
 
-       pushFailure: function( message, source, actual ) {
-               if ( !config.current ) {
-                       throw new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );
-               }
+       extend: extend,
 
-               var output,
-                       details = {
-                               module: config.current.module,
-                               name: config.current.testName,
-                               result: false,
-                               message: message
-                       };
+       load: function() {
+               config.pageLoaded = true;
 
-               message = escapeText( message ) || "error";
-               message = "<span class='test-message'>" + message + "</span>";
-               output = message;
+               // Initialize the configuration options
+               extend( config, {
+                       stats: { all: 0, bad: 0 },
+                       moduleStats: { all: 0, bad: 0 },
+                       started: 0,
+                       updateRate: 1000,
+                       autostart: true,
+                       filter: ""
+               }, true );
 
-               output += "<table>";
+               config.blocking = false;
 
-               if ( actual ) {
-                       output += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText( actual ) + "</pre></td></tr>";
+               if ( config.autostart ) {
+                       resumeProcessing();
                }
+       }
+});
 
-               if ( source ) {
-                       details.source = source;
-                       output += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";
-               }
+// Register logging callbacks
+(function() {
+       var i, l, key,
+               callbacks = [ "begin", "done", "log", "testStart", "testDone",
+                       "moduleStart", "moduleDone" ];
+
+       function registerLoggingCallback( key ) {
+               var loggingCallback = function( callback ) {
+                       if ( QUnit.objectType( callback ) !== "function" ) {
+                               throw new Error(
+                                       "QUnit logging methods require a callback function as their first parameters."
+                               );
+                       }
 
-               output += "</table>";
+                       config.callbacks[ key ].push( callback );
+               };
 
-               runLoggingCallbacks( "log", QUnit, details );
+               // DEPRECATED: This will be removed on QUnit 2.0.0+
+               // Stores the registered functions allowing restoring
+               // at verifyLoggingCallbacks() if modified
+               loggingCallbacks[ key ] = loggingCallback;
 
-               config.current.assertions.push({
-                       result: false,
-                       message: output
-               });
-       },
+               return loggingCallback;
+       }
 
-       url: function( params ) {
-               params = extend( extend( {}, QUnit.urlParams ), params );
-               var key,
-                       querystring = "?";
+       for ( i = 0, l = callbacks.length; i < l; i++ ) {
+               key = callbacks[ i ];
 
-               for ( key in params ) {
-                       if ( hasOwn.call( params, key ) ) {
-                               querystring += encodeURIComponent( key ) + "=" +
-                                       encodeURIComponent( params[ key ] ) + "&";
-                       }
+               // Initialize key collection of logging callback
+               if ( QUnit.objectType( config.callbacks[ key ] ) === "undefined" ) {
+                       config.callbacks[ key ] = [];
                }
-               return window.location.protocol + "//" + window.location.host +
-                       window.location.pathname + querystring.slice( 0, -1 );
-       },
 
-       extend: extend,
-       id: id,
-       addEvent: addEvent,
-       addClass: addClass,
-       hasClass: hasClass,
-       removeClass: removeClass
-       // load, equiv, jsDump, diff: Attached later
-});
+               QUnit[ key ] = registerLoggingCallback( key );
+       }
+})();
 
-/**
- * @deprecated: Created for backwards compatibility with test runner that set the hook function
- * into QUnit.{hook}, instead of invoking it and passing the hook function.
- * QUnit.constructor is set to the empty F() above so that we can add to it's prototype here.
- * Doing this allows us to tell if the following methods have been overwritten on the actual
- * QUnit object.
- */
-extend( QUnit.constructor.prototype, {
+// `onErrorFnPrev` initialized at top of scope
+// Preserve other handlers
+onErrorFnPrev = window.onerror;
 
-       // Logging callbacks; all receive a single argument with the listed properties
-       // run test/logs.html for any related changes
-       begin: registerLoggingCallback( "begin" ),
+// Cover uncaught exceptions
+// Returning true will suppress the default browser handler,
+// returning false will let it run.
+window.onerror = function( error, filePath, linerNr ) {
+       var ret = false;
+       if ( onErrorFnPrev ) {
+               ret = onErrorFnPrev( error, filePath, linerNr );
+       }
 
-       // done: { failed, passed, total, runtime }
-       done: registerLoggingCallback( "done" ),
+       // Treat return value as window.onerror itself does,
+       // Only do our handling if not suppressed.
+       if ( ret !== true ) {
+               if ( QUnit.config.current ) {
+                       if ( QUnit.config.current.ignoreGlobalErrors ) {
+                               return true;
+                       }
+                       QUnit.pushFailure( error, filePath + ":" + linerNr );
+               } else {
+                       QUnit.test( "global failure", extend(function() {
+                               QUnit.pushFailure( error, filePath + ":" + linerNr );
+                       }, { validTest: true } ) );
+               }
+               return false;
+       }
 
-       // log: { result, actual, expected, message }
-       log: registerLoggingCallback( "log" ),
+       return ret;
+};
 
-       // testStart: { name }
-       testStart: registerLoggingCallback( "testStart" ),
+function done() {
+       var runtime, passed;
 
-       // testDone: { name, failed, passed, total, runtime }
-       testDone: registerLoggingCallback( "testDone" ),
+       config.autorun = true;
 
-       // moduleStart: { name }
-       moduleStart: registerLoggingCallback( "moduleStart" ),
+       // Log the last module results
+       if ( config.previousModule ) {
+               runLoggingCallbacks( "moduleDone", {
+                       name: config.previousModule.name,
+                       tests: config.previousModule.tests,
+                       failed: config.moduleStats.bad,
+                       passed: config.moduleStats.all - config.moduleStats.bad,
+                       total: config.moduleStats.all,
+                       runtime: now() - config.moduleStats.started
+               });
+       }
+       delete config.previousModule;
 
-       // moduleDone: { name, failed, passed, total }
-       moduleDone: registerLoggingCallback( "moduleDone" )
-});
+       runtime = now() - config.started;
+       passed = config.stats.all - config.stats.bad;
 
-if ( !defined.document || document.readyState === "complete" ) {
-       config.autorun = true;
+       runLoggingCallbacks( "done", {
+               failed: config.stats.bad,
+               passed: passed,
+               total: config.stats.all,
+               runtime: runtime
+       });
 }
 
-QUnit.load = function() {
-       runLoggingCallbacks( "begin", QUnit, {} );
-
-       // Initialize the config, saving the execution queue
-       var banner, filter, i, j, label, len, main, ol, toolbar, val, selection,
-               urlConfigContainer, moduleFilter, userAgent,
-               numModules = 0,
-               moduleNames = [],
-               moduleFilterHtml = "",
-               urlConfigHtml = "",
-               oldconfig = extend( {}, config );
+// Doesn't support IE6 to IE9
+// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
+function extractStacktrace( e, offset ) {
+       offset = offset === undefined ? 4 : offset;
 
-       QUnit.init();
-       extend(config, oldconfig);
+       var stack, include, i;
 
-       config.blocking = false;
+       if ( e.stacktrace ) {
 
-       len = config.urlConfig.length;
+               // Opera 12.x
+               return e.stacktrace.split( "\n" )[ offset + 3 ];
+       } else if ( e.stack ) {
 
-       for ( i = 0; i < len; i++ ) {
-               val = config.urlConfig[i];
-               if ( typeof val === "string" ) {
-                       val = {
-                               id: val,
-                               label: val
-                       };
-               }
-               config[ val.id ] = QUnit.urlParams[ val.id ];
-               if ( !val.value || typeof val.value === "string" ) {
-                       urlConfigHtml += "<input id='qunit-urlconfig-" + escapeText( val.id ) +
-                               "' name='" + escapeText( val.id ) +
-                               "' type='checkbox'" +
-                               ( val.value ? " value='" + escapeText( val.value ) + "'" : "" ) +
-                               ( config[ val.id ] ? " checked='checked'" : "" ) +
-                               " title='" + escapeText( val.tooltip ) +
-                               "'><label for='qunit-urlconfig-" + escapeText( val.id ) +
-                               "' title='" + escapeText( val.tooltip ) + "'>" + val.label + "</label>";
-               } else {
-                       urlConfigHtml += "<label for='qunit-urlconfig-" + escapeText( val.id ) +
-                               "' title='" + escapeText( val.tooltip ) +
-                               "'>" + val.label +
-                               ": </label><select id='qunit-urlconfig-" + escapeText( val.id ) +
-                               "' name='" + escapeText( val.id ) +
-                               "' title='" + escapeText( val.tooltip ) +
-                               "'><option></option>";
-                       selection = false;
-                       if ( QUnit.is( "array", val.value ) ) {
-                               for ( j = 0; j < val.value.length; j++ ) {
-                                       urlConfigHtml += "<option value='" + escapeText( val.value[j] ) + "'" +
-                                               ( config[ val.id ] === val.value[j] ?
-                                                       (selection = true) && " selected='selected'" :
-                                                       "" ) +
-                                               ">" + escapeText( val.value[j] ) + "</option>";
-                               }
-                       } else {
-                               for ( j in val.value ) {
-                                       if ( hasOwn.call( val.value, j ) ) {
-                                               urlConfigHtml += "<option value='" + escapeText( j ) + "'" +
-                                                       ( config[ val.id ] === j ?
-                                                               (selection = true) && " selected='selected'" :
-                                                               "" ) +
-                                                       ">" + escapeText( val.value[j] ) + "</option>";
-                                       }
-                               }
-                       }
-                       if ( config[ val.id ] && !selection ) {
-                               urlConfigHtml += "<option value='" + escapeText( config[ val.id ] ) +
-                                       "' selected='selected' disabled='disabled'>" +
-                                       escapeText( config[ val.id ] ) +
-                                       "</option>";
-                       }
-                       urlConfigHtml += "</select>";
-               }
-       }
-       for ( i in config.modules ) {
-               if ( config.modules.hasOwnProperty( i ) ) {
-                       moduleNames.push(i);
-               }
-       }
-       numModules = moduleNames.length;
-       moduleNames.sort( function( a, b ) {
-               return a.localeCompare( b );
-       });
-       moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label><select id='qunit-modulefilter' name='modulefilter'><option value='' " +
-               ( config.module === undefined  ? "selected='selected'" : "" ) +
-               ">< All Modules ></option>";
-
-
-       for ( i = 0; i < numModules; i++) {
-                       moduleFilterHtml += "<option value='" + escapeText( encodeURIComponent(moduleNames[i]) ) + "' " +
-                               ( config.module === moduleNames[i] ? "selected='selected'" : "" ) +
-                               ">" + escapeText(moduleNames[i]) + "</option>";
-       }
-       moduleFilterHtml += "</select>";
-
-       // `userAgent` initialized at top of scope
-       userAgent = id( "qunit-userAgent" );
-       if ( userAgent ) {
-               userAgent.innerHTML = navigator.userAgent;
-       }
-
-       // `banner` initialized at top of scope
-       banner = id( "qunit-header" );
-       if ( banner ) {
-               banner.innerHTML = "<a href='" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + "'>" + banner.innerHTML + "</a> ";
-       }
-
-       // `toolbar` initialized at top of scope
-       toolbar = id( "qunit-testrunner-toolbar" );
-       if ( toolbar ) {
-               // `filter` initialized at top of scope
-               filter = document.createElement( "input" );
-               filter.type = "checkbox";
-               filter.id = "qunit-filter-pass";
-
-               addEvent( filter, "click", function() {
-                       var tmp,
-                               ol = id( "qunit-tests" );
-
-                       if ( filter.checked ) {
-                               ol.className = ol.className + " hidepass";
-                       } else {
-                               tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " ";
-                               ol.className = tmp.replace( / hidepass /, " " );
-                       }
-                       if ( defined.sessionStorage ) {
-                               if (filter.checked) {
-                                       sessionStorage.setItem( "qunit-filter-passed-tests", "true" );
-                               } else {
-                                       sessionStorage.removeItem( "qunit-filter-passed-tests" );
-                               }
-                       }
-               });
-
-               if ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( "qunit-filter-passed-tests" ) ) {
-                       filter.checked = true;
-                       // `ol` initialized at top of scope
-                       ol = id( "qunit-tests" );
-                       ol.className = ol.className + " hidepass";
-               }
-               toolbar.appendChild( filter );
-
-               // `label` initialized at top of scope
-               label = document.createElement( "label" );
-               label.setAttribute( "for", "qunit-filter-pass" );
-               label.setAttribute( "title", "Only show tests and assertions that fail. Stored in sessionStorage." );
-               label.innerHTML = "Hide passed tests";
-               toolbar.appendChild( label );
-
-               urlConfigContainer = document.createElement("span");
-               urlConfigContainer.innerHTML = urlConfigHtml;
-               // For oldIE support:
-               // * Add handlers to the individual elements instead of the container
-               // * Use "click" instead of "change" for checkboxes
-               // * Fallback from event.target to event.srcElement
-               addEvents( urlConfigContainer.getElementsByTagName("input"), "click", function( event ) {
-                       var params = {},
-                               target = event.target || event.srcElement;
-                       params[ target.name ] = target.checked ?
-                               target.defaultValue || true :
-                               undefined;
-                       window.location = QUnit.url( params );
-               });
-               addEvents( urlConfigContainer.getElementsByTagName("select"), "change", function( event ) {
-                       var params = {},
-                               target = event.target || event.srcElement;
-                       params[ target.name ] = target.options[ target.selectedIndex ].value || undefined;
-                       window.location = QUnit.url( params );
-               });
-               toolbar.appendChild( urlConfigContainer );
-
-               if (numModules > 1) {
-                       moduleFilter = document.createElement( "span" );
-                       moduleFilter.setAttribute( "id", "qunit-modulefilter-container" );
-                       moduleFilter.innerHTML = moduleFilterHtml;
-                       addEvent( moduleFilter.lastChild, "change", function() {
-                               var selectBox = moduleFilter.getElementsByTagName("select")[0],
-                                       selectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);
-
-                               window.location = QUnit.url({
-                                       module: ( selectedModule === "" ) ? undefined : selectedModule,
-                                       // Remove any existing filters
-                                       filter: undefined,
-                                       testNumber: undefined
-                               });
-                       });
-                       toolbar.appendChild(moduleFilter);
-               }
-       }
-
-       // `main` initialized at top of scope
-       main = id( "qunit-fixture" );
-       if ( main ) {
-               config.fixture = main.innerHTML;
-       }
-
-       if ( config.autostart ) {
-               QUnit.start();
-       }
-};
-
-if ( defined.document ) {
-       addEvent( window, "load", QUnit.load );
-}
-
-// `onErrorFnPrev` initialized at top of scope
-// Preserve other handlers
-onErrorFnPrev = window.onerror;
-
-// Cover uncaught exceptions
-// Returning true will suppress the default browser handler,
-// returning false will let it run.
-window.onerror = function ( error, filePath, linerNr ) {
-       var ret = false;
-       if ( onErrorFnPrev ) {
-               ret = onErrorFnPrev( error, filePath, linerNr );
-       }
-
-       // Treat return value as window.onerror itself does,
-       // Only do our handling if not suppressed.
-       if ( ret !== true ) {
-               if ( QUnit.config.current ) {
-                       if ( QUnit.config.current.ignoreGlobalErrors ) {
-                               return true;
-                       }
-                       QUnit.pushFailure( error, filePath + ":" + linerNr );
-               } else {
-                       QUnit.test( "global failure", extend( function() {
-                               QUnit.pushFailure( error, filePath + ":" + linerNr );
-                       }, { validTest: validTest } ) );
-               }
-               return false;
-       }
-
-       return ret;
-};
-
-function done() {
-       config.autorun = true;
-
-       // Log the last module results
-       if ( config.previousModule ) {
-               runLoggingCallbacks( "moduleDone", QUnit, {
-                       name: config.previousModule,
-                       failed: config.moduleStats.bad,
-                       passed: config.moduleStats.all - config.moduleStats.bad,
-                       total: config.moduleStats.all
-               });
-       }
-       delete config.previousModule;
-
-       var i, key,
-               banner = id( "qunit-banner" ),
-               tests = id( "qunit-tests" ),
-               runtime = +new Date() - config.started,
-               passed = config.stats.all - config.stats.bad,
-               html = [
-                       "Tests completed in ",
-                       runtime,
-                       " milliseconds.<br/>",
-                       "<span class='passed'>",
-                       passed,
-                       "</span> assertions of <span class='total'>",
-                       config.stats.all,
-                       "</span> passed, <span class='failed'>",
-                       config.stats.bad,
-                       "</span> failed."
-               ].join( "" );
-
-       if ( banner ) {
-               banner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" );
-       }
-
-       if ( tests ) {
-               id( "qunit-testresult" ).innerHTML = html;
-       }
-
-       if ( config.altertitle && defined.document && document.title ) {
-               // show ✖ for good, ✔ for bad suite result in title
-               // use escape sequences in case file gets loaded with non-utf-8-charset
-               document.title = [
-                       ( config.stats.bad ? "\u2716" : "\u2714" ),
-                       document.title.replace( /^[\u2714\u2716] /i, "" )
-               ].join( " " );
-       }
-
-       // clear own sessionStorage items if all tests passed
-       if ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {
-               // `key` & `i` initialized at top of scope
-               for ( i = 0; i < sessionStorage.length; i++ ) {
-                       key = sessionStorage.key( i++ );
-                       if ( key.indexOf( "qunit-test-" ) === 0 ) {
-                               sessionStorage.removeItem( key );
-                       }
-               }
-       }
-
-       // scroll back to top to show results
-       if ( config.scrolltop && window.scrollTo ) {
-               window.scrollTo(0, 0);
-       }
-
-       runLoggingCallbacks( "done", QUnit, {
-               failed: config.stats.bad,
-               passed: passed,
-               total: config.stats.all,
-               runtime: runtime
-       });
-}
-
-/** @return Boolean: true if this test should be ran */
-function validTest( test ) {
-       var include,
-               filter = config.filter && config.filter.toLowerCase(),
-               module = config.module && config.module.toLowerCase(),
-               fullName = ( test.module + ": " + test.testName ).toLowerCase();
-
-       // Internally-generated tests are always valid
-       if ( test.callback && test.callback.validTest === validTest ) {
-               delete test.callback.validTest;
-               return true;
-       }
-
-       if ( config.testNumber.length > 0 ) {
-               if ( inArray( test.testNumber, config.testNumber ) < 0 ) {
-                       return false;
-               }
-       }
-
-       if ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {
-               return false;
-       }
-
-       if ( !filter ) {
-               return true;
-       }
-
-       include = filter.charAt( 0 ) !== "!";
-       if ( !include ) {
-               filter = filter.slice( 1 );
-       }
-
-       // If the filter matches, we need to honour include
-       if ( fullName.indexOf( filter ) !== -1 ) {
-               return include;
-       }
-
-       // Otherwise, do the opposite
-       return !include;
-}
-
-// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)
-// Later Safari and IE10 are supposed to support error.stack as well
-// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
-function extractStacktrace( e, offset ) {
-       offset = offset === undefined ? 3 : offset;
-
-       var stack, include, i;
-
-       if ( e.stacktrace ) {
-               // Opera
-               return e.stacktrace.split( "\n" )[ offset + 3 ];
-       } else if ( e.stack ) {
-               // Firefox, Chrome
+               // Firefox, Chrome, Safari 6+, IE10+, PhantomJS and Node
                stack = e.stack.split( "\n" );
-               if (/^error$/i.test( stack[0] ) ) {
+               if ( /^error$/i.test( stack[ 0 ] ) ) {
                        stack.shift();
                }
                if ( fileName ) {
@@ -953,50 +534,38 @@ function extractStacktrace( e, offset ) {
                }
                return stack[ offset ];
        } else if ( e.sourceURL ) {
-               // Safari, PhantomJS
-               // hopefully one day Safari provides actual stacktraces
+
+               // Safari < 6
                // exclude useless self-reference for generated Error objects
                if ( /qunit.js$/.test( e.sourceURL ) ) {
                        return;
                }
+
                // for actual exceptions, this is useful
                return e.sourceURL + ":" + e.line;
        }
 }
-function sourceFromStacktrace( offset ) {
-       try {
-               throw new Error();
-       } catch ( e ) {
-               return extractStacktrace( e, offset );
-       }
-}
 
-/**
- * Escape text for attribute or text content.
- */
-function escapeText( s ) {
-       if ( !s ) {
-               return "";
-       }
-       s = s + "";
-       // Both single quotes and double quotes (for attributes)
-       return s.replace( /['"<>&]/g, function( s ) {
-               switch( s ) {
-                       case "'":
-                               return "&#039;";
-                       case "\"":
-                               return "&quot;";
-                       case "<":
-                               return "&lt;";
-                       case ">":
-                               return "&gt;";
-                       case "&":
-                               return "&amp;";
+function sourceFromStacktrace( offset ) {
+       var e = new Error();
+       if ( !e.stack ) {
+               try {
+                       throw e;
+               } catch ( err ) {
+                       // This should already be true in most browsers
+                       e = err;
                }
-       });
+       }
+       return extractStacktrace( e, offset );
 }
 
 function synchronize( callback, last ) {
+       if ( QUnit.objectType( callback ) === "array" ) {
+               while ( callback.length ) {
+                       synchronize( callback.shift() );
+               }
+               return;
+       }
        config.queue.push( callback );
 
        if ( config.autorun && !config.blocking ) {
@@ -1008,11 +577,17 @@ function process( last ) {
        function next() {
                process( last );
        }
-       var start = new Date().getTime();
+       var start = now();
        config.depth = config.depth ? config.depth + 1 : 1;
 
        while ( config.queue.length && !config.blocking ) {
-               if ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {
+               if ( !defined.setTimeout || config.updateRate <= 0 ||
+                               ( ( now() - start ) < config.updateRate ) ) {
+                       if ( config.current ) {
+
+                               // Reset async tracking for each phase of the Test lifecycle
+                               config.current.usedAsync = false;
+                       }
                        config.queue.shift()();
                } else {
                        setTimeout( next, 13 );
@@ -1025,6 +600,79 @@ function process( last ) {
        }
 }
 
+function begin() {
+       var i, l,
+               modulesLog = [];
+
+       // If the test run hasn't officially begun yet
+       if ( !config.started ) {
+
+               // Record the time of the test run's beginning
+               config.started = now();
+
+               verifyLoggingCallbacks();
+
+               // Delete the loose unnamed module if unused.
+               if ( config.modules[ 0 ].name === "" && config.modules[ 0 ].tests.length === 0 ) {
+                       config.modules.shift();
+               }
+
+               // Avoid unnecessary information by not logging modules' test environments
+               for ( i = 0, l = config.modules.length; i < l; i++ ) {
+                       modulesLog.push({
+                               name: config.modules[ i ].name,
+                               tests: config.modules[ i ].tests
+                       });
+               }
+
+               // The test run is officially beginning now
+               runLoggingCallbacks( "begin", {
+                       totalTests: Test.count,
+                       modules: modulesLog
+               });
+       }
+
+       config.blocking = false;
+       process( true );
+}
+
+function resumeProcessing() {
+       runStarted = true;
+
+       // A slight delay to allow this iteration of the event loop to finish (more assertions, etc.)
+       if ( defined.setTimeout ) {
+               setTimeout(function() {
+                       if ( config.current && config.current.semaphore > 0 ) {
+                               return;
+                       }
+                       if ( config.timeout ) {
+                               clearTimeout( config.timeout );
+                       }
+
+                       begin();
+               }, 13 );
+       } else {
+               begin();
+       }
+}
+
+function pauseProcessing() {
+       config.blocking = true;
+
+       if ( config.testTimeout && defined.setTimeout ) {
+               clearTimeout( config.timeout );
+               config.timeout = setTimeout(function() {
+                       if ( config.current ) {
+                               config.current.semaphore = 0;
+                               QUnit.pushFailure( "Test timed out", sourceFromStacktrace( 2 ) );
+                       } else {
+                               throw new Error( "Test timed out" );
+                       }
+                       resumeProcessing();
+               }, config.testTimeout );
+       }
+}
+
 function saveGlobal() {
        config.pollution = [];
 
@@ -1050,12 +698,12 @@ function checkPollution() {
 
        newGlobals = diff( config.pollution, old );
        if ( newGlobals.length > 0 ) {
-               QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") );
+               QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join( ", " ) );
        }
 
        deletedGlobals = diff( old, config.pollution );
        if ( deletedGlobals.length > 0 ) {
-               QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") );
+               QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join( ", " ) );
        }
 }
 
@@ -1066,7 +714,7 @@ function diff( a, b ) {
 
        for ( i = 0; i < result.length; i++ ) {
                for ( j = 0; j < b.length; j++ ) {
-                       if ( result[i] === b[j] ) {
+                       if ( result[ i ] === b[ j ] ) {
                                result.splice( i, 1 );
                                i--;
                                break;
@@ -1076,14 +724,15 @@ function diff( a, b ) {
        return result;
 }
 
-function extend( a, b ) {
+function extend( a, b, undefOnly ) {
        for ( var prop in b ) {
                if ( hasOwn.call( b, prop ) ) {
+
                        // Avoid "Member not found" error in IE8 caused by messing with window.constructor
                        if ( !( prop === "constructor" && a === window ) ) {
                                if ( b[ prop ] === undefined ) {
                                        delete a[ prop ];
-                               } else {
+                               } else if ( !( undefOnly && typeof a[ prop ] !== "undefined" ) ) {
                                        a[ prop ] = b[ prop ];
                                }
                        }
@@ -1093,78 +742,39 @@ function extend( a, b ) {
        return a;
 }
 
-/**
- * @param {HTMLElement} elem
- * @param {string} type
- * @param {Function} fn
- */
-function addEvent( elem, type, fn ) {
-       if ( elem.addEventListener ) {
-
-               // Standards-based browsers
-               elem.addEventListener( type, fn, false );
-       } else if ( elem.attachEvent ) {
-
-               // support: IE <9
-               elem.attachEvent( "on" + type, fn );
-       } else {
+function runLoggingCallbacks( key, args ) {
+       var i, l, callbacks;
 
-               // Caller must ensure support for event listeners is present
-               throw new Error( "addEvent() was called in a context without event listener support" );
+       callbacks = config.callbacks[ key ];
+       for ( i = 0, l = callbacks.length; i < l; i++ ) {
+               callbacks[ i ]( args );
        }
 }
 
-/**
- * @param {Array|NodeList} elems
- * @param {string} type
- * @param {Function} fn
- */
-function addEvents( elems, type, fn ) {
-       var i = elems.length;
-       while ( i-- ) {
-               addEvent( elems[i], type, fn );
-       }
-}
-
-function hasClass( elem, name ) {
-       return (" " + elem.className + " ").indexOf(" " + name + " ") > -1;
-}
+// DEPRECATED: This will be removed on 2.0.0+
+// This function verifies if the loggingCallbacks were modified by the user
+// If so, it will restore it, assign the given callback and print a console warning
+function verifyLoggingCallbacks() {
+       var loggingCallback, userCallback;
 
-function addClass( elem, name ) {
-       if ( !hasClass( elem, name ) ) {
-               elem.className += (elem.className ? " " : "") + name;
-       }
-}
+       for ( loggingCallback in loggingCallbacks ) {
+               if ( QUnit[ loggingCallback ] !== loggingCallbacks[ loggingCallback ] ) {
 
-function removeClass( elem, name ) {
-       var set = " " + elem.className + " ";
-       // Class name may appear multiple times
-       while ( set.indexOf(" " + name + " ") > -1 ) {
-               set = set.replace(" " + name + " " , " ");
-       }
-       // If possible, trim it for prettiness, but not necessarily
-       elem.className = typeof set.trim === "function" ? set.trim() : set.replace(/^\s+|\s+$/g, "");
-}
+                       userCallback = QUnit[ loggingCallback ];
 
-function id( name ) {
-       return defined.document && document.getElementById && document.getElementById( name );
-}
+                       // Restore the callback function
+                       QUnit[ loggingCallback ] = loggingCallbacks[ loggingCallback ];
 
-function registerLoggingCallback( key ) {
-       return function( callback ) {
-               config[key].push( callback );
-       };
-}
+                       // Assign the deprecated given callback
+                       QUnit[ loggingCallback ]( userCallback );
 
-// Supports deprecated method of completely overwriting logging callbacks
-function runLoggingCallbacks( key, scope, args ) {
-       var i, callbacks;
-       if ( QUnit.hasOwnProperty( key ) ) {
-               QUnit[ key ].call(scope, args );
-       } else {
-               callbacks = config[ key ];
-               for ( i = 0; i < callbacks.length; i++ ) {
-                       callbacks[ i ].call( scope, args );
+                       if ( window.console && window.console.warn ) {
+                               window.console.warn(
+                                       "QUnit." + loggingCallback + " was replaced with a new value.\n" +
+                                       "Please, check out the documentation on how to apply logging callbacks.\n" +
+                                       "Reference: http://api.qunitjs.com/category/callbacks/"
+                               );
+                       }
                }
        }
 }
@@ -1185,40 +795,51 @@ function inArray( elem, array ) {
 }
 
 function Test( settings ) {
+       var i, l;
+
+       ++Test.count;
+
        extend( this, settings );
        this.assertions = [];
-       this.testNumber = ++Test.count;
-}
+       this.semaphore = 0;
+       this.usedAsync = false;
+       this.module = config.currentModule;
+       this.stack = sourceFromStacktrace( 3 );
 
-Test.count = 0;
+       // Register unique strings
+       for ( i = 0, l = this.module.tests; i < l.length; i++ ) {
+               if ( this.module.tests[ i ].name === this.testName ) {
+                       this.testName += " ";
+               }
+       }
 
-Test.prototype = {
-       init: function() {
-               var a, b, li,
-                       tests = id( "qunit-tests" );
+       this.testId = generateHash( this.module.name, this.testName );
+
+       this.module.tests.push({
+               name: this.testName,
+               testId: this.testId
+       });
 
-               if ( tests ) {
-                       b = document.createElement( "strong" );
-                       b.innerHTML = this.nameHtml;
+       if ( settings.skip ) {
 
-                       // `a` initialized at top of scope
-                       a = document.createElement( "a" );
-                       a.innerHTML = "Rerun";
-                       a.href = QUnit.url({ testNumber: this.testNumber });
+               // Skipped tests will fully ignore any sent callback
+               this.callback = function() {};
+               this.async = false;
+               this.expected = 0;
+       } else {
+               this.assert = new Assert( this );
+       }
+}
 
-                       li = document.createElement( "li" );
-                       li.appendChild( b );
-                       li.appendChild( a );
-                       li.className = "running";
-                       li.id = this.id = "qunit-test-output" + testId++;
+Test.count = 0;
 
-                       tests.appendChild( li );
-               }
-       },
-       setup: function() {
+Test.prototype = {
+       before: function() {
                if (
+
                        // Emit moduleStart when we're switching from one module to another
                        this.module !== config.previousModule ||
+
                                // They could be equal (both undefined) but if the previousModule property doesn't
                                // yet exist it means this is the first test in a suite that isn't wrapped in a
                                // module, in which case we'll just emit a moduleStart event for 'undefined'.
@@ -1226,86 +847,65 @@ Test.prototype = {
                                !hasOwn.call( config, "previousModule" )
                ) {
                        if ( hasOwn.call( config, "previousModule" ) ) {
-                               runLoggingCallbacks( "moduleDone", QUnit, {
-                                       name: config.previousModule,
+                               runLoggingCallbacks( "moduleDone", {
+                                       name: config.previousModule.name,
+                                       tests: config.previousModule.tests,
                                        failed: config.moduleStats.bad,
                                        passed: config.moduleStats.all - config.moduleStats.bad,
-                                       total: config.moduleStats.all
+                                       total: config.moduleStats.all,
+                                       runtime: now() - config.moduleStats.started
                                });
                        }
                        config.previousModule = this.module;
-                       config.moduleStats = { all: 0, bad: 0 };
-                       runLoggingCallbacks( "moduleStart", QUnit, {
-                               name: this.module
+                       config.moduleStats = { all: 0, bad: 0, started: now() };
+                       runLoggingCallbacks( "moduleStart", {
+                               name: this.module.name,
+                               tests: this.module.tests
                        });
                }
 
                config.current = this;
 
-               this.testEnvironment = extend({
-                       setup: function() {},
-                       teardown: function() {}
-               }, this.moduleTestEnvironment );
+               this.testEnvironment = extend( {}, this.module.testEnvironment );
+               delete this.testEnvironment.beforeEach;
+               delete this.testEnvironment.afterEach;
 
-               this.started = +new Date();
-               runLoggingCallbacks( "testStart", QUnit, {
+               this.started = now();
+               runLoggingCallbacks( "testStart", {
                        name: this.testName,
-                       module: this.module
+                       module: this.module.name,
+                       testId: this.testId
                });
 
-               /*jshint camelcase:false */
-
-
-               /**
-                * Expose the current test environment.
-                *
-                * @deprecated since 1.12.0: Use QUnit.config.current.testEnvironment instead.
-                */
-               QUnit.current_testEnvironment = this.testEnvironment;
-
-               /*jshint camelcase:true */
-
                if ( !config.pollution ) {
                        saveGlobal();
                }
-               if ( config.notrycatch ) {
-                       this.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );
-                       return;
-               }
-               try {
-                       this.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );
-               } catch( e ) {
-                       QUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
-               }
        },
-       run: function() {
-               config.current = this;
 
-               var running = id( "qunit-testresult" );
+       run: function() {
+               var promise;
 
-               if ( running ) {
-                       running.innerHTML = "Running: <br/>" + this.nameHtml;
-               }
+               config.current = this;
 
                if ( this.async ) {
                        QUnit.stop();
                }
 
-               this.callbackStarted = +new Date();
+               this.callbackStarted = now();
 
                if ( config.notrycatch ) {
-                       this.callback.call( this.testEnvironment, QUnit.assert );
-                       this.callbackRuntime = +new Date() - this.callbackStarted;
+                       promise = this.callback.call( this.testEnvironment, this.assert );
+                       this.resolvePromise( promise );
                        return;
                }
 
                try {
-                       this.callback.call( this.testEnvironment, QUnit.assert );
-                       this.callbackRuntime = +new Date() - this.callbackStarted;
-               } catch( e ) {
-                       this.callbackRuntime = +new Date() - this.callbackStarted;
+                       promise = this.callback.call( this.testEnvironment, this.assert );
+                       this.resolvePromise( promise );
+               } catch ( e ) {
+                       this.pushFailure( "Died on test #" + ( this.assertions.length + 1 ) + " " +
+                               this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
 
-                       QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
                        // else next test will carry the responsibility
                        saveGlobal();
 
@@ -1315,133 +915,96 @@ Test.prototype = {
                        }
                }
        },
-       teardown: function() {
-               config.current = this;
-               if ( config.notrycatch ) {
-                       if ( typeof this.callbackRuntime === "undefined" ) {
-                               this.callbackRuntime = +new Date() - this.callbackStarted;
+
+       after: function() {
+               checkPollution();
+       },
+
+       queueHook: function( hook, hookName ) {
+               var promise,
+                       test = this;
+               return function runHook() {
+                       config.current = test;
+                       if ( config.notrycatch ) {
+                               promise = hook.call( test.testEnvironment, test.assert );
+                               test.resolvePromise( promise, hookName );
+                               return;
                        }
-                       this.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );
-                       return;
-               } else {
                        try {
-                               this.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );
-                       } catch( e ) {
-                               QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );
+                               promise = hook.call( test.testEnvironment, test.assert );
+                               test.resolvePromise( promise, hookName );
+                       } catch ( error ) {
+                               test.pushFailure( hookName + " failed on " + test.testName + ": " +
+                                       ( error.message || error ), extractStacktrace( error, 0 ) );
                        }
+               };
+       },
+
+       // Currently only used for module level hooks, can be used to add global level ones
+       hooks: function( handler ) {
+               var hooks = [];
+
+               // Hooks are ignored on skipped tests
+               if ( this.skip ) {
+                       return hooks;
                }
-               checkPollution();
+
+               if ( this.module.testEnvironment &&
+                               QUnit.objectType( this.module.testEnvironment[ handler ] ) === "function" ) {
+                       hooks.push( this.queueHook( this.module.testEnvironment[ handler ], handler ) );
+               }
+
+               return hooks;
        },
+
        finish: function() {
                config.current = this;
                if ( config.requireExpects && this.expected === null ) {
-                       QUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack );
+                       this.pushFailure( "Expected number of assertions to be defined, but expect() was " +
+                               "not called.", this.stack );
                } else if ( this.expected !== null && this.expected !== this.assertions.length ) {
-                       QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack );
+                       this.pushFailure( "Expected " + this.expected + " assertions, but " +
+                               this.assertions.length + " were run", this.stack );
                } else if ( this.expected === null && !this.assertions.length ) {
-                       QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );
+                       this.pushFailure( "Expected at least one assertion, but none were run - call " +
+                               "expect(0) to accept zero assertions.", this.stack );
                }
 
-               var i, assertion, a, b, time, li, ol,
-                       test = this,
-                       good = 0,
-                       bad = 0,
-                       tests = id( "qunit-tests" );
+               var i,
+                       bad = 0;
 
-               this.runtime = +new Date() - this.started;
+               this.runtime = now() - this.started;
                config.stats.all += this.assertions.length;
                config.moduleStats.all += this.assertions.length;
 
-               if ( tests ) {
-                       ol = document.createElement( "ol" );
-                       ol.className = "qunit-assert-list";
-
-                       for ( i = 0; i < this.assertions.length; i++ ) {
-                               assertion = this.assertions[i];
-
-                               li = document.createElement( "li" );
-                               li.className = assertion.result ? "pass" : "fail";
-                               li.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" );
-                               ol.appendChild( li );
-
-                               if ( assertion.result ) {
-                                       good++;
-                               } else {
-                                       bad++;
-                                       config.stats.bad++;
-                                       config.moduleStats.bad++;
-                               }
-                       }
-
-                       // store result when possible
-                       if ( QUnit.config.reorder && defined.sessionStorage ) {
-                               if ( bad ) {
-                                       sessionStorage.setItem( "qunit-test-" + this.module + "-" + this.testName, bad );
-                               } else {
-                                       sessionStorage.removeItem( "qunit-test-" + this.module + "-" + this.testName );
-                               }
-                       }
-
-                       if ( bad === 0 ) {
-                               addClass( ol, "qunit-collapsed" );
-                       }
-
-                       // `b` initialized at top of scope
-                       b = document.createElement( "strong" );
-                       b.innerHTML = this.nameHtml + " <b class='counts'>(<b class='failed'>" + bad + "</b>, <b class='passed'>" + good + "</b>, " + this.assertions.length + ")</b>";
-
-                       addEvent(b, "click", function() {
-                               var next = b.parentNode.lastChild,
-                                       collapsed = hasClass( next, "qunit-collapsed" );
-                               ( collapsed ? removeClass : addClass )( next, "qunit-collapsed" );
-                       });
-
-                       addEvent(b, "dblclick", function( e ) {
-                               var target = e && e.target ? e.target : window.event.srcElement;
-                               if ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) {
-                                       target = target.parentNode;
-                               }
-                               if ( window.location && target.nodeName.toLowerCase() === "strong" ) {
-                                       window.location = QUnit.url({ testNumber: test.testNumber });
-                               }
-                       });
-
-                       // `time` initialized at top of scope
-                       time = document.createElement( "span" );
-                       time.className = "runtime";
-                       time.innerHTML = this.runtime + " ms";
-
-                       // `li` initialized at top of scope
-                       li = id( this.id );
-                       li.className = bad ? "fail" : "pass";
-                       li.removeChild( li.firstChild );
-                       a = li.firstChild;
-                       li.appendChild( b );
-                       li.appendChild( a );
-                       li.appendChild( time );
-                       li.appendChild( ol );
-
-               } else {
-                       for ( i = 0; i < this.assertions.length; i++ ) {
-                               if ( !this.assertions[i].result ) {
-                                       bad++;
-                                       config.stats.bad++;
-                                       config.moduleStats.bad++;
-                               }
+               for ( i = 0; i < this.assertions.length; i++ ) {
+                       if ( !this.assertions[ i ].result ) {
+                               bad++;
+                               config.stats.bad++;
+                               config.moduleStats.bad++;
                        }
                }
 
-               runLoggingCallbacks( "testDone", QUnit, {
+               runLoggingCallbacks( "testDone", {
                        name: this.testName,
-                       module: this.module,
+                       module: this.module.name,
+                       skipped: !!this.skip,
                        failed: bad,
                        passed: this.assertions.length - bad,
                        total: this.assertions.length,
                        runtime: this.runtime,
+
+                       // HTML Reporter use
+                       assertions: this.assertions,
+                       testId: this.testId,
+
                        // DEPRECATED: this property will be removed in 2.0.0, use runtime instead
                        duration: this.runtime
                });
 
+               // QUnit.reset() is deprecated and will be replaced for a new
+               // fixture reset function on QUnit 2.0/2.1.
+               // It's still called here for backwards compatibility handling
                QUnit.reset();
 
                config.current = undefined;
@@ -1451,93 +1014,316 @@ Test.prototype = {
                var bad,
                        test = this;
 
-               synchronize(function() {
-                       test.init();
-               });
+               if ( !this.valid() ) {
+                       return;
+               }
+
                function run() {
+
                        // each of these can by async
-                       synchronize(function() {
-                               test.setup();
-                       });
-                       synchronize(function() {
-                               test.run();
-                       });
-                       synchronize(function() {
-                               test.teardown();
-                       });
-                       synchronize(function() {
-                               test.finish();
-                       });
+                       synchronize([
+                               function() {
+                                       test.before();
+                               },
+
+                               test.hooks( "beforeEach" ),
+
+                               function() {
+                                       test.run();
+                               },
+
+                               test.hooks( "afterEach" ).reverse(),
+
+                               function() {
+                                       test.after();
+                               },
+                               function() {
+                                       test.finish();
+                               }
+                       ]);
                }
 
                // `bad` initialized at top of scope
                // defer when previous test run passed, if storage is available
                bad = QUnit.config.reorder && defined.sessionStorage &&
-                                               +sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName );
+                               +sessionStorage.getItem( "qunit-test-" + this.module.name + "-" + this.testName );
 
                if ( bad ) {
                        run();
                } else {
                        synchronize( run, true );
                }
-       }
-};
-
-// `assert` initialized at top of scope
-// Assert helpers
-// All of these must either call QUnit.push() or manually do:
-// - runLoggingCallbacks( "log", .. );
-// - config.current.assertions.push({ .. });
-assert = QUnit.assert = {
-       /**
-        * Asserts rough true-ish result.
-        * @name ok
-        * @function
-        * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
-        */
-       ok: function( result, msg ) {
-               if ( !config.current ) {
-                       throw new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) );
-               }
-               result = !!result;
-               msg = msg || ( result ? "okay" : "failed" );
+       },
 
+       push: function( result, actual, expected, message ) {
                var source,
                        details = {
-                               module: config.current.module,
-                               name: config.current.testName,
+                               module: this.module.name,
+                               name: this.testName,
                                result: result,
-                               message: msg
+                               message: message,
+                               actual: actual,
+                               expected: expected,
+                               testId: this.testId,
+                               runtime: now() - this.started
                        };
 
-               msg = "<span class='test-message'>" + escapeText( msg ) + "</span>";
-
                if ( !result ) {
-                       source = sourceFromStacktrace( 2 );
+                       source = sourceFromStacktrace();
+
                        if ( source ) {
                                details.source = source;
-                               msg += "<table><tr class='test-source'><th>Source: </th><td><pre>" +
-                                       escapeText( source ) +
-                                       "</pre></td></tr></table>";
                        }
                }
-               runLoggingCallbacks( "log", QUnit, details );
-               config.current.assertions.push({
-                       result: result,
-                       message: msg
+
+               runLoggingCallbacks( "log", details );
+
+               this.assertions.push({
+                       result: !!result,
+                       message: message
+               });
+       },
+
+       pushFailure: function( message, source, actual ) {
+               if ( !this instanceof Test ) {
+                       throw new Error( "pushFailure() assertion outside test context, was " +
+                               sourceFromStacktrace( 2 ) );
+               }
+
+               var details = {
+                               module: this.module.name,
+                               name: this.testName,
+                               result: false,
+                               message: message || "error",
+                               actual: actual || null,
+                               testId: this.testId,
+                               runtime: now() - this.started
+                       };
+
+               if ( source ) {
+                       details.source = source;
+               }
+
+               runLoggingCallbacks( "log", details );
+
+               this.assertions.push({
+                       result: false,
+                       message: message
                });
        },
 
+       resolvePromise: function( promise, phase ) {
+               var then, message,
+                       test = this;
+               if ( promise != null ) {
+                       then = promise.then;
+                       if ( QUnit.objectType( then ) === "function" ) {
+                               QUnit.stop();
+                               then.call(
+                                       promise,
+                                       QUnit.start,
+                                       function( error ) {
+                                               message = "Promise rejected " +
+                                                       ( !phase ? "during" : phase.replace( /Each$/, "" ) ) +
+                                                       " " + test.testName + ": " + ( error.message || error );
+                                               test.pushFailure( message, extractStacktrace( error, 0 ) );
+
+                                               // else next test will carry the responsibility
+                                               saveGlobal();
+
+                                               // Unblock
+                                               QUnit.start();
+                                       }
+                               );
+                       }
+               }
+       },
+
+       valid: function() {
+               var include,
+                       filter = config.filter && config.filter.toLowerCase(),
+                       module = QUnit.urlParams.module && QUnit.urlParams.module.toLowerCase(),
+                       fullName = ( this.module.name + ": " + this.testName ).toLowerCase();
+
+               // Internally-generated tests are always valid
+               if ( this.callback && this.callback.validTest ) {
+                       return true;
+               }
+
+               if ( config.testId.length > 0 && inArray( this.testId, config.testId ) < 0 ) {
+                       return false;
+               }
+
+               if ( module && ( !this.module.name || this.module.name.toLowerCase() !== module ) ) {
+                       return false;
+               }
+
+               if ( !filter ) {
+                       return true;
+               }
+
+               include = filter.charAt( 0 ) !== "!";
+               if ( !include ) {
+                       filter = filter.slice( 1 );
+               }
+
+               // If the filter matches, we need to honour include
+               if ( fullName.indexOf( filter ) !== -1 ) {
+                       return include;
+               }
+
+               // Otherwise, do the opposite
+               return !include;
+       }
+
+};
+
+// Resets the test setup. Useful for tests that modify the DOM.
+/*
+DEPRECATED: Use multiple tests instead of resetting inside a test.
+Use testStart or testDone for custom cleanup.
+This method will throw an error in 2.0, and will be removed in 2.1
+*/
+QUnit.reset = function() {
+
+       // Return on non-browser environments
+       // This is necessary to not break on node tests
+       if ( typeof window === "undefined" ) {
+               return;
+       }
+
+       var fixture = defined.document && document.getElementById &&
+                       document.getElementById( "qunit-fixture" );
+
+       if ( fixture ) {
+               fixture.innerHTML = config.fixture;
+       }
+};
+
+QUnit.pushFailure = function() {
+       if ( !QUnit.config.current ) {
+               throw new Error( "pushFailure() assertion outside test context, in " +
+                       sourceFromStacktrace( 2 ) );
+       }
+
+       // Gets current test obj
+       var currentTest = QUnit.config.current;
+
+       return currentTest.pushFailure.apply( currentTest, arguments );
+};
+
+// Based on Java's String.hashCode, a simple but not
+// rigorously collision resistant hashing function
+function generateHash( module, testName ) {
+       var hex,
+               i = 0,
+               hash = 0,
+               str = module + "\x1C" + testName,
+               len = str.length;
+
+       for ( ; i < len; i++ ) {
+               hash  = ( ( hash << 5 ) - hash ) + str.charCodeAt( i );
+               hash |= 0;
+       }
+
+       // Convert the possibly negative integer hash code into an 8 character hex string, which isn't
+       // strictly necessary but increases user understanding that the id is a SHA-like hash
+       hex = ( 0x100000000 + hash ).toString( 16 );
+       if ( hex.length < 8 ) {
+               hex = "0000000" + hex;
+       }
+
+       return hex.slice( -8 );
+}
+
+function Assert( testContext ) {
+       this.test = testContext;
+}
+
+// Assert helpers
+QUnit.assert = Assert.prototype = {
+
+       // Specify the number of expected assertions to guarantee that failed test
+       // (no assertions are run at all) don't slip through.
+       expect: function( asserts ) {
+               if ( arguments.length === 1 ) {
+                       this.test.expected = asserts;
+               } else {
+                       return this.test.expected;
+               }
+       },
+
+       // Increment this Test's semaphore counter, then return a single-use function that
+       // decrements that counter a maximum of once.
+       async: function() {
+               var test = this.test,
+                       popped = false;
+
+               test.semaphore += 1;
+               test.usedAsync = true;
+               pauseProcessing();
+
+               return function done() {
+                       if ( !popped ) {
+                               test.semaphore -= 1;
+                               popped = true;
+                               resumeProcessing();
+                       } else {
+                               test.pushFailure( "Called the callback returned from `assert.async` more than once",
+                                       sourceFromStacktrace( 2 ) );
+                       }
+               };
+       },
+
+       // Exports test.push() to the user API
+       push: function( /* result, actual, expected, message */ ) {
+               var assert = this,
+                       currentTest = ( assert instanceof Assert && assert.test ) || QUnit.config.current;
+
+               // Backwards compatibility fix.
+               // Allows the direct use of global exported assertions and QUnit.assert.*
+               // Although, it's use is not recommended as it can leak assertions
+               // to other tests from async tests, because we only get a reference to the current test,
+               // not exactly the test where assertion were intended to be called.
+               if ( !currentTest ) {
+                       throw new Error( "assertion outside test context, in " + sourceFromStacktrace( 2 ) );
+               }
+
+               if ( currentTest.usedAsync === true && currentTest.semaphore === 0 ) {
+                       currentTest.pushFailure( "Assertion after the final `assert.async` was resolved",
+                               sourceFromStacktrace( 2 ) );
+
+                       // Allow this assertion to continue running anyway...
+               }
+
+               if ( !( assert instanceof Assert ) ) {
+                       assert = currentTest.assert;
+               }
+               return assert.test.push.apply( assert.test, arguments );
+       },
+
+       /**
+        * Asserts rough true-ish result.
+        * @name ok
+        * @function
+        * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );
+        */
+       ok: function( result, message ) {
+               message = message || ( result ? "okay" : "failed, expected argument to be truthy, was: " +
+                       QUnit.dump.parse( result ) );
+               this.push( !!result, result, true, message );
+       },
+
        /**
         * Assert that the first two arguments are equal, with an optional message.
         * Prints out both actual and expected values.
         * @name equal
         * @function
-        * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );
+        * @example equal( format( "{0} bytes.", 2), "2 bytes.", "replaces {0} with next argument" );
         */
        equal: function( actual, expected, message ) {
                /*jshint eqeqeq:false */
-               QUnit.push( expected == actual, actual, expected, message );
+               this.push( expected == actual, actual, expected, message );
        },
 
        /**
@@ -1546,7 +1332,7 @@ assert = QUnit.assert = {
         */
        notEqual: function( actual, expected, message ) {
                /*jshint eqeqeq:false */
-               QUnit.push( expected != actual, actual, expected, message );
+               this.push( expected != actual, actual, expected, message );
        },
 
        /**
@@ -1554,9 +1340,9 @@ assert = QUnit.assert = {
         * @function
         */
        propEqual: function( actual, expected, message ) {
-               actual = objectValues(actual);
-               expected = objectValues(expected);
-               QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
+               actual = objectValues( actual );
+               expected = objectValues( expected );
+               this.push( QUnit.equiv( actual, expected ), actual, expected, message );
        },
 
        /**
@@ -1564,9 +1350,9 @@ assert = QUnit.assert = {
         * @function
         */
        notPropEqual: function( actual, expected, message ) {
-               actual = objectValues(actual);
-               expected = objectValues(expected);
-               QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
+               actual = objectValues( actual );
+               expected = objectValues( expected );
+               this.push( !QUnit.equiv( actual, expected ), actual, expected, message );
        },
 
        /**
@@ -1574,7 +1360,7 @@ assert = QUnit.assert = {
         * @function
         */
        deepEqual: function( actual, expected, message ) {
-               QUnit.push( QUnit.equiv(actual, expected), actual, expected, message );
+               this.push( QUnit.equiv( actual, expected ), actual, expected, message );
        },
 
        /**
@@ -1582,7 +1368,7 @@ assert = QUnit.assert = {
         * @function
         */
        notDeepEqual: function( actual, expected, message ) {
-               QUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );
+               this.push( !QUnit.equiv( actual, expected ), actual, expected, message );
        },
 
        /**
@@ -1590,7 +1376,7 @@ assert = QUnit.assert = {
         * @function
         */
        strictEqual: function( actual, expected, message ) {
-               QUnit.push( expected === actual, actual, expected, message );
+               this.push( expected === actual, actual, expected, message );
        },
 
        /**
@@ -1598,90 +1384,73 @@ assert = QUnit.assert = {
         * @function
         */
        notStrictEqual: function( actual, expected, message ) {
-               QUnit.push( expected !== actual, actual, expected, message );
+               this.push( expected !== actual, actual, expected, message );
        },
 
        "throws": function( block, expected, message ) {
-               var actual,
+               var actual, expectedType,
                        expectedOutput = expected,
                        ok = false;
 
-               // 'expected' is optional
-               if ( !message && typeof expected === "string" ) {
+               // 'expected' is optional unless doing string comparison
+               if ( message == null && typeof expected === "string" ) {
                        message = expected;
                        expected = null;
                }
 
-               config.current.ignoreGlobalErrors = true;
+               this.test.ignoreGlobalErrors = true;
                try {
-                       block.call( config.current.testEnvironment );
+                       block.call( this.test.testEnvironment );
                } catch (e) {
                        actual = e;
                }
-               config.current.ignoreGlobalErrors = false;
+               this.test.ignoreGlobalErrors = false;
 
                if ( actual ) {
+                       expectedType = QUnit.objectType( expected );
 
                        // we don't want to validate thrown error
                        if ( !expected ) {
                                ok = true;
                                expectedOutput = null;
 
-                       // expected is an Error object
-                       } else if ( expected instanceof Error ) {
-                               ok = actual instanceof Error &&
-                                        actual.name === expected.name &&
-                                        actual.message === expected.message;
-
                        // expected is a regexp
-                       } else if ( QUnit.objectType( expected ) === "regexp" ) {
+                       } else if ( expectedType === "regexp" ) {
                                ok = expected.test( errorString( actual ) );
 
                        // expected is a string
-                       } else if ( QUnit.objectType( expected ) === "string" ) {
+                       } else if ( expectedType === "string" ) {
                                ok = expected === errorString( actual );
 
-                       // expected is a constructor
-                       } else if ( actual instanceof expected ) {
+                       // expected is a constructor, maybe an Error constructor
+                       } else if ( expectedType === "function" && actual instanceof expected ) {
                                ok = true;
 
-                       // expected is a validation function which returns true is validation passed
-                       } else if ( expected.call( {}, actual ) === true ) {
+                       // expected is an Error object
+                       } else if ( expectedType === "object" ) {
+                               ok = actual instanceof expected.constructor &&
+                                       actual.name === expected.name &&
+                                       actual.message === expected.message;
+
+                       // expected is a validation function which returns true if validation passed
+                       } else if ( expectedType === "function" && expected.call( {}, actual ) === true ) {
                                expectedOutput = null;
                                ok = true;
                        }
 
-                       QUnit.push( ok, actual, expectedOutput, message );
+                       this.push( ok, actual, expectedOutput, message );
                } else {
-                       QUnit.pushFailure( message, null, "No exception was thrown." );
+                       this.test.pushFailure( message, null, "No exception was thrown." );
                }
        }
 };
 
-/**
- * @deprecated since 1.8.0
- * Kept assertion helpers in root for backwards compatibility.
- */
-extend( QUnit.constructor.prototype, assert );
-
-/**
- * @deprecated since 1.9.0
- * Kept to avoid TypeErrors for undefined methods.
- */
-QUnit.constructor.prototype.raises = function() {
-       QUnit.push( false, false, false, "QUnit.raises has been deprecated since 2012 (fad3c1ea), use QUnit.throws instead" );
-};
-
-/**
- * @deprecated since 1.0.0, replaced with error pushes since 1.3.0
- * Kept to avoid TypeErrors for undefined methods.
- */
-QUnit.constructor.prototype.equals = function() {
-       QUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );
-};
-QUnit.constructor.prototype.same = function() {
-       QUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" );
-};
+// Provide an alternative to assert.throws(), for enviroments that consider throws a reserved word
+// Known to us are: Closure Compiler, Narwhal
+(function() {
+       /*jshint sub:true */
+       Assert.prototype.raises = Assert.prototype[ "throws" ];
+}());
 
 // Test for equality any JavaScript type.
 // Author: Philippe Rathé <prathe@gmail.com>
@@ -1701,22 +1470,26 @@ QUnit.equiv = (function() {
 
        // the real equiv function
        var innerEquiv,
+
                // stack to decide between skip/abort functions
                callers = [],
+
                // stack to avoiding loops from circular referencing
                parents = [],
                parentsB = [],
 
-               getProto = Object.getPrototypeOf || function ( obj ) {
-                       /*jshint camelcase:false */
+               getProto = Object.getPrototypeOf || function( obj ) {
+                       /* jshint camelcase: false, proto: true */
                        return obj.__proto__;
                },
-               callbacks = (function () {
+               callbacks = (function() {
 
                        // for string, boolean, number and null
                        function useStrictEquality( b, a ) {
+
                                /*jshint eqeqeq:false */
                                if ( b instanceof a.constructor || a instanceof b.constructor ) {
+
                                        // to catch short annotation VS 'new' annotation of a
                                        // declaration
                                        // e.g. var i = 1;
@@ -1744,10 +1517,13 @@ QUnit.equiv = (function() {
 
                                "regexp": function( b, a ) {
                                        return QUnit.objectType( b ) === "regexp" &&
+
                                                // the regex itself
                                                a.source === b.source &&
+
                                                // and its modifiers
                                                a.global === b.global &&
+
                                                // (gmi) ...
                                                a.ignoreCase === b.ignoreCase &&
                                                a.multiline === b.multiline &&
@@ -1758,7 +1534,7 @@ QUnit.equiv = (function() {
                                // - abort otherwise,
                                // initial === would have catch identical references anyway
                                "function": function() {
-                                       var caller = callers[callers.length - 1];
+                                       var caller = callers[ callers.length - 1 ];
                                        return caller !== Object && typeof caller !== "undefined";
                                },
 
@@ -1782,10 +1558,10 @@ QUnit.equiv = (function() {
                                        for ( i = 0; i < len; i++ ) {
                                                loop = false;
                                                for ( j = 0; j < parents.length; j++ ) {
-                                                       aCircular = parents[j] === a[i];
-                                                       bCircular = parentsB[j] === b[i];
+                                                       aCircular = parents[ j ] === a[ i ];
+                                                       bCircular = parentsB[ j ] === b[ i ];
                                                        if ( aCircular || bCircular ) {
-                                                               if ( a[i] === b[i] || aCircular && bCircular ) {
+                                                               if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
                                                                        loop = true;
                                                                } else {
                                                                        parents.pop();
@@ -1794,7 +1570,7 @@ QUnit.equiv = (function() {
                                                                }
                                                        }
                                                }
-                                               if ( !loop && !innerEquiv(a[i], b[i]) ) {
+                                               if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
                                                        parents.pop();
                                                        parentsB.pop();
                                                        return false;
@@ -1806,6 +1582,7 @@ QUnit.equiv = (function() {
                                },
 
                                "object": function( b, a ) {
+
                                        /*jshint forin:false */
                                        var i, j, loop, aCircular, bCircular,
                                                // Default to true
@@ -1816,11 +1593,12 @@ QUnit.equiv = (function() {
                                        // comparing constructors is more strict than using
                                        // instanceof
                                        if ( a.constructor !== b.constructor ) {
+
                                                // Allow objects with no prototype to be equivalent to
                                                // objects with Object as their constructor.
-                                               if ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||
-                                                       ( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {
-                                                               return false;
+                                               if ( !( ( getProto( a ) === null && getProto( b ) === Object.prototype ) ||
+                                                       ( getProto( b ) === null && getProto( a ) === Object.prototype ) ) ) {
+                                                       return false;
                                                }
                                        }
 
@@ -1835,10 +1613,10 @@ QUnit.equiv = (function() {
                                        for ( i in a ) {
                                                loop = false;
                                                for ( j = 0; j < parents.length; j++ ) {
-                                                       aCircular = parents[j] === a[i];
-                                                       bCircular = parentsB[j] === b[i];
+                                                       aCircular = parents[ j ] === a[ i ];
+                                                       bCircular = parentsB[ j ] === b[ i ];
                                                        if ( aCircular || bCircular ) {
-                                                               if ( a[i] === b[i] || aCircular && bCircular ) {
+                                                               if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
                                                                        loop = true;
                                                                } else {
                                                                        eq = false;
@@ -1846,8 +1624,8 @@ QUnit.equiv = (function() {
                                                                }
                                                        }
                                                }
-                                               aProperties.push(i);
-                                               if ( !loop && !innerEquiv(a[i], b[i]) ) {
+                                               aProperties.push( i );
+                                               if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
                                                        eq = false;
                                                        break;
                                                }
@@ -1873,35 +1651,30 @@ QUnit.equiv = (function() {
                        return true; // end transition
                }
 
-               return (function( a, b ) {
+               return ( (function( a, b ) {
                        if ( a === b ) {
                                return true; // catch the most you can
                        } else if ( a === null || b === null || typeof a === "undefined" ||
                                        typeof b === "undefined" ||
-                                       QUnit.objectType(a) !== QUnit.objectType(b) ) {
-                               return false; // don't lose time with error prone cases
-                       } else {
-                               return bindCallbacks(a, callbacks, [ b, a ]);
+                                       QUnit.objectType( a ) !== QUnit.objectType( b ) ) {
+
+                               // don't lose time with error prone cases
+                               return false;
+                       } else {
+                               return bindCallbacks( a, callbacks, [ b, a ] );
                        }
 
                        // apply transition with (1..n) arguments
-               }( args[0], args[1] ) && innerEquiv.apply( this, args.splice(1, args.length - 1 )) );
+               }( args[ 0 ], args[ 1 ] ) ) &&
+                       innerEquiv.apply( this, args.splice( 1, args.length - 1 ) ) );
        };
 
        return innerEquiv;
 }());
 
-/**
- * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |
- * http://flesler.blogspot.com Licensed under BSD
- * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008
- *
- * @projectDescription Advanced and extensible data dumping for Javascript.
- * @version 1.0.0
- * @author Ariel Flesler
- * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}
- */
-QUnit.jsDump = (function() {
+// Based on jsDump by Ariel Flesler
+// http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html
+QUnit.dump = (function() {
        function quote( str ) {
                return "\"" + str.toString().replace( /"/g, "\\\"" ) + "\"";
        }
@@ -1909,48 +1682,57 @@ QUnit.jsDump = (function() {
                return o + "";
        }
        function join( pre, arr, post ) {
-               var s = jsDump.separator(),
-                       base = jsDump.indent(),
-                       inner = jsDump.indent(1);
+               var s = dump.separator(),
+                       base = dump.indent(),
+                       inner = dump.indent( 1 );
                if ( arr.join ) {
                        arr = arr.join( "," + s + inner );
                }
                if ( !arr ) {
                        return pre + post;
                }
-               return [ pre, inner + arr, base + post ].join(s);
+               return [ pre, inner + arr, base + post ].join( s );
        }
        function array( arr, stack ) {
-               var i = arr.length, ret = new Array(i);
+               var i = arr.length,
+                       ret = new Array( i );
+
+               if ( dump.maxDepth && dump.depth > dump.maxDepth ) {
+                       return "[object Array]";
+               }
+
                this.up();
                while ( i-- ) {
-                       ret[i] = this.parse( arr[i] , undefined , stack);
+                       ret[ i ] = this.parse( arr[ i ], undefined, stack );
                }
                this.down();
                return join( "[", ret, "]" );
        }
 
        var reName = /^function (\w+)/,
-               jsDump = {
-                       // type is used mostly internally, you can fix a (custom)type in advance
-                       parse: function( obj, type, stack ) {
-                               stack = stack || [ ];
-                               var inStack, res,
-                                       parser = this.parsers[ type || this.typeOf(obj) ];
+               dump = {
 
-                               type = typeof parser;
-                               inStack = inArray( obj, stack );
+                       // objType is used mostly internally, you can fix a (custom) type in advance
+                       parse: function( obj, objType, stack ) {
+                               stack = stack || [];
+                               var res, parser, parserType,
+                                       inStack = inArray( obj, stack );
 
                                if ( inStack !== -1 ) {
-                                       return "recursion(" + (inStack - stack.length) + ")";
+                                       return "recursion(" + ( inStack - stack.length ) + ")";
                                }
-                               if ( type === "function" )  {
+
+                               objType = objType || this.typeOf( obj  );
+                               parser = this.parsers[ objType ];
+                               parserType = typeof parser;
+
+                               if ( parserType === "function" ) {
                                        stack.push( obj );
                                        res = parser.call( this, obj, stack );
                                        stack.pop();
                                        return res;
                                }
-                               return ( type === "string" ) ? parser : this.parsers.error;
+                               return ( parserType === "string" ) ? parser : this.parsers.error;
                        },
                        typeOf: function( obj ) {
                                var type;
@@ -1958,23 +1740,29 @@ QUnit.jsDump = (function() {
                                        type = "null";
                                } else if ( typeof obj === "undefined" ) {
                                        type = "undefined";
-                               } else if ( QUnit.is( "regexp", obj) ) {
+                               } else if ( QUnit.is( "regexp", obj ) ) {
                                        type = "regexp";
-                               } else if ( QUnit.is( "date", obj) ) {
+                               } else if ( QUnit.is( "date", obj ) ) {
                                        type = "date";
-                               } else if ( QUnit.is( "function", obj) ) {
+                               } else if ( QUnit.is( "function", obj ) ) {
                                        type = "function";
-                               } else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) {
+                               } else if ( obj.setInterval !== undefined &&
+                                               obj.document !== undefined &&
+                                               obj.nodeType === undefined ) {
                                        type = "window";
                                } else if ( obj.nodeType === 9 ) {
                                        type = "document";
                                } else if ( obj.nodeType ) {
                                        type = "node";
                                } else if (
+
                                        // native arrays
                                        toString.call( obj ) === "[object Array]" ||
+
                                        // NodeList objects
-                                       ( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )
+                                       ( typeof obj.length === "number" && obj.item !== undefined &&
+                                       ( obj.length ? obj.item( 0 ) === obj[ 0 ] : ( obj.item( 0 ) === null &&
+                                       obj[ 0 ] === undefined ) ) )
                                ) {
                                        type = "array";
                                } else if ( obj.constructor === Error.prototype.constructor ) {
@@ -1985,7 +1773,7 @@ QUnit.jsDump = (function() {
                                return type;
                        },
                        separator: function() {
-                               return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&nbsp;" : " ";
+                               return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&#160;" : " ";
                        },
                        // extra can be a number, shortcut for increasing-calling-decreasing
                        indent: function( extra ) {
@@ -1994,9 +1782,9 @@ QUnit.jsDump = (function() {
                                }
                                var chr = this.indentChar;
                                if ( this.HTML ) {
-                                       chr = chr.replace( /\t/g, "   " ).replace( / /g, "&nbsp;" );
+                                       chr = chr.replace( /\t/g, "   " ).replace( / /g, "&#160;" );
                                }
-                               return new Array( this.depth + ( extra || 0 ) ).join(chr);
+                               return new Array( this.depth + ( extra || 0 ) ).join( chr );
                        },
                        up: function( a ) {
                                this.depth += a || 1;
@@ -2005,7 +1793,7 @@ QUnit.jsDump = (function() {
                                this.depth -= a || 1;
                        },
                        setParser: function( name, parser ) {
-                               this.parsers[name] = parser;
+                               this.parsers[ name ] = parser;
                        },
                        // The next 3 are exposed so you can use them
                        quote: quote,
@@ -2013,11 +1801,13 @@ QUnit.jsDump = (function() {
                        join: join,
                        //
                        depth: 1,
-                       // This is the list of parsers, to modify them, use jsDump.setParser
+                       maxDepth: 5,
+
+                       // This is the list of parsers, to modify them, use dump.setParser
                        parsers: {
                                window: "[Window]",
                                document: "[Document]",
-                               error: function(error) {
+                               error: function( error ) {
                                        return "Error(\"" + error.message + "\")";
                                },
                                unknown: "[Unknown]",
@@ -2025,52 +1815,71 @@ QUnit.jsDump = (function() {
                                "undefined": "undefined",
                                "function": function( fn ) {
                                        var ret = "function",
+
                                                // functions never have name in IE
-                                               name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];
+                                               name = "name" in fn ? fn.name : ( reName.exec( fn ) || [] )[ 1 ];
 
                                        if ( name ) {
                                                ret += " " + name;
                                        }
                                        ret += "( ";
 
-                                       ret = [ ret, QUnit.jsDump.parse( fn, "functionArgs" ), "){" ].join( "" );
-                                       return join( ret, QUnit.jsDump.parse(fn,"functionCode" ), "}" );
+                                       ret = [ ret, dump.parse( fn, "functionArgs" ), "){" ].join( "" );
+                                       return join( ret, dump.parse( fn, "functionCode" ), "}" );
                                },
                                array: array,
                                nodelist: array,
                                "arguments": array,
                                object: function( map, stack ) {
-                                       /*jshint forin:false */
-                                       var ret = [ ], keys, key, val, i;
-                                       QUnit.jsDump.up();
+                                       var keys, key, val, i, nonEnumerableProperties,
+                                               ret = [];
+
+                                       if ( dump.maxDepth && dump.depth > dump.maxDepth ) {
+                                               return "[object Object]";
+                                       }
+
+                                       dump.up();
                                        keys = [];
                                        for ( key in map ) {
                                                keys.push( key );
                                        }
+
+                                       // Some properties are not always enumerable on Error objects.
+                                       nonEnumerableProperties = [ "message", "name" ];
+                                       for ( i in nonEnumerableProperties ) {
+                                               key = nonEnumerableProperties[ i ];
+                                               if ( key in map && !( key in keys ) ) {
+                                                       keys.push( key );
+                                               }
+                                       }
                                        keys.sort();
                                        for ( i = 0; i < keys.length; i++ ) {
                                                key = keys[ i ];
                                                val = map[ key ];
-                                               ret.push( QUnit.jsDump.parse( key, "key" ) + ": " + QUnit.jsDump.parse( val, undefined, stack ) );
+                                               ret.push( dump.parse( key, "key" ) + ": " +
+                                                       dump.parse( val, undefined, stack ) );
                                        }
-                                       QUnit.jsDump.down();
+                                       dump.down();
                                        return join( "{", ret, "}" );
                                },
                                node: function( node ) {
                                        var len, i, val,
-                                               open = QUnit.jsDump.HTML ? "&lt;" : "<",
-                                               close = QUnit.jsDump.HTML ? "&gt;" : ">",
+                                               open = dump.HTML ? "&lt;" : "<",
+                                               close = dump.HTML ? "&gt;" : ">",
                                                tag = node.nodeName.toLowerCase(),
                                                ret = open + tag,
                                                attrs = node.attributes;
 
                                        if ( attrs ) {
                                                for ( i = 0, len = attrs.length; i < len; i++ ) {
-                                                       val = attrs[i].nodeValue;
-                                                       // IE6 includes all attributes in .attributes, even ones not explicitly set.
-                                                       // Those have values like undefined, null, 0, false, "" or "inherit".
+                                                       val = attrs[ i ].nodeValue;
+
+                                                       // IE6 includes all attributes in .attributes, even ones not explicitly
+                                                       // set. Those have values like undefined, null, 0, false, "" or
+                                                       // "inherit".
                                                        if ( val && val !== "inherit" ) {
-                                                               ret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" );
+                                                               ret += " " + attrs[ i ].nodeName + "=" +
+                                                                       dump.parse( val, "attribute" );
                                                        }
                                                }
                                        }
@@ -2083,6 +1892,7 @@ QUnit.jsDump = (function() {
 
                                        return ret + open + "/" + tag + close;
                                },
+
                                // function calls it internally, it's the arguments part of the function
                                functionArgs: function( fn ) {
                                        var args,
@@ -2092,10 +1902,11 @@ QUnit.jsDump = (function() {
                                                return "";
                                        }
 
-                                       args = new Array(l);
+                                       args = new Array( l );
                                        while ( l-- ) {
+
                                                // 97 is 'a'
-                                               args[l] = String.fromCharCode(97+l);
+                                               args[ l ] = String.fromCharCode( 97 + l );
                                        }
                                        return " " + args.join( ", " ) + " ";
                                },
@@ -2119,9 +1930,79 @@ QUnit.jsDump = (function() {
                        multiline: true
                };
 
-       return jsDump;
+       return dump;
 }());
 
+// back compat
+QUnit.jsDump = QUnit.dump;
+
+// For browser, export only select globals
+if ( typeof window !== "undefined" ) {
+
+       // Deprecated
+       // Extend assert methods to QUnit and Global scope through Backwards compatibility
+       (function() {
+               var i,
+                       assertions = Assert.prototype;
+
+               function applyCurrent( current ) {
+                       return function() {
+                               var assert = new Assert( QUnit.config.current );
+                               current.apply( assert, arguments );
+                       };
+               }
+
+               for ( i in assertions ) {
+                       QUnit[ i ] = applyCurrent( assertions[ i ] );
+               }
+       })();
+
+       (function() {
+               var i, l,
+                       keys = [
+                               "test",
+                               "module",
+                               "expect",
+                               "asyncTest",
+                               "start",
+                               "stop",
+                               "ok",
+                               "equal",
+                               "notEqual",
+                               "propEqual",
+                               "notPropEqual",
+                               "deepEqual",
+                               "notDeepEqual",
+                               "strictEqual",
+                               "notStrictEqual",
+                               "throws"
+                       ];
+
+               for ( i = 0, l = keys.length; i < l; i++ ) {
+                       window[ keys[ i ] ] = QUnit[ keys[ i ] ];
+               }
+       })();
+
+       window.QUnit = QUnit;
+}
+
+// For nodejs
+if ( typeof module !== "undefined" && module.exports ) {
+       module.exports = QUnit;
+}
+
+// For CommonJS with exports, but without module.exports, like Rhino
+if ( typeof exports !== "undefined" ) {
+       exports.QUnit = QUnit;
+}
+
+// Get a reference to the global object, like window in browsers
+}( (function() {
+       return this;
+})() ));
+
+/*istanbul ignore next */
+// jscs:disable maximumLineLength
 /*
  * Javascript Diff Algorithm
  *  By John Resig (http://ejohn.org/)
@@ -2137,6 +2018,8 @@ QUnit.jsDump = (function() {
  * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"
  */
 QUnit.diff = (function() {
+       var hasOwn = Object.prototype.hasOwnProperty;
+
        /*jshint eqeqeq:false, eqnull:true */
        function diff( o, n ) {
                var i,
@@ -2144,65 +2027,65 @@ QUnit.diff = (function() {
                        os = {};
 
                for ( i = 0; i < n.length; i++ ) {
-                       if ( !hasOwn.call( ns, n[i] ) ) {
-                               ns[ n[i] ] = {
+                       if ( !hasOwn.call( ns, n[ i ] ) ) {
+                               ns[ n[ i ] ] = {
                                        rows: [],
                                        o: null
                                };
                        }
-                       ns[ n[i] ].rows.push( i );
+                       ns[ n[ i ] ].rows.push( i );
                }
 
                for ( i = 0; i < o.length; i++ ) {
-                       if ( !hasOwn.call( os, o[i] ) ) {
-                               os[ o[i] ] = {
+                       if ( !hasOwn.call( os, o[ i ] ) ) {
+                               os[ o[ i ] ] = {
                                        rows: [],
                                        n: null
                                };
                        }
-                       os[ o[i] ].rows.push( i );
+                       os[ o[ i ] ].rows.push( i );
                }
 
                for ( i in ns ) {
                        if ( hasOwn.call( ns, i ) ) {
-                               if ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {
-                                       n[ ns[i].rows[0] ] = {
-                                               text: n[ ns[i].rows[0] ],
-                                               row: os[i].rows[0]
+                               if ( ns[ i ].rows.length === 1 && hasOwn.call( os, i ) && os[ i ].rows.length === 1 ) {
+                                       n[ ns[ i ].rows[ 0 ] ] = {
+                                               text: n[ ns[ i ].rows[ 0 ] ],
+                                               row: os[ i ].rows[ 0 ]
                                        };
-                                       o[ os[i].rows[0] ] = {
-                                               text: o[ os[i].rows[0] ],
-                                               row: ns[i].rows[0]
+                                       o[ os[ i ].rows[ 0 ] ] = {
+                                               text: o[ os[ i ].rows[ 0 ] ],
+                                               row: ns[ i ].rows[ 0 ]
                                        };
                                }
                        }
                }
 
                for ( i = 0; i < n.length - 1; i++ ) {
-                       if ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&
-                                               n[ i + 1 ] == o[ n[i].row + 1 ] ) {
+                       if ( n[ i ].text != null && n[ i + 1 ].text == null && n[ i ].row + 1 < o.length && o[ n[ i ].row + 1 ].text == null &&
+                               n[ i + 1 ] == o[ n[ i ].row + 1 ] ) {
 
                                n[ i + 1 ] = {
                                        text: n[ i + 1 ],
-                                       row: n[i].row + 1
+                                       row: n[ i ].row + 1
                                };
-                               o[ n[i].row + 1 ] = {
-                                       text: o[ n[i].row + 1 ],
+                               o[ n[ i ].row + 1 ] = {
+                                       text: o[ n[ i ].row + 1 ],
                                        row: i + 1
                                };
                        }
                }
 
                for ( i = n.length - 1; i > 0; i-- ) {
-                       if ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&
-                                               n[ i - 1 ] == o[ n[i].row - 1 ]) {
+                       if ( n[ i ].text != null && n[ i - 1 ].text == null && n[ i ].row > 0 && o[ n[ i ].row - 1 ].text == null &&
+                               n[ i - 1 ] == o[ n[ i ].row - 1 ] ) {
 
                                n[ i - 1 ] = {
                                        text: n[ i - 1 ],
-                                       row: n[i].row - 1
+                                       row: n[ i ].row - 1
                                };
-                               o[ n[i].row - 1 ] = {
-                                       text: o[ n[i].row - 1 ],
+                               o[ n[ i ].row - 1 ] = {
+                                       text: o[ n[ i ].row - 1 ],
                                        row: i - 1
                                };
                        }
@@ -2220,48 +2103,45 @@ QUnit.diff = (function() {
 
                var i, pre,
                        str = "",
-                       out = diff( o === "" ? [] : o.split(/\s+/), n === "" ? [] : n.split(/\s+/) ),
-                       oSpace = o.match(/\s+/g),
-                       nSpace = n.match(/\s+/g);
+                       out = diff( o === "" ? [] : o.split( /\s+/ ), n === "" ? [] : n.split( /\s+/ ) ),
+                       oSpace = o.match( /\s+/g ),
+                       nSpace = n.match( /\s+/g );
 
                if ( oSpace == null ) {
                        oSpace = [ " " ];
-               }
-               else {
+               } else {
                        oSpace.push( " " );
                }
 
                if ( nSpace == null ) {
                        nSpace = [ " " ];
-               }
-               else {
+               } else {
                        nSpace.push( " " );
                }
 
                if ( out.n.length === 0 ) {
                        for ( i = 0; i < out.o.length; i++ ) {
-                               str += "<del>" + out.o[i] + oSpace[i] + "</del>";
+                               str += "<del>" + out.o[ i ] + oSpace[ i ] + "</del>";
                        }
-               }
-               else {
-                       if ( out.n[0].text == null ) {
-                               for ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {
-                                       str += "<del>" + out.o[n] + oSpace[n] + "</del>";
+               } else {
+                       if ( out.n[ 0 ].text == null ) {
+                               for ( n = 0; n < out.o.length && out.o[ n ].text == null; n++ ) {
+                                       str += "<del>" + out.o[ n ] + oSpace[ n ] + "</del>";
                                }
                        }
 
                        for ( i = 0; i < out.n.length; i++ ) {
-                               if (out.n[i].text == null) {
-                                       str += "<ins>" + out.n[i] + nSpace[i] + "</ins>";
-                               }
-                               else {
+                               if ( out.n[ i ].text == null ) {
+                                       str += "<ins>" + out.n[ i ] + nSpace[ i ] + "</ins>";
+                               } else {
+
                                        // `pre` initialized at top of scope
                                        pre = "";
 
-                                       for ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
-                                               pre += "<del>" + out.o[n] + oSpace[n] + "</del>";
+                                       for ( n = out.n[ i ].row + 1; n < out.o.length && out.o[ n ].text == null; n++ ) {
+                                               pre += "<del>" + out.o[ n ] + oSpace[ n ] + "</del>";
                                        }
-                                       str += " " + out.n[i].text + nSpace[i] + pre;
+                                       str += " " + out.n[ i ].text + nSpace[ i ] + pre;
                                }
                        }
                }
@@ -2269,20 +2149,671 @@ QUnit.diff = (function() {
                return str;
        };
 }());
+// jscs:enable
 
-// For browser, export only select globals
-if ( typeof window !== "undefined" ) {
-       extend( window, QUnit.constructor.prototype );
-       window.QUnit = QUnit;
+(function() {
+
+// Deprecated QUnit.init - Ref #530
+// Re-initialize the configuration options
+QUnit.init = function() {
+       var tests, banner, result, qunit,
+               config = QUnit.config;
+
+       config.stats = { all: 0, bad: 0 };
+       config.moduleStats = { all: 0, bad: 0 };
+       config.started = 0;
+       config.updateRate = 1000;
+       config.blocking = false;
+       config.autostart = true;
+       config.autorun = false;
+       config.filter = "";
+       config.queue = [];
+
+       // Return on non-browser environments
+       // This is necessary to not break on node tests
+       if ( typeof window === "undefined" ) {
+               return;
+       }
+
+       qunit = id( "qunit" );
+       if ( qunit ) {
+               qunit.innerHTML =
+                       "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
+                       "<h2 id='qunit-banner'></h2>" +
+                       "<div id='qunit-testrunner-toolbar'></div>" +
+                       "<h2 id='qunit-userAgent'></h2>" +
+                       "<ol id='qunit-tests'></ol>";
+       }
+
+       tests = id( "qunit-tests" );
+       banner = id( "qunit-banner" );
+       result = id( "qunit-testresult" );
+
+       if ( tests ) {
+               tests.innerHTML = "";
+       }
+
+       if ( banner ) {
+               banner.className = "";
+       }
+
+       if ( result ) {
+               result.parentNode.removeChild( result );
+       }
+
+       if ( tests ) {
+               result = document.createElement( "p" );
+               result.id = "qunit-testresult";
+               result.className = "result";
+               tests.parentNode.insertBefore( result, tests );
+               result.innerHTML = "Running...<br />&#160;";
+       }
+};
+
+// Don't load the HTML Reporter on non-Browser environments
+if ( typeof window === "undefined" ) {
+       return;
 }
 
-// For CommonJS environments, export everything
-if ( typeof module !== "undefined" && module.exports ) {
-       module.exports = QUnit;
+var config = QUnit.config,
+       hasOwn = Object.prototype.hasOwnProperty,
+       defined = {
+               document: window.document !== undefined,
+               sessionStorage: (function() {
+                       var x = "qunit-test-string";
+                       try {
+                               sessionStorage.setItem( x, x );
+                               sessionStorage.removeItem( x );
+                               return true;
+                       } catch ( e ) {
+                               return false;
+                       }
+               }())
+       },
+       modulesList = [];
+
+/**
+* Escape text for attribute or text content.
+*/
+function escapeText( s ) {
+       if ( !s ) {
+               return "";
+       }
+       s = s + "";
+
+       // Both single quotes and double quotes (for attributes)
+       return s.replace( /['"<>&]/g, function( s ) {
+               switch ( s ) {
+               case "'":
+                       return "&#039;";
+               case "\"":
+                       return "&quot;";
+               case "<":
+                       return "&lt;";
+               case ">":
+                       return "&gt;";
+               case "&":
+                       return "&amp;";
+               }
+       });
 }
 
+/**
+ * @param {HTMLElement} elem
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvent( elem, type, fn ) {
+       if ( elem.addEventListener ) {
 
-// Get a reference to the global object, like window in browsers
-}( (function() {
-       return this;
-})() ));
+               // Standards-based browsers
+               elem.addEventListener( type, fn, false );
+       } else if ( elem.attachEvent ) {
+
+               // support: IE <9
+               elem.attachEvent( "on" + type, fn );
+       }
+}
+
+/**
+ * @param {Array|NodeList} elems
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvents( elems, type, fn ) {
+       var i = elems.length;
+       while ( i-- ) {
+               addEvent( elems[ i ], type, fn );
+       }
+}
+
+function hasClass( elem, name ) {
+       return ( " " + elem.className + " " ).indexOf( " " + name + " " ) >= 0;
+}
+
+function addClass( elem, name ) {
+       if ( !hasClass( elem, name ) ) {
+               elem.className += ( elem.className ? " " : "" ) + name;
+       }
+}
+
+function toggleClass( elem, name ) {
+       if ( hasClass( elem, name ) ) {
+               removeClass( elem, name );
+       } else {
+               addClass( elem, name );
+       }
+}
+
+function removeClass( elem, name ) {
+       var set = " " + elem.className + " ";
+
+       // Class name may appear multiple times
+       while ( set.indexOf( " " + name + " " ) >= 0 ) {
+               set = set.replace( " " + name + " ", " " );
+       }
+
+       // trim for prettiness
+       elem.className = typeof set.trim === "function" ? set.trim() : set.replace( /^\s+|\s+$/g, "" );
+}
+
+function id( name ) {
+       return defined.document && document.getElementById && document.getElementById( name );
+}
+
+function getUrlConfigHtml() {
+       var i, j, val,
+               escaped, escapedTooltip,
+               selection = false,
+               len = config.urlConfig.length,
+               urlConfigHtml = "";
+
+       for ( i = 0; i < len; i++ ) {
+               val = config.urlConfig[ i ];
+               if ( typeof val === "string" ) {
+                       val = {
+                               id: val,
+                               label: val
+                       };
+               }
+
+               escaped = escapeText( val.id );
+               escapedTooltip = escapeText( val.tooltip );
+
+               config[ val.id ] = QUnit.urlParams[ val.id ];
+               if ( !val.value || typeof val.value === "string" ) {
+                       urlConfigHtml += "<input id='qunit-urlconfig-" + escaped +
+                               "' name='" + escaped + "' type='checkbox'" +
+                               ( val.value ? " value='" + escapeText( val.value ) + "'" : "" ) +
+                               ( config[ val.id ] ? " checked='checked'" : "" ) +
+                               " title='" + escapedTooltip + "' /><label for='qunit-urlconfig-" + escaped +
+                               "' title='" + escapedTooltip + "'>" + val.label + "</label>";
+               } else {
+                       urlConfigHtml += "<label for='qunit-urlconfig-" + escaped +
+                               "' title='" + escapedTooltip + "'>" + val.label +
+                               ": </label><select id='qunit-urlconfig-" + escaped +
+                               "' name='" + escaped + "' title='" + escapedTooltip + "'><option></option>";
+
+                       if ( QUnit.is( "array", val.value ) ) {
+                               for ( j = 0; j < val.value.length; j++ ) {
+                                       escaped = escapeText( val.value[ j ] );
+                                       urlConfigHtml += "<option value='" + escaped + "'" +
+                                               ( config[ val.id ] === val.value[ j ] ?
+                                                       ( selection = true ) && " selected='selected'" : "" ) +
+                                               ">" + escaped + "</option>";
+                               }
+                       } else {
+                               for ( j in val.value ) {
+                                       if ( hasOwn.call( val.value, j ) ) {
+                                               urlConfigHtml += "<option value='" + escapeText( j ) + "'" +
+                                                       ( config[ val.id ] === j ?
+                                                               ( selection = true ) && " selected='selected'" : "" ) +
+                                                       ">" + escapeText( val.value[ j ] ) + "</option>";
+                                       }
+                               }
+                       }
+                       if ( config[ val.id ] && !selection ) {
+                               escaped = escapeText( config[ val.id ] );
+                               urlConfigHtml += "<option value='" + escaped +
+                                       "' selected='selected' disabled='disabled'>" + escaped + "</option>";
+                       }
+                       urlConfigHtml += "</select>";
+               }
+       }
+
+       return urlConfigHtml;
+}
+
+// Handle "click" events on toolbar checkboxes and "change" for select menus.
+// Updates the URL with the new state of `config.urlConfig` values.
+function toolbarChanged() {
+       var updatedUrl, value,
+               field = this,
+               params = {};
+
+       // Detect if field is a select menu or a checkbox
+       if ( "selectedIndex" in field ) {
+               value = field.options[ field.selectedIndex ].value || undefined;
+       } else {
+               value = field.checked ? ( field.defaultValue || true ) : undefined;
+       }
+
+       params[ field.name ] = value;
+       updatedUrl = QUnit.url( params );
+
+       if ( "hidepassed" === field.name && "replaceState" in window.history ) {
+               config[ field.name ] = value || false;
+               if ( value ) {
+                       addClass( id( "qunit-tests" ), "hidepass" );
+               } else {
+                       removeClass( id( "qunit-tests" ), "hidepass" );
+               }
+
+               // It is not necessary to refresh the whole page
+               window.history.replaceState( null, "", updatedUrl );
+       } else {
+               window.location = updatedUrl;
+       }
+}
+
+function toolbarUrlConfigContainer() {
+       var urlConfigContainer = document.createElement( "span" );
+
+       urlConfigContainer.innerHTML = getUrlConfigHtml();
+
+       // For oldIE support:
+       // * Add handlers to the individual elements instead of the container
+       // * Use "click" instead of "change" for checkboxes
+       addEvents( urlConfigContainer.getElementsByTagName( "input" ), "click", toolbarChanged );
+       addEvents( urlConfigContainer.getElementsByTagName( "select" ), "change", toolbarChanged );
+
+       return urlConfigContainer;
+}
+
+function toolbarModuleFilterHtml() {
+       var i,
+               moduleFilterHtml = "";
+
+       if ( !modulesList.length ) {
+               return false;
+       }
+
+       modulesList.sort(function( a, b ) {
+               return a.localeCompare( b );
+       });
+
+       moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label>" +
+               "<select id='qunit-modulefilter' name='modulefilter'><option value='' " +
+               ( QUnit.urlParams.module === undefined ? "selected='selected'" : "" ) +
+               ">< All Modules ></option>";
+
+       for ( i = 0; i < modulesList.length; i++ ) {
+               moduleFilterHtml += "<option value='" +
+                       escapeText( encodeURIComponent( modulesList[ i ] ) ) + "' " +
+                       ( QUnit.urlParams.module === modulesList[ i ] ? "selected='selected'" : "" ) +
+                       ">" + escapeText( modulesList[ i ] ) + "</option>";
+       }
+       moduleFilterHtml += "</select>";
+
+       return moduleFilterHtml;
+}
+
+function toolbarModuleFilter() {
+       var toolbar = id( "qunit-testrunner-toolbar" ),
+               moduleFilter = document.createElement( "span" ),
+               moduleFilterHtml = toolbarModuleFilterHtml();
+
+       if ( !moduleFilterHtml ) {
+               return false;
+       }
+
+       moduleFilter.setAttribute( "id", "qunit-modulefilter-container" );
+       moduleFilter.innerHTML = moduleFilterHtml;
+
+       addEvent( moduleFilter.lastChild, "change", function() {
+               var selectBox = moduleFilter.getElementsByTagName( "select" )[ 0 ],
+                       selection = decodeURIComponent( selectBox.options[ selectBox.selectedIndex ].value );
+
+               window.location = QUnit.url({
+                       module: ( selection === "" ) ? undefined : selection,
+
+                       // Remove any existing filters
+                       filter: undefined,
+                       testId: undefined
+               });
+       });
+
+       toolbar.appendChild( moduleFilter );
+}
+
+function appendToolbar() {
+       var toolbar = id( "qunit-testrunner-toolbar" );
+
+       if ( toolbar ) {
+               toolbar.appendChild( toolbarUrlConfigContainer() );
+       }
+}
+
+function appendBanner() {
+       var banner = id( "qunit-banner" );
+
+       if ( banner ) {
+               banner.className = "";
+               banner.innerHTML = "<a href='" +
+                       QUnit.url({ filter: undefined, module: undefined, testId: undefined }) +
+                       "'>" + banner.innerHTML + "</a> ";
+       }
+}
+
+function appendTestResults() {
+       var tests = id( "qunit-tests" ),
+               result = id( "qunit-testresult" );
+
+       if ( result ) {
+               result.parentNode.removeChild( result );
+       }
+
+       if ( tests ) {
+               tests.innerHTML = "";
+               result = document.createElement( "p" );
+               result.id = "qunit-testresult";
+               result.className = "result";
+               tests.parentNode.insertBefore( result, tests );
+               result.innerHTML = "Running...<br />&#160;";
+       }
+}
+
+function storeFixture() {
+       var fixture = id( "qunit-fixture" );
+       if ( fixture ) {
+               config.fixture = fixture.innerHTML;
+       }
+}
+
+function appendUserAgent() {
+       var userAgent = id( "qunit-userAgent" );
+       if ( userAgent ) {
+               userAgent.innerHTML = navigator.userAgent;
+       }
+}
+
+function appendTestsList( modules ) {
+       var i, l, x, z, test, moduleObj;
+
+       for ( i = 0, l = modules.length; i < l; i++ ) {
+               moduleObj = modules[ i ];
+
+               if ( moduleObj.name ) {
+                       modulesList.push( moduleObj.name );
+               }
+
+               for ( x = 0, z = moduleObj.tests.length; x < z; x++ ) {
+                       test = moduleObj.tests[ x ];
+
+                       appendTest( test.name, test.testId, moduleObj.name );
+               }
+       }
+}
+
+function appendTest( name, testId, moduleName ) {
+       var title, rerunTrigger, testBlock, assertList,
+               tests = id( "qunit-tests" );
+
+       if ( !tests ) {
+               return;
+       }
+
+       title = document.createElement( "strong" );
+       title.innerHTML = getNameHtml( name, moduleName );
+
+       rerunTrigger = document.createElement( "a" );
+       rerunTrigger.innerHTML = "Rerun";
+       rerunTrigger.href = QUnit.url({ testId: testId });
+
+       testBlock = document.createElement( "li" );
+       testBlock.appendChild( title );
+       testBlock.appendChild( rerunTrigger );
+       testBlock.id = "qunit-test-output-" + testId;
+
+       assertList = document.createElement( "ol" );
+       assertList.className = "qunit-assert-list";
+
+       testBlock.appendChild( assertList );
+
+       tests.appendChild( testBlock );
+}
+
+// HTML Reporter initialization and load
+QUnit.begin(function( details ) {
+       var qunit = id( "qunit" );
+
+       // Fixture is the only one necessary to run without the #qunit element
+       storeFixture();
+
+       if ( !qunit ) {
+               return;
+       }
+
+       qunit.innerHTML =
+               "<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
+               "<h2 id='qunit-banner'></h2>" +
+               "<div id='qunit-testrunner-toolbar'></div>" +
+               "<h2 id='qunit-userAgent'></h2>" +
+               "<ol id='qunit-tests'></ol>";
+
+       appendBanner();
+       appendTestResults();
+       appendUserAgent();
+       appendToolbar();
+       appendTestsList( details.modules );
+       toolbarModuleFilter();
+
+       if ( config.hidepassed ) {
+               addClass( qunit.lastChild, "hidepass" );
+       }
+});
+
+QUnit.done(function( details ) {
+       var i, key,
+               banner = id( "qunit-banner" ),
+               tests = id( "qunit-tests" ),
+               html = [
+                       "Tests completed in ",
+                       details.runtime,
+                       " milliseconds.<br />",
+                       "<span class='passed'>",
+                       details.passed,
+                       "</span> assertions of <span class='total'>",
+                       details.total,
+                       "</span> passed, <span class='failed'>",
+                       details.failed,
+                       "</span> failed."
+               ].join( "" );
+
+       if ( banner ) {
+               banner.className = details.failed ? "qunit-fail" : "qunit-pass";
+       }
+
+       if ( tests ) {
+               id( "qunit-testresult" ).innerHTML = html;
+       }
+
+       if ( config.altertitle && defined.document && document.title ) {
+
+               // show ✖ for good, ✔ for bad suite result in title
+               // use escape sequences in case file gets loaded with non-utf-8-charset
+               document.title = [
+                       ( details.failed ? "\u2716" : "\u2714" ),
+                       document.title.replace( /^[\u2714\u2716] /i, "" )
+               ].join( " " );
+       }
+
+       // clear own sessionStorage items if all tests passed
+       if ( config.reorder && defined.sessionStorage && details.failed === 0 ) {
+               for ( i = 0; i < sessionStorage.length; i++ ) {
+                       key = sessionStorage.key( i++ );
+                       if ( key.indexOf( "qunit-test-" ) === 0 ) {
+                               sessionStorage.removeItem( key );
+                       }
+               }
+       }
+
+       // scroll back to top to show results
+       if ( config.scrolltop && window.scrollTo ) {
+               window.scrollTo( 0, 0 );
+       }
+});
+
+function getNameHtml( name, module ) {
+       var nameHtml = "";
+
+       if ( module ) {
+               nameHtml = "<span class='module-name'>" + escapeText( module ) + "</span>: ";
+       }
+
+       nameHtml += "<span class='test-name'>" + escapeText( name ) + "</span>";
+
+       return nameHtml;
+}
+
+QUnit.testStart(function( details ) {
+       var running, testBlock;
+
+       testBlock = id( "qunit-test-output-" + details.testId );
+       if ( testBlock ) {
+               testBlock.className = "running";
+       } else {
+
+               // Report later registered tests
+               appendTest( details.name, details.testId, details.module );
+       }
+
+       running = id( "qunit-testresult" );
+       if ( running ) {
+               running.innerHTML = "Running: <br />" + getNameHtml( details.name, details.module );
+       }
+
+});
+
+QUnit.log(function( details ) {
+       var assertList, assertLi,
+               message, expected, actual,
+               testItem = id( "qunit-test-output-" + details.testId );
+
+       if ( !testItem ) {
+               return;
+       }
+
+       message = escapeText( details.message ) || ( details.result ? "okay" : "failed" );
+       message = "<span class='test-message'>" + message + "</span>";
+       message += "<span class='runtime'>@ " + details.runtime + " ms</span>";
+
+       // pushFailure doesn't provide details.expected
+       // when it calls, it's implicit to also not show expected and diff stuff
+       // Also, we need to check details.expected existence, as it can exist and be undefined
+       if ( !details.result && hasOwn.call( details, "expected" ) ) {
+               expected = escapeText( QUnit.dump.parse( details.expected ) );
+               actual = escapeText( QUnit.dump.parse( details.actual ) );
+               message += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" +
+                       expected +
+                       "</pre></td></tr>";
+
+               if ( actual !== expected ) {
+                       message += "<tr class='test-actual'><th>Result: </th><td><pre>" +
+                               actual + "</pre></td></tr>" +
+                               "<tr class='test-diff'><th>Diff: </th><td><pre>" +
+                               QUnit.diff( expected, actual ) + "</pre></td></tr>";
+               }
+
+               if ( details.source ) {
+                       message += "<tr class='test-source'><th>Source: </th><td><pre>" +
+                               escapeText( details.source ) + "</pre></td></tr>";
+               }
+
+               message += "</table>";
+
+       // this occours when pushFailure is set and we have an extracted stack trace
+       } else if ( !details.result && details.source ) {
+               message += "<table>" +
+                       "<tr class='test-source'><th>Source: </th><td><pre>" +
+                       escapeText( details.source ) + "</pre></td></tr>" +
+                       "</table>";
+       }
+
+       assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
+
+       assertLi = document.createElement( "li" );
+       assertLi.className = details.result ? "pass" : "fail";
+       assertLi.innerHTML = message;
+       assertList.appendChild( assertLi );
+});
+
+QUnit.testDone(function( details ) {
+       var testTitle, time, testItem, assertList,
+               good, bad, testCounts, skipped,
+               tests = id( "qunit-tests" );
+
+       if ( !tests ) {
+               return;
+       }
+
+       testItem = id( "qunit-test-output-" + details.testId );
+
+       assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
+
+       good = details.passed;
+       bad = details.failed;
+
+       // store result when possible
+       if ( config.reorder && defined.sessionStorage ) {
+               if ( bad ) {
+                       sessionStorage.setItem( "qunit-test-" + details.module + "-" + details.name, bad );
+               } else {
+                       sessionStorage.removeItem( "qunit-test-" + details.module + "-" + details.name );
+               }
+       }
+
+       if ( bad === 0 ) {
+               addClass( assertList, "qunit-collapsed" );
+       }
+
+       // testItem.firstChild is the test name
+       testTitle = testItem.firstChild;
+
+       testCounts = bad ?
+               "<b class='failed'>" + bad + "</b>, " + "<b class='passed'>" + good + "</b>, " :
+               "";
+
+       testTitle.innerHTML += " <b class='counts'>(" + testCounts +
+               details.assertions.length + ")</b>";
+
+       if ( details.skipped ) {
+               addClass( testItem, "skipped" );
+               skipped = document.createElement( "em" );
+               skipped.className = "qunit-skipped-label";
+               skipped.innerHTML = "skipped";
+               testItem.insertBefore( skipped, testTitle );
+       } else {
+               addEvent( testTitle, "click", function() {
+                       toggleClass( assertList, "qunit-collapsed" );
+               });
+
+               testItem.className = bad ? "fail" : "pass";
+
+               time = document.createElement( "span" );
+               time.className = "runtime";
+               time.innerHTML = details.runtime + " ms";
+               testItem.insertBefore( time, assertList );
+       }
+});
+
+if ( !defined.document || document.readyState === "complete" ) {
+       config.pageLoaded = true;
+       config.autorun = true;
+}
+
+if ( defined.document ) {
+       addEvent( window, "load", QUnit.load );
+}
+
+})();
index 1b8c520..2fb7adf 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('af', {
@@ -26,6 +26,7 @@
         },
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -54,6 +55,7 @@
             y : '\'n jaar',
             yy : '%d jaar'
         },
+        ordinalParse: /\d{1,2}(ste|de)/,
         ordinal : function (number) {
             return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter
         },
index 5b2095a..7add172 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('ar-ma', {
@@ -20,6 +20,7 @@
         weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
index f7867ea..ea7e2f6 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var symbolMap = {
@@ -43,6 +43,7 @@
         weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -79,7 +80,7 @@
             yy : '%d سنوات'
         },
         preparse: function (string) {
-            return string.replace(/[۰-۹]/g, function (match) {
+            return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
                 return numberMap[match];
             }).replace(/،/g, ',');
         },
index 1791a6b..d645008 100644 (file)
@@ -10,7 +10,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var symbolMap = {
@@ -76,6 +76,7 @@
         weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
             yy : pluralize('y')
         },
         preparse: function (string) {
-            return string.replace(/[۰-۹]/g, function (match) {
+            return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
                 return numberMap[match];
             }).replace(/،/g, ',');
         },
index e82f6e1..d4d1434 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var suffixes = {
@@ -44,6 +44,7 @@
         weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD.MM.YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -83,6 +84,7 @@
                 return 'axşam';
             }
         },
+        ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,
         ordinal : function (number) {
             if (number === 0) {  // special case for zero
                 return number + '-ıncı';
index fe3186a..68a6f37 100644 (file)
@@ -10,7 +10,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function plural(word, num) {
@@ -71,6 +71,7 @@
         weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD.MM.YYYY',
             LL : 'D MMMM YYYY г.',
             LLL : 'D MMMM YYYY г., LT',
             }
         },
 
+        ordinalParse: /\d{1,2}-(і|ы|га)/,
         ordinal: function (number, period) {
             switch (period) {
             case 'M':
index 41b1e3a..540e17b 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('bg', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
         longDateFormat : {
             LT : 'H:mm',
+            LTS : 'LT:ss',
             L : 'D.MM.YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -59,6 +60,7 @@
             y : 'година',
             yy : '%d години'
         },
+        ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
         ordinal : function (number) {
             var lastDigit = number % 10,
                 last2Digits = number % 100;
index 7e8ccfd..e9549d9 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var symbolMap = {
@@ -44,6 +44,7 @@
         weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'),
         longDateFormat : {
             LT : 'A h:mm সময়',
+            LTS : 'A h:mm:ss সময়',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY, LT',
index 0d44e47..cece8d1 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var symbolMap = {
@@ -44,6 +44,7 @@
         weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
         longDateFormat : {
             LT : 'A h:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY, LT',
index a4f1491..1f8dd61 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function relativeTimeWithMutation(number, withoutSuffix, key) {
@@ -67,6 +67,7 @@
         weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'),
         longDateFormat : {
             LT : 'h[e]mm A',
+            LTS : 'h[e]mm:ss A',
             L : 'DD/MM/YYYY',
             LL : 'D [a viz] MMMM YYYY',
             LLL : 'D [a viz] MMMM YYYY LT',
@@ -95,6 +96,7 @@
             y : 'ur bloaz',
             yy : specialMutationForYears
         },
+        ordinalParse: /\d{1,2}(añ|vet)/,
         ordinal : function (number) {
             var output = (number === 1) ? 'añ' : 'vet';
             return number + output;
index b9a5851..c59f46b 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function translate(number, withoutSuffix, key) {
     }
 
     return moment.defineLocale('bs', {
-        months : 'januar_februar_mart_april_maj_juni_juli_avgust_septembar_oktobar_novembar_decembar'.split('_'),
-        monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'),
+        months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'),
+        monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'),
         weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
         weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
         weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
         longDateFormat : {
             LT : 'H:mm',
+            LTS : 'LT:ss',
             L : 'DD. MM. YYYY',
             LL : 'D. MMMM YYYY',
             LLL : 'D. MMMM YYYY LT',
             y      : 'godinu',
             yy     : translate
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index fd41ff5..4f0d3fe 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('ca', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'),
         longDateFormat : {
             LT : 'H:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
             y : 'un any',
             yy : '%d anys'
         },
-        ordinal : '%dº',
+        ordinalParse: /\d{1,2}(r|n|t|è|a)/,
+        ordinal : function (number, period) {
+            var output = (number === 1) ? 'r' :
+                (number === 2) ? 'n' :
+                (number === 3) ? 'r' :
+                (number === 4) ? 't' : 'è';
+            if (period === 'w' || period === 'W') {
+                output = 'a';
+            }
+            return number + output;
+        },
         week : {
             dow : 1, // Monday is the first day of the week.
             doy : 4  // The week that contains Jan 4th is the first week of the year.
index 87dec55..b61658d 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'),
@@ -87,7 +87,8 @@
         weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'),
         longDateFormat : {
             LT: 'H:mm',
-            L : 'DD. MM. YYYY',
+            LTS : 'LT:ss',
+            L : 'DD.MM.YYYY',
             LL : 'D. MMMM YYYY',
             LLL : 'D. MMMM YYYY LT',
             LLLL : 'dddd D. MMMM YYYY LT'
             y : translate,
             yy : translate
         },
+        ordinalParse : /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 138b6c1..ea8e314 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('cv', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'вр_тн_ыт_юн_кç_эр_шм'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD-MM-YYYY',
             LL : 'YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ]',
             LLL : 'YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT',
@@ -50,6 +51,7 @@
             y : 'пĕр çул',
             yy : '%d çул'
         },
+        ordinalParse: /\d{1,2}-мĕш/,
         ordinal : '%d-мĕш',
         week : {
             dow : 1, // Monday is the first day of the week.
index 65fb356..72b2f91 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('cy', {
@@ -20,6 +20,7 @@
         // time formats are the same as en-gb
         longDateFormat: {
             LT: 'HH:mm',
+            LTS : 'LT:ss',
             L: 'DD/MM/YYYY',
             LL: 'D MMMM YYYY',
             LLL: 'D MMMM YYYY LT',
@@ -48,6 +49,7 @@
             y: 'blwyddyn',
             yy: '%d flynedd'
         },
+        ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/,
         // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
         ordinal: function (number) {
             var b = number,
index 5e9ef96..686ce00 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('da', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D. MMMM YYYY',
             LLL : 'D. MMMM YYYY LT',
@@ -47,6 +48,7 @@
             y : 'et år',
             yy : '%d år'
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index ff715f8..c982638 100644 (file)
@@ -10,7 +10,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function processRelativeTime(number, withoutSuffix, key, isFuture) {
         weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
         weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
         longDateFormat : {
-            LT: 'HH:mm [Uhr]',
+            LT: 'HH:mm',
+            LTS: 'HH:mm:ss',
             L : 'DD.MM.YYYY',
             LL : 'D. MMMM YYYY',
             LLL : 'D. MMMM YYYY LT',
             LLLL : 'dddd, D. MMMM YYYY LT'
         },
         calendar : {
-            sameDay: '[Heute um] LT',
+            sameDay: '[Heute um] LT [Uhr]',
             sameElse: 'L',
-            nextDay: '[Morgen um] LT',
-            nextWeek: 'dddd [um] LT',
-            lastDay: '[Gestern um] LT',
-            lastWeek: '[letzten] dddd [um] LT'
+            nextDay: '[Morgen um] LT [Uhr]',
+            nextWeek: 'dddd [um] LT [Uhr]',
+            lastDay: '[Gestern um] LT [Uhr]',
+            lastWeek: '[letzten] dddd [um] LT [Uhr]'
         },
         relativeTime : {
             future : 'in %s',
@@ -63,6 +64,7 @@
             y : processRelativeTime,
             yy : processRelativeTime
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 11ab9ac..f6d89a9 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function processRelativeTime(number, withoutSuffix, key, isFuture) {
         weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
         weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
         longDateFormat : {
-            LT: 'HH:mm [Uhr]',
+            LT: 'HH:mm',
+            LTS: 'HH:mm:ss',
             L : 'DD.MM.YYYY',
             LL : 'D. MMMM YYYY',
             LLL : 'D. MMMM YYYY LT',
             LLLL : 'dddd, D. MMMM YYYY LT'
         },
         calendar : {
-            sameDay: '[Heute um] LT',
+            sameDay: '[Heute um] LT [Uhr]',
             sameElse: 'L',
-            nextDay: '[Morgen um] LT',
-            nextWeek: 'dddd [um] LT',
-            lastDay: '[Gestern um] LT',
-            lastWeek: '[letzten] dddd [um] LT'
+            nextDay: '[Morgen um] LT [Uhr]',
+            nextWeek: 'dddd [um] LT [Uhr]',
+            lastDay: '[Gestern um] LT [Uhr]',
+            lastWeek: '[letzten] dddd [um] LT [Uhr]'
         },
         relativeTime : {
             future : 'in %s',
@@ -62,6 +63,7 @@
             y : processRelativeTime,
             yy : processRelativeTime
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index eb8eb1a..6dc769e 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('el', {
@@ -38,6 +38,7 @@
         meridiemParse : /[ΠΜ]\.?Μ?\.?/i,
         longDateFormat : {
             LT : 'h:mm A',
+            LTS : 'h:mm:ss A',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -71,7 +72,7 @@
         relativeTime : {
             future : 'σε %s',
             past : '%s πριν',
-            s : 'δευτερόλεπτα',
+            s : 'λίγα Î´ÎµÏ\85Ï\84εÏ\81Ï\8cλεÏ\80Ï\84α',
             m : 'ένα λεπτό',
             mm : '%d λεπτά',
             h : 'μία ώρα',
@@ -83,9 +84,8 @@
             y : 'ένας χρόνος',
             yy : '%d χρόνια'
         },
-        ordinal : function (number) {
-            return number + 'η';
-        },
+        ordinalParse: /\d{1,2}η/,
+        ordinal: '%dη',
         week : {
             dow : 1, // Monday is the first day of the week.
             doy : 4  // The week that contains Jan 4st is the first week of the year.
index 75ad34a..a382b0a 100644 (file)
@@ -7,7 +7,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('en-au', {
@@ -18,6 +18,7 @@
         weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
         longDateFormat : {
             LT : 'h:mm A',
+            LTS : 'h:mm:ss A',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -46,6 +47,7 @@
             y : 'a year',
             yy : '%d years'
         },
+        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
         ordinal : function (number) {
             var b = number % 10,
                 output = (~~(number % 100 / 10) === 1) ? 'th' :
index 077dc8b..2dec8a6 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('en-ca', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
         longDateFormat : {
             LT : 'h:mm A',
+            LTS : 'h:mm:ss A',
             L : 'YYYY-MM-DD',
             LL : 'D MMMM, YYYY',
             LLL : 'D MMMM, YYYY LT',
@@ -47,6 +48,7 @@
             y : 'a year',
             yy : '%d years'
         },
+        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
         ordinal : function (number) {
             var b = number % 10,
                 output = (~~(number % 100 / 10) === 1) ? 'th' :
index 4491d4a..4ea2b29 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('en-gb', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -47,6 +48,7 @@
             y : 'a year',
             yy : '%d years'
         },
+        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
         ordinal : function (number) {
             var b = number % 10,
                 output = (~~(number % 100 / 10) === 1) ? 'th' :
index 735ed8e..6a3d097 100644 (file)
@@ -10,7 +10,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('eo', {
@@ -21,6 +21,7 @@
         weekdaysMin : 'Di_Lu_Ma_Me_Ĵa_Ve_Sa'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'YYYY-MM-DD',
             LL : 'D[-an de] MMMM, YYYY',
             LLL : 'D[-an de] MMMM, YYYY LT',
@@ -56,6 +57,7 @@
             y : 'jaro',
             yy : '%d jaroj'
         },
+        ordinalParse: /\d{1,2}a/,
         ordinal : '%da',
         week : {
             dow : 1, // Monday is the first day of the week.
index 04b83a8..b6e30b1 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'),
@@ -28,6 +28,7 @@
         weekdaysMin : 'Do_Lu_Ma_Mi_Ju_Vi_Sá'.split('_'),
         longDateFormat : {
             LT : 'H:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D [de] MMMM [de] YYYY',
             LLL : 'D [de] MMMM [de] YYYY LT',
@@ -66,6 +67,7 @@
             y : 'un año',
             yy : '%d años'
         },
+        ordinalParse : /\d{1,2}º/,
         ordinal : '%dº',
         week : {
             dow : 1, // Monday is the first day of the week.
index 242ee16..7dbcee7 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function processRelativeTime(number, withoutSuffix, key, isFuture) {
@@ -39,6 +39,7 @@
         weekdaysMin   : 'P_E_T_K_N_R_L'.split('_'),
         longDateFormat : {
             LT   : 'H:mm',
+            LTS : 'LT:ss',
             L    : 'DD.MM.YYYY',
             LL   : 'D. MMMM YYYY',
             LLL  : 'D. MMMM YYYY LT',
@@ -67,6 +68,7 @@
             y      : processRelativeTime,
             yy     : processRelativeTime
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 8fb89b4..c455c46 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('eu', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'YYYY-MM-DD',
             LL : 'YYYY[ko] MMMM[ren] D[a]',
             LLL : 'YYYY[ko] MMMM[ren] D[a] LT',
@@ -51,6 +52,7 @@
             y : 'urte bat',
             yy : '%d urte'
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index b1151bd..ad2087a 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var symbolMap = {
@@ -43,6 +43,7 @@
         weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -88,6 +89,7 @@
                 return symbolMap[match];
             }).replace(/,/g, '،');
         },
+        ordinalParse: /\d{1,2}م/,
         ordinal : '%dم',
         week : {
             dow : 6, // Saturday is the first day of the week.
index 1fedcab..f884c3e 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '),
@@ -64,6 +64,7 @@
         weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'),
         longDateFormat : {
             LT : 'HH.mm',
+            LTS : 'HH.mm.ss',
             L : 'DD.MM.YYYY',
             LL : 'Do MMMM[ta] YYYY',
             LLL : 'Do MMMM[ta] YYYY, [klo] LT',
@@ -96,6 +97,7 @@
             y : translate,
             yy : translate
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index a27f9da..6b940e8 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('fo', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -47,6 +48,7 @@
             y : 'eitt ár',
             yy : '%d ár'
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index c0f1bdc..6cac1b8 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('fr-ca', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'YYYY-MM-DD',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -47,6 +48,7 @@
             y : 'un an',
             yy : '%d ans'
         },
+        ordinalParse: /\d{1,2}(er|)/,
         ordinal : function (number) {
             return number + (number === 1 ? 'er' : '');
         }
index f217ff1..4a7cbcc 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('fr', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -47,6 +48,7 @@
             y : 'un an',
             yy : '%d ans'
         },
+        ordinalParse: /\d{1,2}(er|)/,
         ordinal : function (number) {
             return number + (number === 1 ? 'er' : '');
         },
index ac63862..5ff9e3f 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('gl', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'Do_Lu_Ma_Mé_Xo_Ve_Sá'.split('_'),
         longDateFormat : {
             LT : 'H:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -62,6 +63,7 @@
             y : 'un ano',
             yy : '%d anos'
         },
+        ordinalParse : /\d{1,2}º/,
         ordinal : '%dº',
         week : {
             dow : 1, // Monday is the first day of the week.
index 06f954f..9f9f470 100644 (file)
@@ -10,7 +10,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('he', {
@@ -21,6 +21,7 @@
         weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D [ב]MMMM YYYY',
             LLL : 'D [ב]MMMM YYYY LT',
index 4e64560..73deba5 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var symbolMap = {
@@ -44,6 +44,7 @@
         weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
         longDateFormat : {
             LT : 'A h:mm बजे',
+            LTS : 'A h:mm:ss बजे',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY, LT',
index 9e3f6fa..65264dc 100644 (file)
@@ -10,7 +10,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function translate(number, withoutSuffix, key) {
@@ -74,6 +74,7 @@
         weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
         longDateFormat : {
             LT : 'H:mm',
+            LTS : 'LT:ss',
             L : 'DD. MM. YYYY',
             LL : 'D. MMMM YYYY',
             LLL : 'D. MMMM YYYY LT',
             y      : 'godinu',
             yy     : translate
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 73fdb83..7eccd1d 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' ');
@@ -57,6 +57,7 @@
         weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'),
         longDateFormat : {
             LT : 'H:mm',
+            LTS : 'LT:ss',
             L : 'YYYY.MM.DD.',
             LL : 'YYYY. MMMM D.',
             LLL : 'YYYY. MMMM D., LT',
@@ -96,6 +97,7 @@
             y : translate,
             yy : translate
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index affcd7e..053a845 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function monthsCaseReplace(m, format) {
@@ -44,6 +44,7 @@
         weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD.MM.YYYY',
             LL : 'D MMMM YYYY թ.',
             LLL : 'D MMMM YYYY թ., LT',
@@ -89,6 +90,7 @@
             }
         },
 
+        ordinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/,
         ordinal: function (number, period) {
             switch (period) {
             case 'DDD':
index 143426a..36a841a 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('id', {
@@ -20,6 +20,7 @@
         weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'),
         longDateFormat : {
             LT : 'HH.mm',
+            LTS : 'LT.ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY [pukul] LT',
index 479f82d..21888aa 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function plural(n) {
@@ -87,6 +87,7 @@
         weekdaysMin : 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'),
         longDateFormat : {
             LT : 'H:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D. MMMM YYYY',
             LLL : 'D. MMMM YYYY [kl.] LT',
             y : translate,
             yy : translate
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 6695390..9d14714 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('it', {
@@ -20,6 +20,7 @@
         weekdaysMin : 'D_L_Ma_Me_G_V_S'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
             nextDay: '[Domani alle] LT',
             nextWeek: 'dddd [alle] LT',
             lastDay: '[Ieri alle] LT',
-            lastWeek: '[lo scorso] dddd [alle] LT',
+            lastWeek: function () {
+                switch (this.day()) {
+                    case 0:
+                        return '[la scorsa] dddd [alle] LT';
+                    default:
+                        return '[lo scorso] dddd [alle] LT';
+                }
+            },
             sameElse: 'L'
         },
         relativeTime : {
@@ -50,6 +58,7 @@
             y : 'un anno',
             yy : '%d anni'
         },
+        ordinalParse : /\d{1,2}º/,
         ordinal: '%dº',
         week : {
             dow : 1, // Monday is the first day of the week.
index f14fa4e..3f55bcf 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('ja', {
@@ -19,6 +19,7 @@
         weekdaysMin : '日_月_火_水_木_金_土'.split('_'),
         longDateFormat : {
             LT : 'Ah時m分',
+            LTS : 'LTs秒',
             L : 'YYYY/MM/DD',
             LL : 'YYYY年M月D日',
             LLL : 'YYYY年M月D日LT',
index 73eb9c7..b56e18c 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function monthsCaseReplace(m, format) {
@@ -45,6 +45,7 @@
         weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'),
         longDateFormat : {
             LT : 'h:mm A',
+            LTS : 'h:mm:ss A',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -84,6 +85,7 @@
             y : 'წელი',
             yy : '%d წელი'
         },
+        ordinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/,
         ordinal : function (number) {
             if (number === 0) {
                 return number;
index 9ba4888..8d7b9b8 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('km', {
@@ -19,6 +19,7 @@
         weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
         longDateFormat: {
             LT: 'HH:mm',
+            LTS : 'LT:ss',
             L: 'DD/MM/YYYY',
             LL: 'D MMMM YYYY',
             LLL: 'D MMMM YYYY LT',
index 57017f5..956345b 100644 (file)
@@ -11,7 +11,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('ko', {
@@ -22,6 +22,7 @@
         weekdaysMin : '일_월_화_수_목_금_토'.split('_'),
         longDateFormat : {
             LT : 'A h시 m분',
+            LTS : 'A h시 m분 s초',
             L : 'YYYY.MM.DD',
             LL : 'YYYY년 MMMM D일',
             LLL : 'YYYY년 MMMM D일 LT',
@@ -54,6 +55,7 @@
             y : '일년',
             yy : '%d년'
         },
+        ordinalParse : /\d{1,2}일/,
         ordinal : '%d일',
         meridiemParse : /(오전|오후)/,
         isPM : function (token) {
index 14fab97..2e84dab 100644 (file)
@@ -12,7 +12,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function processRelativeTime(number, withoutSuffix, key, isFuture) {
@@ -91,6 +91,7 @@
         weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'),
         longDateFormat: {
             LT: 'H:mm [Auer]',
+            LTS: 'H:mm:ss [Auer]',
             L: 'DD.MM.YYYY',
             LL: 'D. MMMM YYYY',
             LLL: 'D. MMMM YYYY LT',
             y : processRelativeTime,
             yy : '%d Joer'
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal: '%d.',
         week: {
             dow: 1, // Monday is the first day of the week.
index 013f8f1..2d87e04 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var units = {
@@ -75,6 +75,7 @@
         weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'YYYY-MM-DD',
             LL : 'YYYY [m.] MMMM D [d.]',
             LLL : 'YYYY [m.] MMMM D [d.], LT [val.]',
             y : translateSingular,
             yy : translate
         },
+        ordinalParse: /\d{1,2}-oji/,
         ordinal : function (number) {
             return number + '-oji';
         },
index 7e1892e..47a0708 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var units = {
@@ -40,6 +40,7 @@
         weekdaysMin : 'Sv_P_O_T_C_Pk_S'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD.MM.YYYY',
             LL : 'YYYY. [gada] D. MMMM',
             LLL : 'YYYY. [gada] D. MMMM, LT',
@@ -68,6 +69,7 @@
             y : 'gadu',
             yy : relativeTimeWithPlural
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 94c7fc1..de36631 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('mk', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'),
         longDateFormat : {
             LT : 'H:mm',
+            LTS : 'LT:ss',
             L : 'D.MM.YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -59,6 +60,7 @@
             y : 'година',
             yy : '%d години'
         },
+        ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
         ordinal : function (number) {
             var lastDigit = number % 10,
                 last2Digits = number % 100;
index ea4d949..3850914 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('ml', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'),
         longDateFormat : {
             LT : 'A h:mm -നു',
+            LTS : 'A h:mm:ss -നു',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY, LT',
index 141eaf8..45c200e 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var symbolMap = {
@@ -44,6 +44,7 @@
         weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
         longDateFormat : {
             LT : 'A h:mm वाजता',
+            LTS : 'A h:mm:ss वाजता',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY, LT',
index 7efcbaa..09ec280 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('ms-my', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
         longDateFormat : {
             LT : 'HH.mm',
+            LTS : 'LT.ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY [pukul] LT',
index 138d101..31f5c9e 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var symbolMap = {
@@ -42,6 +42,7 @@
         weekdaysMin: 'နွေ_လာ_င်္ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
         longDateFormat: {
             LT: 'HH:mm',
+            LTS: 'HH:mm:ss',
             L: 'DD/MM/YYYY',
             LL: 'D MMMM YYYY',
             LLL: 'D MMMM YYYY LT',
index 533659d..4764b50 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('nb', {
@@ -20,6 +20,7 @@
         weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
         longDateFormat : {
             LT : 'H.mm',
+            LTS : 'LT.ss',
             L : 'DD.MM.YYYY',
             LL : 'D. MMMM YYYY',
             LLL : 'D. MMMM YYYY [kl.] LT',
@@ -48,6 +49,7 @@
             y : 'ett år',
             yy : '%d år'
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 51629eb..ceb2834 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var symbolMap = {
@@ -44,6 +44,7 @@
         weekdaysMin : 'आइ._सो._मङ्_बु._बि._शु._श.'.split('_'),
         longDateFormat : {
             LT : 'Aको h:mm बजे',
+            LTS : 'Aको h:mm:ss बजे',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY, LT',
index 213beeb..9f4fdfe 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_'),
@@ -28,6 +28,7 @@
         weekdaysMin : 'Zo_Ma_Di_Wo_Do_Vr_Za'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD-MM-YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -56,6 +57,7 @@
             y : 'één jaar',
             yy : '%d jaar'
         },
+        ordinalParse: /\d{1,2}(ste|de)/,
         ordinal : function (number) {
             return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
         },
index c5b6505..d7a8238 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('nn', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD.MM.YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -47,6 +48,7 @@
             y : 'eit år',
             yy : '%d år'
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 63a62f1..418ca81 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_'),
@@ -50,6 +50,7 @@
         weekdaysMin : 'N_Pn_Wt_Śr_Cz_Pt_So'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD.MM.YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -89,6 +90,7 @@
             y : 'rok',
             yy : translate
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 44eedaf..813c2de 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('pt-br', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'dom_2ª_3ª_4ª_5ª_6ª_sáb'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D [de] MMMM [de] YYYY',
             LLL : 'D [de] MMMM [de] YYYY [às] LT',
@@ -51,6 +52,7 @@
             y : 'um ano',
             yy : '%d anos'
         },
+        ordinalParse: /\d{1,2}º/,
         ordinal : '%dº'
     });
 }));
index aced692..4afd564 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('pt', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'dom_2ª_3ª_4ª_5ª_6ª_sáb'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D [de] MMMM [de] YYYY',
             LLL : 'D [de] MMMM [de] YYYY LT',
@@ -51,6 +52,7 @@
             y : 'um ano',
             yy : '%d anos'
         },
+        ordinalParse: /\d{1,2}º/,
         ordinal : '%dº',
         week : {
             dow : 1, // Monday is the first day of the week.
index dc34d3c..fcc7d07 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function relativeTimeWithPlural(number, withoutSuffix, key) {
@@ -36,6 +36,7 @@
         weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'),
         longDateFormat : {
             LT : 'H:mm',
+            LTS : 'LT:ss',
             L : 'DD.MM.YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY H:mm',
index 2f15233..5adfa9a 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function plural(word, num) {
@@ -48,7 +48,7 @@
 
     function monthsShortCaseReplace(m, format) {
         var monthsShort = {
-            'nominative': 'янв_фев_мар_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'),
+            'nominative': 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'),
             'accusative': 'янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек'.split('_')
         },
 
@@ -65,7 +65,7 @@
             'accusative': 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_')
         },
 
-        nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую)? ?\] ?dddd/).test(format) ?
+        nounCase = (/\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/).test(format) ?
             'accusative' :
             'nominative';
 
@@ -81,6 +81,7 @@
         monthsParse : [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[й|я]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i],
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD.MM.YYYY',
             LL : 'D MMMM YYYY г.',
             LLL : 'D MMMM YYYY г., LT',
             nextWeek: function () {
                 return this.day() === 2 ? '[Во] dddd [в] LT' : '[В] dddd [в] LT';
             },
-            lastWeek: function () {
-                switch (this.day()) {
-                case 0:
-                    return '[В прошлое] dddd [в] LT';
-                case 1:
-                case 2:
-                case 4:
-                    return '[В прошлый] dddd [в] LT';
-                case 3:
-                case 5:
-                case 6:
-                    return '[В прошлую] dddd [в] LT';
+            lastWeek: function (now) {
+                if (now.week() !== this.week()) {
+                    switch (this.day()) {
+                    case 0:
+                        return '[В прошлое] dddd [в] LT';
+                    case 1:
+                    case 2:
+                    case 4:
+                        return '[В прошлый] dddd [в] LT';
+                    case 3:
+                    case 5:
+                    case 6:
+                        return '[В прошлую] dddd [в] LT';
+                    }
+                } else {
+                    if (this.day() === 2) {
+                        return '[Во] dddd [в] LT';
+                    } else {
+                        return '[В] dddd [в] LT';
+                    }
                 }
             },
             sameElse: 'L'
             }
         },
 
+        ordinalParse: /\d{1,2}-(й|го|я)/,
         ordinal: function (number, period) {
             switch (period) {
             case 'M':
index 991afeb..f9d74c5 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_'),
@@ -88,6 +88,7 @@
         weekdaysMin : 'ne_po_ut_st_št_pi_so'.split('_'),
         longDateFormat : {
             LT: 'H:mm',
+            LTS : 'LT:ss',
             L : 'DD.MM.YYYY',
             LL : 'D. MMMM YYYY',
             LLL : 'D. MMMM YYYY LT',
             y : translate,
             yy : translate
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 2bdbf1c..232695f 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function translate(number, withoutSuffix, key) {
@@ -80,6 +80,7 @@
         weekdaysMin : 'ne_po_to_sr_če_pe_so'.split('_'),
         longDateFormat : {
             LT : 'H:mm',
+            LTS : 'LT:ss',
             L : 'DD. MM. YYYY',
             LL : 'D. MMMM YYYY',
             LLL : 'D. MMMM YYYY LT',
             y      : 'eno leto',
             yy     : translate
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 6ae4178..415495a 100644 (file)
@@ -10,7 +10,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('sq', {
@@ -24,6 +24,7 @@
         },
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -52,6 +53,7 @@
             y : 'një vit',
             yy : '%d vite'
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 7278de6..57619b6 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var translator = {
@@ -42,6 +42,7 @@
         weekdaysMin: ['не', 'по', 'ут', 'ср', 'че', 'пе', 'су'],
         longDateFormat: {
             LT: 'H:mm',
+            LTS : 'LT:ss',
             L: 'DD. MM. YYYY',
             LL: 'D. MMMM YYYY',
             LLL: 'D. MMMM YYYY LT',
@@ -96,6 +97,7 @@
             y      : 'годину',
             yy     : translator.translate
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index d008282..6f14284 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var translator = {
@@ -42,6 +42,7 @@
         weekdaysMin: ['ne', 'po', 'ut', 'sr', 'če', 'pe', 'su'],
         longDateFormat: {
             LT: 'H:mm',
+            LTS : 'LT:ss',
             L: 'DD. MM. YYYY',
             LL: 'D. MMMM YYYY',
             LLL: 'D. MMMM YYYY LT',
@@ -96,6 +97,7 @@
             y      : 'godinu',
             yy     : translator.translate
         },
+        ordinalParse: /\d{1,2}\./,
         ordinal : '%d.',
         week : {
             dow : 1, // Monday is the first day of the week.
index 634b3cf..6e14958 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('sv', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'YYYY-MM-DD',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -47,6 +48,7 @@
             y : 'ett år',
             yy : '%d år'
         },
+        ordinalParse: /\d{1,2}(e|a)/,
         ordinal : function (number) {
             var b = number % 10,
                 output = (~~(number % 100 / 10) === 1) ? 'e' :
index 53bab0d..d0356a3 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     /*var symbolMap = {
@@ -44,6 +44,7 @@
         weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY, LT',
@@ -82,6 +83,7 @@
                 return symbolMap[match];
             });
         },*/
+        ordinalParse: /\d{1,2}வது/,
         ordinal : function (number) {
             return number + 'வது';
         },
index fc99701..e3c5422 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('th', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'),
         longDateFormat : {
             LT : 'H นาฬิกา m นาที',
+            LTS : 'LT s วินาที',
             L : 'YYYY/MM/DD',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY เวลา LT',
index c15cc1f..40dbb07 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('tl-ph', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'MM/D/YYYY',
             LL : 'MMMM D, YYYY',
             LLL : 'MMMM D, YYYY LT',
@@ -47,6 +48,7 @@
             y : 'isang taon',
             yy : '%d taon'
         },
+        ordinalParse: /\d{1,2}/,
         ordinal : function (number) {
             return number;
         },
index 36e8fca..cd0a746 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     var suffixes = {
@@ -46,6 +46,7 @@
         weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD.MM.YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
@@ -74,6 +75,7 @@
             y : 'bir yıl',
             yy : '%d yıl'
         },
+        ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,
         ordinal : function (number) {
             if (number === 0) {  // special case for zero
                 return number + '\'ıncı';
index 3189772..34592b4 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('tzm-latn', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
index 0a7f3f1..9591521 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('tzm', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS: 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
index bc22fff..3dce4bc 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     function plural(word, num) {
@@ -79,6 +79,7 @@
         weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD.MM.YYYY',
             LL : 'D MMMM YYYY р.',
             LLL : 'D MMMM YYYY р., LT',
             }
         },
 
+        ordinalParse: /\d{1,2}-(й|го)/,
         ordinal: function (number, period) {
             switch (period) {
             case 'M':
index 62fb89e..139e4de 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('uz', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM YYYY',
             LLL : 'D MMMM YYYY LT',
index 20e3ffe..15ec7dd 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('vi', {
@@ -19,6 +19,7 @@
         weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
         longDateFormat : {
             LT : 'HH:mm',
+            LTS : 'LT:ss',
             L : 'DD/MM/YYYY',
             LL : 'D MMMM [năm] YYYY',
             LLL : 'D MMMM [năm] YYYY LT',
@@ -51,6 +52,7 @@
             y : 'một năm',
             yy : '%d năm'
         },
+        ordinalParse: /\d{1,2}/,
         ordinal : function (number) {
             return number;
         },
index aff26c5..b8a0bd2 100644 (file)
@@ -9,7 +9,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('zh-cn', {
@@ -20,6 +20,7 @@
         weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
         longDateFormat : {
             LT : 'Ah点mm',
+            LTS : 'Ah点m分s秒',
             L : 'YYYY-MM-DD',
             LL : 'YYYY年MMMD日',
             LLL : 'YYYY年MMMD日LT',
@@ -69,6 +70,7 @@
             },
             sameElse : 'LL'
         },
+        ordinalParse: /\d{1,2}(日|月|周)/,
         ordinal : function (number, period) {
             switch (period) {
             case 'd':
index 71f99a2..b3c4439 100644 (file)
@@ -8,7 +8,7 @@
     } else if (typeof exports === 'object') {
         module.exports = factory(require('../moment')); // Node
     } else {
-        factory(window.moment); // Browser global
+        factory((typeof global !== 'undefined' ? global : this).moment); // node or other global
     }
 }(function (moment) {
     return moment.defineLocale('zh-tw', {
@@ -19,6 +19,7 @@
         weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
         longDateFormat : {
             LT : 'Ah點mm',
+            LTS : 'Ah點m分s秒',
             L : 'YYYY年MMMD日',
             LL : 'YYYY年MMMD日',
             LLL : 'YYYY年MMMD日LT',
@@ -50,6 +51,7 @@
             lastWeek : '[上]ddddLT',
             sameElse : 'L'
         },
+        ordinalParse: /\d{1,2}(日|月|週)/,
         ordinal : function (number, period) {
             switch (period) {
             case 'd' :
index d100a9c..85e190d 100644 (file)
@@ -1,5 +1,5 @@
 //! moment.js
-//! version : 2.8.3
+//! version : 2.8.4
 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
 //! license : MIT
 //! momentjs.com
@@ -10,7 +10,7 @@
     ************************************/
 
     var moment,
-        VERSION = '2.8.3',
+        VERSION = '2.8.4',
         // the global-scope this is NOT the global object in Node.js
         globalScope = typeof global !== 'undefined' ? global : this,
         oldGlobalMoment,
@@ -33,7 +33,7 @@
         momentProperties = [],
 
         // check for nodeJS
-        hasModule = (typeof module !== 'undefined' && module.exports),
+        hasModule = (typeof module !== 'undefined' && module && module.exports),
 
         // ASP.NET json date format regex
         aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
@@ -44,8 +44,8 @@
         isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
 
         // format tokens
-        formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
-        localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
+        formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,
+        localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,
 
         // parsing token regexes
         parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
@@ -56,8 +56,8 @@
         parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
         parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
         parseTokenT = /T/i, // T (ISO separator)
+        parseTokenOffsetMs = /[\+\-]?\d+/, // 1234567890123
         parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
-        parseTokenOrdinal = /\d{1,2}/,
 
         //strict parsing regexes
         parseTokenOneDigit = /\d/, // 0 - 9
             zz : function () {
                 return this.zoneName();
             },
+            x    : function () {
+                return this.valueOf();
+            },
             X    : function () {
                 return this.unix();
             },
             overflow =
                 m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
                 m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE :
-                m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR :
+                m._a[HOUR] < 0 || m._a[HOUR] > 24 ||
+                    (m._a[HOUR] === 24 && (m._a[MINUTE] !== 0 ||
+                                           m._a[SECOND] !== 0 ||
+                                           m._a[MILLISECOND] !== 0)) ? HOUR :
                 m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
                 m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
                 m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
             if (m._strict) {
                 m._isValid = m._isValid &&
                     m._pf.charsLeftOver === 0 &&
-                    m._pf.unusedTokens.length === 0;
+                    m._pf.unusedTokens.length === 0 &&
+                    m._pf.bigHour === undefined;
             }
         }
         return m._isValid;
 
     // Return a moment from input, that is local/utc/zone equivalent to model.
     function makeAs(input, model) {
-        return model._isUTC ? moment(input).zone(model._offset || 0) :
-            moment(input).local();
+        var res, diff;
+        if (model._isUTC) {
+            res = model.clone();
+            diff = (moment.isMoment(input) || isDate(input) ?
+                    +input : +moment(input)) - (+res);
+            // Use low-level api, because this fn is low-level api.
+            res._d.setTime(+res._d + diff);
+            moment.updateOffset(res, false);
+            return res;
+        } else {
+            return moment(input).local();
+        }
     }
 
     /************************************
                     this['_' + i] = prop;
                 }
             }
+            // Lenient ordinal parsing accepts just a number in addition to
+            // number + (possibly) stuff coming from _ordinalParseLenient.
+            this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + /\d{1,2}/.source);
         },
 
         _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
             return this._monthsShort[m.month()];
         },
 
-        monthsParse : function (monthName) {
+        monthsParse : function (monthName, format, strict) {
             var i, mom, regex;
 
             if (!this._monthsParse) {
                 this._monthsParse = [];
+                this._longMonthsParse = [];
+                this._shortMonthsParse = [];
             }
 
             for (i = 0; i < 12; i++) {
                 // make the regex if we don't have it already
-                if (!this._monthsParse[i]) {
-                    mom = moment.utc([2000, i]);
+                mom = moment.utc([2000, i]);
+                if (strict && !this._longMonthsParse[i]) {
+                    this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
+                    this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
+                }
+                if (!strict && !this._monthsParse[i]) {
                     regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
                     this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
                 }
                 // test the regex
-                if (this._monthsParse[i].test(monthName)) {
+                if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
+                    return i;
+                } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
+                    return i;
+                } else if (!strict && this._monthsParse[i].test(monthName)) {
                     return i;
                 }
             }
         },
 
         _longDateFormat : {
+            LTS : 'h:mm:ss A',
             LT : 'h:mm A',
             L : 'MM/DD/YYYY',
             LL : 'MMMM D, YYYY',
             lastWeek : '[Last] dddd [at] LT',
             sameElse : 'L'
         },
-        calendar : function (key, mom) {
+        calendar : function (key, mom, now) {
             var output = this._calendar[key];
-            return typeof output === 'function' ? output.apply(mom) : output;
+            return typeof output === 'function' ? output.apply(mom, [now]) : output;
         },
 
         _relativeTime : {
             return this._ordinal.replace('%d', number);
         },
         _ordinal : '%d',
+        _ordinalParse : /\d{1,2}/,
 
         preparse : function (string) {
             return string;
         case 'a':
         case 'A':
             return config._locale._meridiemParse;
+        case 'x':
+            return parseTokenOffsetMs;
         case 'X':
             return parseTokenTimestampMs;
         case 'Z':
         case 'E':
             return parseTokenOneOrTwoDigits;
         case 'Do':
-            return parseTokenOrdinal;
+            return strict ? config._locale._ordinalParse : config._locale._ordinalParseLenient;
         default :
             a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i'));
             return a;
             break;
         case 'MMM' : // fall through to MMMM
         case 'MMMM' :
-            a = config._locale.monthsParse(input);
+            a = config._locale.monthsParse(input, token, config._strict);
             // if we didn't find a month name, mark the date as invalid.
             if (a != null) {
                 datePartArray[MONTH] = a;
             break;
         case 'Do' :
             if (input != null) {
-                datePartArray[DATE] = toInt(parseInt(input, 10));
+                datePartArray[DATE] = toInt(parseInt(
+                            input.match(/\d{1,2}/)[0], 10));
             }
             break;
         // DAY OF YEAR
         case 'A' :
             config._isPm = config._locale.isPM(input);
             break;
-        // 24 HOUR
-        case 'H' : // fall through to hh
-        case 'HH' : // fall through to hh
+        // HOUR
         case 'h' : // fall through to hh
         case 'hh' :
+            config._pf.bigHour = true;
+            /* falls through */
+        case 'H' : // fall through to HH
+        case 'HH' :
             datePartArray[HOUR] = toInt(input);
             break;
         // MINUTE
         case 'SSSS' :
             datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
             break;
+        // UNIX OFFSET (MILLISECONDS)
+        case 'x':
+            config._d = new Date(toInt(input));
+            break;
         // UNIX TIMESTAMP WITH MS
         case 'X':
             config._d = new Date(parseFloat(input) * 1000);
             config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
         }
 
+        // Check for 24:00:00.000
+        if (config._a[HOUR] === 24 &&
+                config._a[MINUTE] === 0 &&
+                config._a[SECOND] === 0 &&
+                config._a[MILLISECOND] === 0) {
+            config._nextDay = true;
+            config._a[HOUR] = 0;
+        }
+
         config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
         // Apply timezone offset from input. The actual zone can be changed
         // with parseZone.
         if (config._tzm != null) {
             config._d.setUTCMinutes(config._d.getUTCMinutes() + config._tzm);
         }
+
+        if (config._nextDay) {
+            config._a[HOUR] = 24;
+        }
     }
 
     function dateFromObject(config) {
         config._a = [
             normalizedInput.year,
             normalizedInput.month,
-            normalizedInput.day,
+            normalizedInput.day || normalizedInput.date,
             normalizedInput.hour,
             normalizedInput.minute,
             normalizedInput.second,
             config._pf.unusedInput.push(string);
         }
 
+        // clear _12h flag if hour is <= 12
+        if (config._pf.bigHour === true && config._a[HOUR] <= 12) {
+            config._pf.bigHour = undefined;
+        }
         // handle am pm
         if (config._isPm && config._a[HOUR] < 12) {
             config._a[HOUR] += 12;
         if (config._isPm === false && config._a[HOUR] === 12) {
             config._a[HOUR] = 0;
         }
-
         dateFromConfig(config);
         checkOverflow(config);
     }
 
     function makeMoment(config) {
         var input = config._i,
-            format = config._f;
+            format = config._f,
+            res;
 
         config._locale = config._locale || moment.localeData(config._l);
 
             makeDateFromInput(config);
         }
 
-        return new Moment(config);
+        res = new Moment(config);
+        if (res._nextDay) {
+            // Adding is smart enough around DST
+            res.add(1, 'd');
+            res._nextDay = undefined;
+        }
+
+        return res;
     }
 
     moment = function (input, format, locale, strict) {
         'release. Please refer to ' +
         'https://github.com/moment/moment/issues/1407 for more info.',
         function (config) {
-            config._d = new Date(config._i);
+            config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
         }
     );
 
         toISOString : function () {
             var m = moment(this).utc();
             if (0 < m.year() && m.year() <= 9999) {
-                return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+                if ('function' === typeof Date.prototype.toISOString) {
+                    // native implementation is ~50x faster, use it when we can
+                    return this.toDate().toISOString();
+                } else {
+                    return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+                }
             } else {
                 return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
             }
                     diff < 1 ? 'sameDay' :
                     diff < 2 ? 'nextDay' :
                     diff < 7 ? 'nextWeek' : 'sameElse';
-            return this.format(this.localeData().calendar(format, this));
+            return this.format(this.localeData().calendar(format, this, moment(now)));
         },
 
         isLeapYear : function () {
 
         endOf: function (units) {
             units = normalizeUnits(units);
+            if (units === undefined || units === 'millisecond') {
+                return this;
+            }
             return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
         },
 
         isAfter: function (input, units) {
+            var inputMs;
             units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
             if (units === 'millisecond') {
                 input = moment.isMoment(input) ? input : moment(input);
                 return +this > +input;
             } else {
-                return +this.clone().startOf(units) > +moment(input).startOf(units);
+                inputMs = moment.isMoment(input) ? +input : +moment(input);
+                return inputMs < +this.clone().startOf(units);
             }
         },
 
         isBefore: function (input, units) {
+            var inputMs;
             units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
             if (units === 'millisecond') {
                 input = moment.isMoment(input) ? input : moment(input);
                 return +this < +input;
             } else {
-                return +this.clone().startOf(units) < +moment(input).startOf(units);
+                inputMs = moment.isMoment(input) ? +input : +moment(input);
+                return +this.clone().endOf(units) < inputMs;
             }
         },
 
         isSame: function (input, units) {
+            var inputMs;
             units = normalizeUnits(units || 'millisecond');
             if (units === 'millisecond') {
                 input = moment.isMoment(input) ? input : moment(input);
                 return +this === +input;
             } else {
-                return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
+                inputMs = +moment(input);
+                return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units));
             }
         },
 
         },
 
         lang : deprecate(
-            'moment().lang() is deprecated. Use moment().localeData() instead.',
+            'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
             function (key) {
                 if (key === undefined) {
                     return this.localeData();
                 return units === 'month' ? months : months / 12;
             } else {
                 // handle milliseconds separately because of floating point math errors (issue #1867)
-                days = this._days + yearsToDays(this._months / 12);
+                days = this._days + Math.round(yearsToDays(this._months / 12));
                 switch (units) {
                     case 'week': return days / 7 + this._milliseconds / 6048e5;
                     case 'day': return days + this._milliseconds / 864e5;
 
     // Set default locale, other locale will inherit from English.
     moment.locale('en', {
+        ordinalParse: /\d{1,2}(th|st|nd|rd)/,
         ordinal : function (number) {
             var b = number % 10,
                 output = (toInt(number % 100 / 10) === 1) ? 'th' :
index c7afbfa..130bd8e 100644 (file)
@@ -8,6 +8,12 @@
        "ooui-outline-control-move-up": "Premjesti stavku gore",
        "ooui-outline-control-remove": "Ukloni stavku",
        "ooui-toolbar-more": "Više",
+       "ooui-toolgroup-expand": "Više",
+       "ooui-toolgroup-collapse": "Manje",
        "ooui-dialog-message-accept": "U redu",
-       "ooui-dialog-message-reject": "Otkaži"
+       "ooui-dialog-message-reject": "Otkaži",
+       "ooui-dialog-process-error": "Nešto je pošlo naopako",
+       "ooui-dialog-process-dismiss": "Odbaci",
+       "ooui-dialog-process-retry": "Pokušajte ponovo",
+       "ooui-dialog-process-continue": "Nastavi"
 }
index 32fc9fe..9ff787a 100644 (file)
        "ooui-outline-control-move-down": "Pārvietot vienumu uz leju",
        "ooui-outline-control-move-up": "Pārvietot vienumu uz augšu",
        "ooui-toolbar-more": "Vairāk",
+       "ooui-toolgroup-expand": "Vairāk",
+       "ooui-toolgroup-collapse": "Mazāk",
        "ooui-dialog-message-accept": "Labi",
        "ooui-dialog-message-reject": "Atcelt",
-       "ooui-dialog-process-retry": "Mēģināt vēlreiz"
+       "ooui-dialog-process-error": "Kaut kas nogāja greizi",
+       "ooui-dialog-process-retry": "Mēģināt vēlreiz",
+       "ooui-dialog-process-continue": "Turpināt"
 }
index 382317e..704a186 100644 (file)
@@ -8,9 +8,12 @@
        "ooui-outline-control-move-up": "Premesti stavku na gore",
        "ooui-outline-control-remove": "Ukloni stavku",
        "ooui-toolbar-more": "Više",
+       "ooui-toolgroup-expand": "Više",
+       "ooui-toolgroup-collapse": "Manje",
        "ooui-dialog-message-accept": "U redu",
        "ooui-dialog-message-reject": "Otkaži",
        "ooui-dialog-process-error": "Nešto je pošlo naopako",
        "ooui-dialog-process-dismiss": "Odbaci",
-       "ooui-dialog-process-retry": "Pokušaj ponovo"
+       "ooui-dialog-process-retry": "Pokušaj ponovo",
+       "ooui-dialog-process-continue": "Nastavi"
 }
index ee157b2..006cdeb 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.6.1
+ * OOjs UI v0.6.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2015 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-01-05T13:04:47Z
+ * Date: 2015-01-10T01:25:31Z
  */
 .oo-ui-progressBarWidget-slide-frames from {
        margin-left: -40%;
        opacity: 0.2;
 }
 .oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
-       color: #dddddd;
+       color: #ffffff;
+       background: #eeeeee;
 }
 .oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:hover,
 .oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:focus {
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
        color: #015ccc;
+       box-shadow: none;
 }
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus > .oo-ui-labelElement-label {
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
        color: #008c6d;
+       box-shadow: none;
 }
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus > .oo-ui-labelElement-label {
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
        color: #a7170f;
+       box-shadow: none;
 }
 .oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
        margin: 0.1em 0;
        margin-right: 0.3em;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
-       color: #dddddd;
-       background: #ffffff;
-       border: solid 1px #cdcdcd;
+       color: #ffffff;
+       background: #eeeeee;
+       border: #eeeeee;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button {
        color: #757575;
        background-color: #ffffff;
        border: solid 1px #cdcdcd;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 rgba(0, 0, 0, 0.2), 0 0.1em 0 0 rgba(0, 0, 0, 0.2);
        border-color: #aaaaaa;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
        background-color: #d0d0d0;
        border-color: #d0d0d0;
+       box-shadow: none;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button {
        color: #0274ff;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 #015ccc, 0 0.1em 0 0 rgba(0, 0, 0, 0.1);
        border-bottom-color: #015ccc;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px #015ccc;
+       border-color: #015ccc;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+       color: #015ccc;
+       border-color: #d0d0d0;
+       box-shadow: none;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button {
        color: #00af89;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 #008c6d, 0 0.1em 0 0 rgba(0, 0, 0, 0.1);
        border-bottom-color: #008c6d;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px #008c6d;
+       border-color: #008c6d;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+       color: #008c6d;
+       border-color: #d0d0d0;
+       box-shadow: none;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
        color: #d11d13;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 #a7170f, 0 0.1em 0 0 rgba(0, 0, 0, 0.1);
        border-bottom-color: #a7170f;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px #a7170f;
+       border-color: #a7170f;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+       color: #a7170f;
+       border-color: #d0d0d0;
+       box-shadow: none;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button {
-       text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
        color: #ffffff;
        background-color: #0274ff;
        border-color: #0274ff;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 #015ccc, 0 0.1em 0 0 rgba(0, 0, 0, 0.1);
        border-bottom-color: #015ccc;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px #015ccc;
+       border-color: #015ccc;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled .oo-ui-buttonElement-button:active,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
        background-color: #015ccc;
+       border-color: #015ccc;
+       box-shadow: none;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button {
-       text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
        color: #ffffff;
        background-color: #00af89;
        border-color: #00af89;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 #008c6d, 0 0.1em 0 0 rgba(0, 0, 0, 0.1);
        border-bottom-color: #008c6d;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px #008c6d;
+       border-color: #008c6d;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled .oo-ui-buttonElement-button:active,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
        background-color: #008c6d;
+       border-color: #008c6d;
+       box-shadow: none;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
-       text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
        color: #ffffff;
        background-color: #d11d13;
        border-color: #d11d13;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 #a7170f, 0 0.1em 0 0 rgba(0, 0, 0, 0.1);
        border-bottom-color: #a7170f;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px #a7170f;
+       border-color: #a7170f;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled .oo-ui-buttonElement-button:active,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
        background-color: #a7170f;
+       border-color: #a7170f;
+       box-shadow: none;
 }
 .oo-ui-clippableElement-clippable {
        -webkit-box-sizing: border-box;
        box-shadow: inset 0 -0.2em 0 0 rgba(0, 0, 0, 0.2);
 }
 .oo-ui-popupWidget-anchored .oo-ui-popupWidget-popup {
-       margin-top: 7px;
+       margin-top: 9px;
 }
 .oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:before,
 .oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:after {
        border-top: 0;
 }
 .oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:before {
-       bottom: -8px;
-       left: -13px;
+       bottom: -10px;
+       left: -9px;
        border-bottom-color: #888888;
-       border-width: 13px;
+       border-width: 10px;
 }
 .oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:after {
-       bottom: -8px;
-       left: -12px;
+       bottom: -10px;
+       left: -8px;
        border-bottom-color: #ffffff;
-       border-width: 12px;
+       border-width: 9px;
 }
 .oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
        -webkit-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
        margin: 0 0.4em;
 }
 .oo-ui-checkboxInputWidget input[type="checkbox"] + span::before {
+       -webkit-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+          -moz-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+           -ms-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+            -o-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+               transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
        content: "";
        -webkit-box-sizing: border-box;
           -moz-box-sizing: border-box;
        height: 2em;
        background-color: white;
        border: 1px solid #777777;
-}
-.oo-ui-checkboxInputWidget input[type="checkbox"]:checked + span::before {
        background-image: /* @embed */ url(themes/mediawiki/images/icons/check-constructive.svg);
        background-size: 2em, 2em;
        background-repeat: no-repeat;
        background-position: center center;
        background-origin: border-box;
+       background-size: 0 0;
+}
+.oo-ui-checkboxInputWidget input[type="checkbox"]:checked + span::before {
+       background-size: 100% 100%;
 }
 .oo-ui-checkboxInputWidget input[type="checkbox"]:active + span::before {
        background-color: #dddddd;
 .oo-ui-image-invert.oo-ui-icon-link {
        background-image: /* @embed */ url(themes/mediawiki/images/icons/link-invert.png);
 }
+.oo-ui-icon-lock {
+       background-image: /* @embed */ url(themes/mediawiki/images/icons/lock.png);
+}
+.oo-ui-image-invert .oo-ui-icon-lock,
+.oo-ui-image-invert.oo-ui-icon-lock {
+       background-image: /* @embed */ url(themes/mediawiki/images/icons/lock-invert.png);
+}
 .oo-ui-icon-menu {
        background-image: /* @embed */ url(themes/mediawiki/images/icons/menu.png);
 }
index 09b4474..4f6eb59 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.6.1
+ * OOjs UI v0.6.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2015 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-01-05T13:04:40Z
+ * Date: 2015-01-10T01:25:19Z
  */
 /**
  * @class
index 815ef02..9956340 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.6.1
+ * OOjs UI v0.6.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2015 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-01-05T13:04:47Z
+ * Date: 2015-01-10T01:25:31Z
  */
 .oo-ui-progressBarWidget-slide-frames from {
        margin-left: -40%;
        opacity: 0.2;
 }
 .oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
-       color: #dddddd;
+       color: #ffffff;
+       background: #eeeeee;
 }
 .oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:hover,
 .oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:focus {
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
        color: #015ccc;
+       box-shadow: none;
 }
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus > .oo-ui-labelElement-label {
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
        color: #008c6d;
+       box-shadow: none;
 }
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus > .oo-ui-labelElement-label {
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button > .oo-ui-labelElement-label,
 .oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
        color: #a7170f;
+       box-shadow: none;
 }
 .oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
        margin: 0.1em 0;
        margin-right: 0.3em;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
-       color: #dddddd;
-       background: #ffffff;
-       border: solid 1px #cdcdcd;
+       color: #ffffff;
+       background: #eeeeee;
+       border: #eeeeee;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button {
        color: #757575;
        background-color: #ffffff;
        border: solid 1px #cdcdcd;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 rgba(0, 0, 0, 0.2), 0 0.1em 0 0 rgba(0, 0, 0, 0.2);
        border-color: #aaaaaa;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.2);
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
        background-color: #d0d0d0;
        border-color: #d0d0d0;
+       box-shadow: none;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button {
        color: #0274ff;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 #015ccc, 0 0.1em 0 0 rgba(0, 0, 0, 0.1);
        border-bottom-color: #015ccc;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px #015ccc;
+       border-color: #015ccc;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+       color: #015ccc;
+       border-color: #d0d0d0;
+       box-shadow: none;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button {
        color: #00af89;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 #008c6d, 0 0.1em 0 0 rgba(0, 0, 0, 0.1);
        border-bottom-color: #008c6d;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px #008c6d;
+       border-color: #008c6d;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+       color: #008c6d;
+       border-color: #d0d0d0;
+       box-shadow: none;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
        color: #d11d13;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 #a7170f, 0 0.1em 0 0 rgba(0, 0, 0, 0.1);
        border-bottom-color: #a7170f;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px #a7170f;
+       border-color: #a7170f;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+       color: #a7170f;
+       border-color: #d0d0d0;
+       box-shadow: none;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button {
-       text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
        color: #ffffff;
        background-color: #0274ff;
        border-color: #0274ff;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 #015ccc, 0 0.1em 0 0 rgba(0, 0, 0, 0.1);
        border-bottom-color: #015ccc;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px #015ccc;
+       border-color: #015ccc;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled .oo-ui-buttonElement-button:active,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
        background-color: #015ccc;
+       border-color: #015ccc;
+       box-shadow: none;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button {
-       text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
        color: #ffffff;
        background-color: #00af89;
        border-color: #00af89;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 #008c6d, 0 0.1em 0 0 rgba(0, 0, 0, 0.1);
        border-bottom-color: #008c6d;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px #008c6d;
+       border-color: #008c6d;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled .oo-ui-buttonElement-button:active,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
        background-color: #008c6d;
+       border-color: #008c6d;
+       box-shadow: none;
 }
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
-       text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.2);
        color: #ffffff;
        background-color: #d11d13;
        border-color: #d11d13;
 }
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover,
-.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover {
        box-shadow: inset 0 -0.2em 0 0 #a7170f, 0 0.1em 0 0 rgba(0, 0, 0, 0.1);
        border-bottom-color: #a7170f;
 }
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
+       box-shadow: inset 0 0 0 1px #a7170f;
+       border-color: #a7170f;
+}
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled .oo-ui-buttonElement-button:active,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
 .oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
        background-color: #a7170f;
+       border-color: #a7170f;
+       box-shadow: none;
 }
 .oo-ui-clippableElement-clippable {
        -webkit-box-sizing: border-box;
        box-shadow: inset 0 -0.2em 0 0 rgba(0, 0, 0, 0.2);
 }
 .oo-ui-popupWidget-anchored .oo-ui-popupWidget-popup {
-       margin-top: 7px;
+       margin-top: 9px;
 }
 .oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:before,
 .oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:after {
        border-top: 0;
 }
 .oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:before {
-       bottom: -8px;
-       left: -13px;
+       bottom: -10px;
+       left: -9px;
        border-bottom-color: #888888;
-       border-width: 13px;
+       border-width: 10px;
 }
 .oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:after {
-       bottom: -8px;
-       left: -12px;
+       bottom: -10px;
+       left: -8px;
        border-bottom-color: #ffffff;
-       border-width: 12px;
+       border-width: 9px;
 }
 .oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
        -webkit-transition: width 100ms ease-in-out, height 100ms ease-in-out, left 100ms ease-in-out;
        margin: 0 0.4em;
 }
 .oo-ui-checkboxInputWidget input[type="checkbox"] + span::before {
+       -webkit-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+          -moz-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+           -ms-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+            -o-transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+               transition: background-size 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
        content: "";
        -webkit-box-sizing: border-box;
           -moz-box-sizing: border-box;
        height: 2em;
        background-color: white;
        border: 1px solid #777777;
-}
-.oo-ui-checkboxInputWidget input[type="checkbox"]:checked + span::before {
        background-image: /* @embed */ url(themes/mediawiki/images/icons/check-constructive.svg);
        background-size: 2em, 2em;
        background-repeat: no-repeat;
        background-position: center center;
        background-origin: border-box;
+       background-size: 0 0;
+}
+.oo-ui-checkboxInputWidget input[type="checkbox"]:checked + span::before {
+       background-size: 100% 100%;
 }
 .oo-ui-checkboxInputWidget input[type="checkbox"]:active + span::before {
        background-color: #dddddd;
 .oo-ui-image-invert.oo-ui-icon-link {
        background-image: /* @embed */ url(themes/mediawiki/images/icons/link-invert.svg);
 }
+.oo-ui-icon-lock {
+       background-image: /* @embed */ url(themes/mediawiki/images/icons/lock.svg);
+}
+.oo-ui-image-invert .oo-ui-icon-lock,
+.oo-ui-image-invert.oo-ui-icon-lock {
+       background-image: /* @embed */ url(themes/mediawiki/images/icons/lock-invert.svg);
+}
 .oo-ui-icon-menu {
        background-image: /* @embed */ url(themes/mediawiki/images/icons/menu.svg);
 }
index ef99551..38aa092 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOjs UI v0.6.1
+ * OOjs UI v0.6.2
  * https://www.mediawiki.org/wiki/OOjs_UI
  *
  * Copyright 2011–2015 OOjs Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2015-01-05T13:04:40Z
+ * Date: 2015-01-10T01:25:19Z
  */
 ( function ( OO ) {
 
@@ -722,6 +722,7 @@ OO.ui.ActionSet.prototype.organize = function () {
  * @param {Object} [config] Configuration options
  * @cfg {Function} [$] jQuery for the frame the widget is in
  * @cfg {string[]} [classes] CSS class names to add
+ * @cfg {string} [id] HTML id attribute
  * @cfg {string} [text] Text to insert
  * @cfg {jQuery} [$content] Content elements to append (after text)
  * @cfg {Mixed} [data] Element data
@@ -742,6 +743,9 @@ OO.ui.Element = function OoUiElement( config ) {
        if ( $.isArray( config.classes ) ) {
                this.$element.addClass( config.classes.join( ' ' ) );
        }
+       if ( config.id ) {
+               this.$element.attr( 'id', config.id );
+       }
        if ( config.text ) {
                this.$element.text( config.text );
        }
@@ -3092,7 +3096,7 @@ OO.ui.WindowManager.prototype.addWindows = function ( windows ) {
  *
  * Windows will be closed before they are removed.
  *
- * @param {string} name Symbolic name of window to remove
+ * @param {string[]} names Symbolic names of windows to remove
  * @return {jQuery.Promise} Promise resolved when window is closed and removed
  * @throws {Error} If windows being removed are not being managed
  */
@@ -3238,12 +3242,11 @@ OO.ui.WindowManager.prototype.toggleAriaIsolation = function ( isolate ) {
 
 /**
  * Destroy window manager.
- *
- * Windows will not be closed, only removed from the DOM.
  */
 OO.ui.WindowManager.prototype.destroy = function () {
        this.toggleGlobalEvents( false );
        this.toggleAriaIsolation( false );
+       this.clearWindows();
        this.$element.remove();
 };
 
@@ -10121,6 +10124,8 @@ OO.ui.RadioInputWidget.prototype.isSelected = function () {
  * @param {Object} [config] Configuration options
  * @cfg {string} [type='text'] HTML tag `type` attribute
  * @cfg {string} [placeholder] Placeholder text
+ * @cfg {boolean} [autofocus=false] Ask the browser to focus this widget, using the 'autofocus' HTML
+ *  attribute
  * @cfg {boolean} [readOnly=false] Prevent changes
  * @cfg {boolean} [multiline=false] Allow multiple lines of text
  * @cfg {boolean} [autosize=false] Automatically resize to fit content
@@ -10174,6 +10179,9 @@ OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
        if ( config.placeholder ) {
                this.$input.attr( 'placeholder', config.placeholder );
        }
+       if ( config.autofocus ) {
+               this.$input.attr( 'autofocus', 'autofocus' );
+       }
        this.$element.attr( 'role', 'textbox' );
 };
 
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-invert.png b/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-invert.png
new file mode 100644 (file)
index 0000000..d8d5eac
Binary files /dev/null and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-invert.png differ
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-invert.svg b/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-invert.svg
new file mode 100644 (file)
index 0000000..016c2ed
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+    <g id="lock">
+        <path d="M14 9.06c0-1.562-.656-2.342-2-2.342-1.344 0-1.992.775-2 2.33V10h4zm3-.036V10h2v10H7c-.46 0-1.168-.156-1.497-.485-.33-.327-.503-.727-.503-1.195V10h2v-.964c0-.914.19-1.75.574-2.517.383-.767.92-1.407 1.606-1.852C9.867 4.223 11.14 4 12 4c1.243 0 2.852.473 3.71 1.44.86.97 1.29 2.186 1.29 3.584z"/>
+    </g>
+</svg>
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock.png b/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock.png
new file mode 100644 (file)
index 0000000..59787d2
Binary files /dev/null and b/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock.png differ
diff --git a/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock.svg b/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock.svg
new file mode 100644 (file)
index 0000000..86fd1e3
--- /dev/null
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+    <g id="lock">
+        <path d="M14 9.06c0-1.562-.656-2.342-2-2.342-1.344 0-1.992.775-2 2.33V10h4zm3-.036V10h2v10H7c-.46 0-1.168-.156-1.497-.485-.33-.327-.503-.727-.503-1.195V10h2v-.964c0-.914.19-1.75.574-2.517.383-.767.92-1.407 1.606-1.852C9.867 4.223 11.14 4 12 4c1.243 0 2.852.473 3.71 1.44.86.97 1.29 2.186 1.29 3.584z"/>
+    </g>
+</svg>
index 226eb5c..55f3d1f 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down-invert.png differ
index 31a561a..6ee6803 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"><style>* { fill: #FFFFFF }</style>
-    <g id="ltr">
-        <path id="arrow" d="M12.008,3.034 L11.545,2.567 C11.095,2.121 10.359,2.122 9.908,2.567 L6.003,6.424 L2.087,2.559 C1.637,2.113 0.911,2.129 0.461,2.576 L-0.001,3.034 L6.003,9 L6.003,8.991 L6.003,9 L12.008,3.034"/>
+    <g id="down">
+        <path id="arrow" d="M11 4l-.463-.467c-.45-.446-1.186-.445-1.637 0l-2.897 2.89-2.915-2.898c-.45-.446-1.176-.43-1.626.017L1 4l5.003 5v-.01V9L11 4"/>
     </g>
 </svg>
index 9a418c9..db8c51d 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down.png and b/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down.png differ
index d64695f..0c0da8e 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="ltr">
-        <path id="arrow" d="M12.008,3.034 L11.545,2.567 C11.095,2.121 10.359,2.122 9.908,2.567 L6.003,6.424 L2.087,2.559 C1.637,2.113 0.911,2.129 0.461,2.576 L-0.001,3.034 L6.003,9 L6.003,8.991 L6.003,9 L12.008,3.034"/>
+    <g id="down">
+        <path id="arrow" d="M11 4l-.463-.467c-.45-.446-1.186-.445-1.637 0l-2.897 2.89-2.915-2.898c-.45-.446-1.176-.43-1.626.017L1 4l5.003 5v-.01V9L11 4"/>
     </g>
 </svg>
index a348495..9edc9de 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr-invert.png differ
index 5816c08..64203e1 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"><style>* { fill: #FFFFFF }</style>
     <g id="ltr">
-        <path id="arrow" d="M3.972,-0.005 L3.503,0.458 C3.058,0.908 3.058,1.644 3.503,2.095 L7.36,6 L3.495,9.915 C3.05,10.365 3.065,11.091 3.513,11.541 L3.972,12.004 L9.938,6 L9.929,6 L9.938,6 L3.972,-0.005"/>
+        <path id="arrow" d="M4 1l-.47.463c-.444.45-.444 1.186 0 1.637L6.423 6l-2.9 2.91c-.444.45-.43 1.177.02 1.627L4 11l5-5h-.01H9L4 1"/>
     </g>
 </svg>
index bfed7d2..19e9820 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr.png and b/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr.png differ
index 7bccea1..0d11e3e 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="ltr">
-        <path id="arrow" d="M3.972,-0.005 L3.503,0.458 C3.058,0.908 3.058,1.644 3.503,2.095 L7.36,6 L3.495,9.915 C3.05,10.365 3.065,11.091 3.513,11.541 L3.972,12.004 L9.938,6 L9.929,6 L9.938,6 L3.972,-0.005"/>
+        <path id="arrow" d="M4 1l-.47.463c-.444.45-.444 1.186 0 1.637L6.423 6l-2.9 2.91c-.444.45-.43 1.177.02 1.627L4 11l5-5h-.01H9L4 1"/>
     </g>
 </svg>
index 5080ea5..ac769a3 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl-invert.png differ
index 01e40d7..3d36e4f 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"><style>* { fill: #FFFFFF }</style>
     <g id="rtl">
-        <path id="arrow" d="M7.979,12.004 L8.448,11.541 C8.893,11.091 8.893,10.355 8.448,9.904 L4.59,5.999 L8.455,2.084 C8.9,1.634 8.885,0.908 8.437,0.458 L7.979,-0.005 L2.013,5.999 L2.022,5.999 L2.013,5.999 L7.979,12.004"/>
+        <path id="arrow" d="M8 11l.47-.463c.444-.45.444-1.186 0-1.637L5.576 6l2.9-2.91c.444-.45.43-1.177-.02-1.627L8 1 3 6h.01H3l5 5"/>
     </g>
 </svg>
index 0639809..d912a1b 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl.png and b/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl.png differ
index 304c516..e4c04b8 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="rtl">
-        <path id="arrow" d="M7.979,12.004 L8.448,11.541 C8.893,11.091 8.893,10.355 8.448,9.904 L4.59,5.999 L8.455,2.084 C8.9,1.634 8.885,0.908 8.437,0.458 L7.979,-0.005 L2.013,5.999 L2.022,5.999 L2.013,5.999 L7.979,12.004"/>
+        <path id="arrow" d="M8 11l.47-.463c.444-.45.444-1.186 0-1.637L5.576 6l2.9-2.91c.444-.45.43-1.177-.02-1.627L8 1 3 6h.01H3l5 5"/>
     </g>
 </svg>
index 0474926..c8f4402 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up-invert.png and b/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up-invert.png differ
index e880711..9bbde71 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"><style>* { fill: #FFFFFF }</style>
     <g id="up">
-        <path id="arrow" d="M-0.001,7.99 L0.462,8.459 C0.912,8.904 1.648,8.904 2.099,8.459 L6.004,4.601 L9.919,8.467 C10.369,8.912 11.095,8.897 11.545,8.449 L12.008,7.99 L6.004,2.024 L6.004,2.033 L6.004,2.024 L-0.001,7.99"/>
+        <path id="arrow" d="M1 8l.463.47c.45.444 1.186.444 1.637 0L6 5.567l2.91 2.91c.45.444 1.177.43 1.627-.02L11 8 6 2.99V3v-.01L1 8"/>
     </g>
 </svg>
index ac9f0b5..214b12e 100644 (file)
Binary files a/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up.png and b/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up.png differ
index 4769526..ad41a87 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="up">
-        <path id="arrow" d="M-0.001,7.99 L0.462,8.459 C0.912,8.904 1.648,8.904 2.099,8.459 L6.004,4.601 L9.919,8.467 C10.369,8.912 11.095,8.897 11.545,8.449 L12.008,7.99 L6.004,2.024 L6.004,2.033 L6.004,2.024 L-0.001,7.99"/>
+        <path id="arrow" d="M1 8l.463.47c.45.444 1.186.444 1.637 0L6 5.567l2.91 2.91c.45.444 1.177.43 1.627-.02L11 8 6 2.99V3v-.01L1 8"/>
     </g>
 </svg>
index e3ffbda..e4cd3a2 100644 (file)
                                        imgHeight = $( this ).data( 'imgHeight' ),
                                        width = $( this ).data( 'width' ),
                                        captionWidth = $( this ).data( 'captionWidth' ),
+                                       $innerDiv = $( this ).children( 'div' ).first(),
+                                       $imageDiv = $innerDiv.children( 'div.thumb' ),
                                        $imageElm, imageElm;
 
                                // Restore original sizes so we can arrange the elements as on freshly loaded page
                                $( this ).width( width );
-                               $( this ).children( 'div' ).first().width( width );
-                               $( this ).children( 'div' ).first().children( 'div.thumb' ).width( imgWidth );
+                               $innerDiv.width( width );
+                               $imageDiv.width( imgWidth );
                                $( this ).find( 'div.gallerytextwrapper' ).width( captionWidth );
 
                                $imageElm = $( this ).find( 'img' ).first();
                                if ( imageElm ) {
                                        imageElm.width = imgWidth;
                                        imageElm.height = imgHeight;
+                               } else {
+                                       $imageDiv.height( imgHeight );
                                }
                        } );
                } ) );
index 506dc11..be0c638 100644 (file)
@@ -61,6 +61,7 @@
 
                // the pseudo before element of the label after the checkbox now looks like a checkbox
                & + label::before {
+                       .transition( 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275) );
                        content: '';
                        cursor: pointer;
                        .box-sizing(border-box);
                        height: @checkboxSize;
                        background-color: #fff;
                        border: 1px solid @colorGray7;
-               }
-
-               // 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-size( @checkboxSize - 0.2em, @checkboxSize - 0.2em );
                        background-repeat: no-repeat;
                        background-position: center center;
                        background-origin: border-box;
+                       background-size: 0 0;
+               }
+
+               // when the input is checked, style the label pseudo before element that followed as a checked checkbox
+               &:checked + label::before {
+                       background-size: 100% 100%;
                }
 
                &:active + label::before {
index 40d1723..ad951b0 100644 (file)
@@ -36,8 +36,9 @@
        // Standalone icons
        //
        // Markup:
-       // <div class="mw-ui-icon mw-ui-icon-element mw-ui-icon-ok">OK</div>
-       // <div class="mw-ui-icon mw-ui-icon-element mw-ui-icon-ok mw-ui-button mw-ui-progressive">OK</div>
+       // <div class="mw-ui-icon mw-ui-icon-element mw-ui-icon-ok">OK</div><br/>
+       // <div class="mw-ui-icon mw-ui-icon-element mw-ui-icon-ok mw-ui-button mw-ui-progressive">OK</div><br/>
+       // <button class="mw-ui-icon mw-ui-icon-ok mw-ui-icon-element mw-ui-button mw-ui-quiet" title="">Close</button>
        //
        // Styleguide 6.1.1.
        &.mw-ui-icon-element {
@@ -49,7 +50,6 @@
                min-width: @width;
                max-width: @width;
                &:before {
-                       top: 0;
                        left: 0;
                        right: 0;
                        position: absolute;
index 6bf93f4..1763c8e 100644 (file)
                }
        }
 
+       // String format helper. Replaces $1, $2 .. $N placeholders with positional
+       // args. Used by Message.prototype.parser() and exported as mw.format().
+       function format( formatString ) {
+               var parameters = slice.call( arguments, 1 );
+               return formatString.replace( /\$(\d+)/g, function ( str, match ) {
+                       var index = parseInt( match, 10 ) - 1;
+                       return parameters[index] !== undefined ? parameters[index] : '$' + match;
+               } );
+       }
+
        /* Object constructors */
 
        /**
                 * This function will not be called for nonexistent messages.
                 */
                parser: function () {
-                       var parameters = this.parameters;
-                       return this.map.get( this.key ).replace( /\$(\d+)/g, function ( str, match ) {
-                               var index = parseInt( match, 10 ) - 1;
-                               return parameters[index] !== undefined ? parameters[index] : '$' + match;
-                       } );
+                       return format.apply( null, [ this.map.get( this.key ) ].concat( this.parameters ) );
                },
 
                /**
                                function () { return +new Date(); };
                }() ),
 
+               /**
+                * Format a string. Replace $1, $2 ... $N with positional arguments.
+                *
+                * @method
+                * @since 1.25
+                * @param {string} fmt Format string
+                * @param {Mixed...} parameters Substitutions for $N placeholders.
+                * @return {string} Formatted string
+                */
+               format: format,
+
                /**
                 * Track an analytic event.
                 *
                 *
                 * @property {mw.Map} config
                 */
-               // Dummy placeholder. Re-assigned in ResourceLoaderStartupModule to an instance of `mw.Map`.
+               // Dummy placeholder. Re-assigned in ResourceLoaderStartUpModule to an instance of `mw.Map`.
                config: null,
 
                /**
index c011a68..fd89e56 100644 (file)
@@ -9,9 +9,13 @@ module.exports = function ( grunt ) {
        grunt.loadNpmTasks( 'grunt-banana-checker' );
        grunt.loadNpmTasks( 'grunt-jscs' );
        grunt.loadNpmTasks( 'grunt-jsonlint' );
+       grunt.loadNpmTasks( 'grunt-karma' );
 
        grunt.file.setBase(  __dirname + '/../..' );
 
+       var wgServer = process.env.MW_SERVER,
+               wgScriptPath = process.env.MW_SCRIPT_PATH;
+
        grunt.initConfig( {
                pkg: grunt.file.readJSON( __dirname + '/package.json' ),
                jshint: {
@@ -61,10 +65,53 @@ module.exports = function ( grunt ) {
                                '.jshintrc'
                        ],
                        tasks: 'test'
+               },
+               karma: {
+                       options: {
+                               proxies: ( function () {
+                                       var obj = {};
+                                       // Set up a proxy for requests to relative urls inside wgScriptPath. Uses a
+                                       // property accessor instead of plain obj[wgScriptPath] assignment as throw if
+                                       // unset. Running grunt normally (e.g. npm test), should not fail over this.
+                                       // This ensures 'npm test' works out of the box, statically, on a git clone
+                                       // without MediaWiki fully installed or some environment variables set.
+                                       Object.defineProperty( obj, wgScriptPath, {
+                                               enumerable: true,
+                                               get: function () {
+                                                       if ( !wgServer ) {
+                                                               grunt.fail.fatal( 'MW_SERVER is not set' );
+                                                       }
+                                                       if ( !wgScriptPath ) {
+                                                               grunt.fail.fatal( 'MW_SCRIPT_PATH is not set' );
+                                                       }
+                                                       return wgServer + wgScriptPath;
+                                               }
+                                       } );
+                                       return obj;
+                               }() ),
+                               files: [ {
+                                       pattern: wgServer + wgScriptPath + '/index.php?title=Special:JavaScriptTest/qunit/export',
+                                       watched: false,
+                                       included: true,
+                                       served: false
+                               } ],
+                               frameworks: [ 'qunit' ],
+                               reporters: [ 'dots' ],
+                               singleRun: true,
+                               autoWatch: false
+                       },
+                       main: {
+                               browsers: [ 'Chrome' ]
+                       },
+                       more: {
+                               browsers: [ 'Chrome', 'Firefox' ]
+                       }
                }
        } );
 
        grunt.registerTask( 'lint', ['jshint', 'jscs', 'jsonlint', 'banana'] );
+       grunt.registerTask( 'qunit', 'karma:main' );
+
        grunt.registerTask( 'test', ['lint'] );
-       grunt.registerTask( 'default', ['test'] );
+       grunt.registerTask( 'default', 'test' );
 };
index 9b15379..101fcd9 100644 (file)
@@ -6,10 +6,16 @@
   },
   "devDependencies": {
     "grunt": "0.4.2",
+    "grunt-banana-checker": "0.2.0",
     "grunt-contrib-jshint": "0.10.0",
     "grunt-contrib-watch": "0.6.1",
-    "grunt-banana-checker": "0.2.0",
     "grunt-jscs": "0.8.1",
-    "grunt-jsonlint": "1.0.4"
+    "grunt-jsonlint": "1.0.4",
+    "grunt-karma": "0.9.0",
+    "karma": "0.12.28",
+    "karma-chrome-launcher": "0.1.7",
+    "karma-firefox-launcher": "0.1.3",
+    "karma-qunit": "0.1.4",
+    "qunitjs": "1.15.0"
   }
 }
index 327c1da..7e07823 100644 (file)
@@ -198,7 +198,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        }
 
        protected function setUp() {
-               wfProfileIn( __METHOD__ );
                parent::setUp();
                $this->called['setUp'] = true;
 
@@ -225,11 +224,9 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
 
                DeferredUpdates::clearPendingUpdates();
 
-               wfProfileOut( __METHOD__ );
        }
 
        protected function tearDown() {
-               wfProfileIn( __METHOD__ );
 
                $this->called['tearDown'] = true;
                // Cleaning up temporary files
@@ -273,7 +270,6 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                }
 
                parent::tearDown();
-               wfProfileOut( __METHOD__ );
        }
 
        /**
index 678c89b..ea753e8 100644 (file)
@@ -28,7 +28,8 @@ class ImportTest extends MediaWikiLangTestCase {
                $source = $this->getInputStreamSource( $xml );
 
                $redirect = null;
-               $callback = function ( $title, $origTitle, $revCount, $sRevCount, $pageInfo ) use ( &$redirect ) {
+               $callback = function ( Title $title, ForeignTitle $foreignTitle, $revCount,
+                       $sRevCount, $pageInfo ) use ( &$redirect ) {
                        if ( array_key_exists( 'redirect', $pageInfo ) ) {
                                $redirect = $pageInfo['redirect'];
                        }
@@ -98,4 +99,59 @@ EOF
                );
        }
 
+       /**
+        * @covers WikiImporter::handleSiteInfo
+        * @dataProvider getSiteInfoXML
+        * @param string $xml
+        * @param array|null $namespaces
+        */
+       public function testSiteInfoContainsNamespaces( $xml, $namespaces ) {
+               $source = $this->getInputStreamSource( $xml );
+
+               $importNamespaces = null;
+               $callback = function ( array $siteinfo, $innerImporter ) use ( &$importNamespaces ) {
+                       $importNamespaces = $siteinfo['_namespaces'];
+               };
+
+               $importer = new WikiImporter( $source, ConfigFactory::getDefaultInstance()->makeConfig( 'main' ) );
+               $importer->setSiteInfoCallback( $callback );
+               $importer->doImport();
+
+               $this->assertEquals( $importNamespaces, $namespaces );
+       }
+
+       public function getSiteInfoXML() {
+               return array(
+                       array(
+                               <<< EOF
+<mediawiki xmlns="http://www.mediawiki.org/xml/export-0.10/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.mediawiki.org/xml/export-0.10/ http://www.mediawiki.org/xml/export-0.10.xsd" version="0.10" xml:lang="en">
+  <siteinfo>
+    <namespaces>
+      <namespace key="-2" case="first-letter">Media</namespace>
+      <namespace key="-1" case="first-letter">Special</namespace>
+      <namespace key="0" case="first-letter" />
+      <namespace key="1" case="first-letter">Talk</namespace>
+      <namespace key="2" case="first-letter">User</namespace>
+      <namespace key="3" case="first-letter">User talk</namespace>
+      <namespace key="100" case="first-letter">Portal</namespace>
+      <namespace key="101" case="first-letter">Portal talk</namespace>
+    </namespaces>
+  </siteinfo>
+</mediawiki>
+EOF
+                       ,
+                               array(
+                                       '-2' => 'Media',
+                                       '-1' => 'Special',
+                                       '0' => '',
+                                       '1' => 'Talk',
+                                       '2' => 'User',
+                                       '3' => 'User talk',
+                                       '100' => 'Portal',
+                                       '101' => 'Portal talk',
+                               )
+                       ),
+               );
+       }
+
 }
diff --git a/tests/phpunit/includes/LanguageConverterTest.php b/tests/phpunit/includes/LanguageConverterTest.php
deleted file mode 100644 (file)
index d4ccca9..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-<?php
-
-class LanguageConverterTest extends MediaWikiLangTestCase {
-       /** @var LanguageToTest */
-       protected $lang = null;
-       /** @var TestConverter */
-       protected $lc = null;
-
-       protected function setUp() {
-               parent::setUp();
-
-               $this->setMwGlobals( array(
-                       'wgContLang' => Language::factory( 'tg' ),
-                       'wgLanguageCode' => 'tg',
-                       'wgDefaultLanguageVariant' => false,
-                       'wgMemc' => new EmptyBagOStuff,
-                       'wgRequest' => new FauxRequest( array() ),
-                       'wgUser' => new User,
-               ) );
-
-               $this->lang = new LanguageToTest();
-               $this->lc = new TestConverter(
-                       $this->lang, 'tg',
-                       array( 'tg', 'tg-latn' )
-               );
-       }
-
-       protected function tearDown() {
-               unset( $this->lc );
-               unset( $this->lang );
-
-               parent::tearDown();
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        */
-       public function testGetPreferredVariantDefaults() {
-               $this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getHeaderVariant
-        */
-       public function testGetPreferredVariantHeaders() {
-               global $wgRequest;
-               $wgRequest->setHeader( 'Accept-Language', 'tg-latn' );
-
-               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getHeaderVariant
-        */
-       public function testGetPreferredVariantHeaderWeight() {
-               global $wgRequest;
-               $wgRequest->setHeader( 'Accept-Language', 'tg;q=1' );
-
-               $this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getHeaderVariant
-        */
-       public function testGetPreferredVariantHeaderWeight2() {
-               global $wgRequest;
-               $wgRequest->setHeader( 'Accept-Language', 'tg-latn;q=1' );
-
-               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getHeaderVariant
-        */
-       public function testGetPreferredVariantHeaderMulti() {
-               global $wgRequest;
-               $wgRequest->setHeader( 'Accept-Language', 'en, tg-latn;q=1' );
-
-               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        */
-       public function testGetPreferredVariantUserOption() {
-               global $wgUser;
-
-               $wgUser = new User;
-               $wgUser->load(); // from 'defaults'
-               $wgUser->mId = 1;
-               $wgUser->mDataLoaded = true;
-               $wgUser->mOptionsLoaded = true;
-               $wgUser->setOption( 'variant', 'tg-latn' );
-
-               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getUserVariant
-        */
-       public function testGetPreferredVariantUserOptionForForeignLanguage() {
-               global $wgContLang, $wgUser;
-
-               $wgContLang = Language::factory( 'en' );
-               $wgUser = new User;
-               $wgUser->load(); // from 'defaults'
-               $wgUser->mId = 1;
-               $wgUser->mDataLoaded = true;
-               $wgUser->mOptionsLoaded = true;
-               $wgUser->setOption( 'variant-tg', 'tg-latn' );
-
-               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getUserVariant
-        * @covers LanguageConverter::getURLVariant
-        */
-       public function testGetPreferredVariantHeaderUserVsUrl() {
-               global $wgContLang, $wgRequest, $wgUser;
-
-               $wgContLang = Language::factory( 'tg-latn' );
-               $wgRequest->setVal( 'variant', 'tg' );
-               $wgUser = User::newFromId( "admin" );
-               $wgUser->setId( 1 );
-               $wgUser->mFrom = 'defaults';
-               $wgUser->mOptionsLoaded = true;
-               // The user's data is ignored because the variant is set in the URL.
-               $wgUser->setOption( 'variant', 'tg-latn' );
-               $this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        */
-       public function testGetPreferredVariantDefaultLanguageVariant() {
-               global $wgDefaultLanguageVariant;
-
-               $wgDefaultLanguageVariant = 'tg-latn';
-               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
-       }
-
-       /**
-        * @covers LanguageConverter::getPreferredVariant
-        * @covers LanguageConverter::getURLVariant
-        */
-       public function testGetPreferredVariantDefaultLanguageVsUrlVariant() {
-               global $wgDefaultLanguageVariant, $wgRequest, $wgContLang;
-
-               $wgContLang = Language::factory( 'tg-latn' );
-               $wgDefaultLanguageVariant = 'tg';
-               $wgRequest->setVal( 'variant', null );
-               $this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
-       }
-}
-
-/**
- * Test converter (from Tajiki to latin orthography)
- */
-class TestConverter extends LanguageConverter {
-       private $table = array(
-               'б' => 'b',
-               'в' => 'v',
-               'г' => 'g',
-       );
-
-       function loadDefaultTables() {
-               $this->mTables = array(
-                       'tg-latn' => new ReplacementArray( $this->table ),
-                       'tg' => new ReplacementArray()
-               );
-       }
-}
-
-class LanguageToTest extends Language {
-       function __construct() {
-               parent::__construct();
-               $variants = array( 'tg', 'tg-latn' );
-               $this->mConverter = new TestConverter( $this, 'tg', $variants );
-       }
-}
index fc88a55..6341bf0 100644 (file)
@@ -193,4 +193,49 @@ class LinkerTest extends MediaWikiLangTestCase {
                        ),
                );
        }
+
+       /**
+        * @covers Linker::formatLinksInComment
+        * @dataProvider provideCasesForFormatLinksInComment
+        */
+       public function testFormatLinksInComment( $expected, $input, $wiki ) {
+
+               $conf = new SiteConfiguration();
+               $conf->settings = array(
+                       'wgServer' => array(
+                               'enwiki' => '//en.example.org'
+                       ),
+                       'wgArticlePath' => array(
+                               'enwiki' => '/w/$1',
+                       ),
+               );
+               $conf->suffixes = array( 'wiki' );
+               $this->setMwGlobals( array(
+                       'wgScript' => '/wiki/index.php',
+                       'wgArticlePath' => '/wiki/$1',
+                       'wgWellFormedXml' => true,
+                       'wgCapitalLinks' => true,
+                       'wgConf' => $conf,
+               ) );
+
+               $this->assertEquals(
+                       $expected,
+                       Linker::formatLinksInComment( $input, Title::newFromText( 'Special:BlankPage' ), false, $wiki )
+               );
+       }
+
+       public static function provideCasesForFormatLinksInComment() {
+               return array(
+                       array(
+                               'foo bar <a href="/wiki/Special:BlankPage" title="Special:BlankPage">Special:BlankPage</a>',
+                               'foo bar [[Special:BlankPage]]',
+                               null,
+                       ),
+                       array(
+                               'foo bar <a class="external" rel="nofollow" href="//en.example.org/w/Special:BlankPage">Special:BlankPage</a>',
+                               'foo bar [[Special:BlankPage]]',
+                               'enwiki',
+                       ),
+               );
+       }
 }
index 51d03ed..e91edcb 100644 (file)
@@ -65,7 +65,10 @@ class ApiMainTest extends ApiTestCase {
         * Test if all classes in the main module manager exists
         */
        public function testClassNamesInModuleManager() {
-               global $wgAutoloadLocalClasses;
+               global $wgAutoloadLocalClasses, $wgAutoloadClasses;
+
+               // wgAutoloadLocalClasses has precedence, just like in includes/AutoLoader.php
+               $classes = $wgAutoloadLocalClasses + $wgAutoloadClasses;
 
                $api = new ApiMain(
                        new FauxRequest( array( 'action' => 'query', 'meta' => 'siteinfo' ) )
@@ -74,7 +77,7 @@ class ApiMainTest extends ApiTestCase {
                foreach( $modules as $name => $class ) {
                        $this->assertArrayHasKey(
                                $class,
-                               $wgAutoloadLocalClasses,
+                               $classes,
                                'Class ' . $class . ' for api module ' . $name . ' not in autoloader (with exact case)'
                        );
                }
index 3ab1334..5f061b5 100644 (file)
@@ -121,7 +121,10 @@ class ApiQueryTest extends ApiTestCase {
         * Test if all classes in the query module manager exists
         */
        public function testClassNamesInModuleManager() {
-               global $wgAutoloadLocalClasses;
+               global $wgAutoloadLocalClasses, $wgAutoloadClasses;
+
+               // wgAutoloadLocalClasses has precedence, just like in includes/AutoLoader.php
+               $classes = $wgAutoloadLocalClasses + $wgAutoloadClasses;
 
                $api = new ApiMain(
                        new FauxRequest( array( 'action' => 'query', 'meta' => 'siteinfo' ) )
@@ -131,7 +134,7 @@ class ApiQueryTest extends ApiTestCase {
                foreach( $modules as $name => $class ) {
                        $this->assertArrayHasKey(
                                $class,
-                               $wgAutoloadLocalClasses,
+                               $classes,
                                'Class ' . $class . ' for api module ' . $name . ' not in autoloader (with exact case)'
                        );
                }
index 26b81cc..149a28c 100644 (file)
@@ -164,7 +164,7 @@ class JavaScriptMinifierTest extends PHPUnit_Framework_TestCase {
                );
        }
 
-       public static function provideBug32548() {
+       public static function provideExponentLineBreaking() {
                return array(
                        array(
                                // This one gets interpreted all together by the prior code;
@@ -183,14 +183,13 @@ class JavaScriptMinifierTest extends PHPUnit_Framework_TestCase {
        }
 
        /**
-        * @dataProvider provideBug32548
+        * @dataProvider provideExponentLineBreaking
         * @covers JavaScriptMinifier::minify
-        * @todo give this test a real name explaining what is being tested here
         */
-       public function testBug32548Exponent( $num ) {
+       public function testExponentLineBreaking( $num ) {
                // Long line breaking was being incorrectly done between the base and
                // exponent part of a number, causing a syntax error. The line should
-               // instead break at the start of the number.
+               // instead break at the start of the number. (T34548)
                $prefix = 'var longVarName' . str_repeat( '_', 973 ) . '=';
                $suffix = ',shortVarName=0;';
 
index d8cfcc4..5fa609a 100644 (file)
@@ -7,50 +7,48 @@ class MediaHandlerTest extends MediaWikiTestCase {
 
        /**
         * @covers MediaHandler::fitBoxWidth
-        * @todo split into a dataprovider and test method
+        *
+        * @dataProvider provideTestFitBoxWidth
         */
-       public function testFitBoxWidth() {
-               $vals = array(
-                       array(
-                               'width' => 50,
-                               'height' => 50,
-                               'tests' => array(
+       public function testFitBoxWidth( $width, $height, $max, $expected ) {
+               $y = round( $expected * $height / $width );
+               $result = MediaHandler::fitBoxWidth( $width, $height, $max );
+               $y2 = round( $result * $height / $width );
+               $this->assertEquals( $expected,
+                       $result,
+                       "($width, $height, $max) wanted: {$expected}x$y, got: {z$result}x$y2" );
+       }
+
+       public function provideTestFitBoxWidth() {
+               return array_merge(
+                       $this->provideTestFitBoxWidthSingle( 50, 50, array(
                                        50 => 50,
                                        17 => 17,
-                                       18 => 18 ) ),
-                       array(
-                               'width' => 366,
-                               'height' => 300,
-                               'tests' => array(
+                                       18 => 18 )
+                       ),
+                       $this->provideTestFitBoxWidthSingle( 366, 300, array(
                                        50 => 61,
                                        17 => 21,
-                                       18 => 22 ) ),
-                       array(
-                               'width' => 300,
-                               'height' => 366,
-                               'tests' => array(
+                                       18 => 22 )
+                       ),
+                       $this->provideTestFitBoxWidthSingle( 300, 366, array(
                                        50 => 41,
                                        17 => 14,
-                                       18 => 15 ) ),
-                       array(
-                               'width' => 100,
-                               'height' => 400,
-                               'tests' => array(
+                                       18 => 15 )
+                       ),
+                       $this->provideTestFitBoxWidthSingle( 100, 400, array(
                                        50 => 12,
                                        17 => 4,
-                                       18 => 4 ) ) );
-               foreach ( $vals as $row ) {
-                       $tests = $row['tests'];
-                       $height = $row['height'];
-                       $width = $row['width'];
-                       foreach ( $tests as $max => $expected ) {
-                               $y = round( $expected * $height / $width );
-                               $result = MediaHandler::fitBoxWidth( $width, $height, $max );
-                               $y2 = round( $result * $height / $width );
-                               $this->assertEquals( $expected,
-                                       $result,
-                                       "($width, $height, $max) wanted: {$expected}x$y, got: {$result}x$y2" );
-                       }
+                                       18 => 4 )
+                       )
+               );
+       }
+
+       private function provideTestFitBoxWidthSingle( $width, $height, $tests ) {
+               $result = array();
+               foreach ( $tests as $max => $expected ) {
+                       $result[] = array( $width, $height, $max, $expected );
                }
+               return $result;
        }
 }
index f4b469b..af83767 100644 (file)
  *
  * @todo covers tags, will be UtfNormal::cleanUp once the below is resolved
  * @todo split me into test methods and providers per the below comment
+ * @todo Document individual tests
  *
  * We ignore code coverage for this test suite until they are rewritten
  * to use data providers (bug 46561).
  * @codeCoverageIgnore
  */
 class CleanUpTest extends MediaWikiTestCase {
-       /** @todo document */
        public function testAscii() {
                $text = 'This is plain ASCII text.';
                $this->assertEquals( $text, UtfNormal::cleanUp( $text ) );
        }
 
-       /** @todo document */
        public function testNull() {
                $text = "a \x00 null";
                $expect = "a \xef\xbf\xbd null";
@@ -54,13 +53,11 @@ class CleanUpTest extends MediaWikiTestCase {
                        bin2hex( UtfNormal::cleanUp( $text ) ) );
        }
 
-       /** @todo document */
        public function testLatin() {
                $text = "L'\xc3\xa9cole";
                $this->assertEquals( $text, UtfNormal::cleanUp( $text ) );
        }
 
-       /** @todo document */
        public function testLatinNormal() {
                $text = "L'e\xcc\x81cole";
                $expect = "L'\xc3\xa9cole";
@@ -69,7 +66,6 @@ class CleanUpTest extends MediaWikiTestCase {
 
        /**
         * This test is *very* expensive!
-        * @todo document
         */
        function XtestAllChars() {
                $rep = UTF8_REPLACEMENT;
@@ -109,7 +105,6 @@ class CleanUpTest extends MediaWikiTestCase {
                }
        }
 
-       /** @todo document */
        public static function provideAllBytes() {
                return array(
                        array( '', '' ),
@@ -121,7 +116,6 @@ class CleanUpTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideAllBytes
-        * @todo document
         */
        function testBytes( $head, $tail ) {
                for ( $i = 0x0; $i < 256; $i++ ) {
@@ -156,7 +150,6 @@ class CleanUpTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideAllBytes
-        * @todo document
         */
        function testDoubleBytes( $head, $tail ) {
                for ( $first = 0xc0; $first < 0x100; $first += 2 ) {
@@ -202,7 +195,6 @@ class CleanUpTest extends MediaWikiTestCase {
 
        /**
         * @dataProvider provideAllBytes
-        * @todo document
         */
        function testTripleBytes( $head, $tail ) {
                for ( $first = 0xc0; $first < 0x100; $first += 2 ) {
@@ -275,7 +267,6 @@ class CleanUpTest extends MediaWikiTestCase {
                }
        }
 
-       /** @todo document */
        public function testChunkRegression() {
                # Check for regression against a chunking bug
                $text = "\x46\x55\xb8" .
@@ -298,7 +289,6 @@ class CleanUpTest extends MediaWikiTestCase {
                        bin2hex( UtfNormal::cleanUp( $text ) ) );
        }
 
-       /** @todo document */
        public function testInterposeRegression() {
                $text = "\x4e\x30" .
                        "\xb1" . # bad tail
@@ -333,7 +323,6 @@ class CleanUpTest extends MediaWikiTestCase {
                        bin2hex( UtfNormal::cleanUp( $text ) ) );
        }
 
-       /** @todo document */
        public function testOverlongRegression() {
                $text = "\x67" .
                        "\x1a" . # forbidden ascii
@@ -358,7 +347,6 @@ class CleanUpTest extends MediaWikiTestCase {
                        bin2hex( UtfNormal::cleanUp( $text ) ) );
        }
 
-       /** @todo document */
        public function testSurrogateRegression() {
                $text = "\xed\xb4\x96" . # surrogate 0xDD16
                        "\x83" . # bad tail
@@ -373,7 +361,6 @@ class CleanUpTest extends MediaWikiTestCase {
                        bin2hex( UtfNormal::cleanUp( $text ) ) );
        }
 
-       /** @todo document */
        public function testBomRegression() {
                $text = "\xef\xbf\xbe" . # U+FFFE, illegal char
                        "\xb2" . # bad tail
@@ -388,7 +375,6 @@ class CleanUpTest extends MediaWikiTestCase {
                        bin2hex( UtfNormal::cleanUp( $text ) ) );
        }
 
-       /** @todo document */
        public function testForbiddenRegression() {
                $text = "\xef\xbf\xbf"; # U+FFFF, illegal char
                $expect = "\xef\xbf\xbd";
@@ -397,7 +383,6 @@ class CleanUpTest extends MediaWikiTestCase {
                        bin2hex( UtfNormal::cleanUp( $text ) ) );
        }
 
-       /** @todo document */
        public function testHangulRegression() {
                $text = "\xed\x9c\xaf" . # Hangul char
                        "\xe1\x87\x81"; # followed by another final jamo
index c024cee..a6b4880 100644 (file)
@@ -1,5 +1,9 @@
 <?php
 
+/**
+ * @group Database
+ *        ^--- trigger DB shadowing because we are using Title magic
+ */
 class ParserOutputTest extends MediaWikiTestCase {
 
        public static function provideIsLinkInternal() {
@@ -84,4 +88,66 @@ class ParserOutputTest extends MediaWikiTestCase {
                $this->assertEquals( $po->getProperty( 'foo' ), false );
                $this->assertArrayNotHasKey( 'foo', $properties );
        }
+
+       /**
+        * @covers ParserOutput::hasCustomDataUpdates
+        * @covers ParserOutput::addSecondaryDataUpdate
+        */
+       public function testHasCustomDataUpdates() {
+               $po = new ParserOutput();
+               $this->assertFalse( $po->hasCustomDataUpdates() );
+
+               $dataUpdate = $this->getMock( 'DataUpdate' );
+               $po->addSecondaryDataUpdate( $dataUpdate );
+               $this->assertTrue( $po->hasCustomDataUpdates() );
+       }
+
+       /**
+        * @covers ParserOutput::getSecondaryDataUpdate
+        * @covers ParserOutput::addSecondaryDataUpdate
+        */
+       public function testGetSecondaryDataUpdates() {
+               // NOTE: getSecondaryDataUpdates always returns a LinksUpdate object
+               // in addition to the DataUpdates registered via addSecondaryDataUpdate().
+
+               $title = Title::makeTitle( NS_MAIN, 'Dummy' );
+               $title->resetArticleID( 7777777 );
+
+               $po = new ParserOutput();
+               $this->assertCount( 1, $po->getSecondaryDataUpdates( $title ) );
+
+               $dataUpdate = $this->getMock( 'DataUpdate' );
+               $po->addSecondaryDataUpdate( $dataUpdate );
+               $this->assertCount( 2, $po->getSecondaryDataUpdates( $title ) );
+
+               // Test Fallback to getTitleText
+               $this->insertPage( 'Project:ParserOutputTestDummyPage' );
+               $po->setTitleText( 'Project:ParserOutputTestDummyPage' );
+               $this->assertCount( 2, $po->getSecondaryDataUpdates() );
+       }
+
+       /**
+        * @covers ParserOutput::getSecondaryDataUpdate
+        * @covers ParserOutput::__sleep
+        */
+       public function testGetSecondaryDataUpdates_serialization() {
+               $title = Title::makeTitle( NS_MAIN, 'Dummy' );
+               $title->resetArticleID( 7777777 );
+
+               $po = new ParserOutput();
+
+               // Serializing is fine with no custom DataUpdates.
+               $po = unserialize( serialize( $po ) );
+               $this->assertCount( 1, $po->getSecondaryDataUpdates( $title ) );
+
+               // If there are custom DataUpdates, getSecondaryDataUpdates
+               // should fail after serialization.
+               $dataUpdate = $this->getMock( 'DataUpdate' );
+               $po->addSecondaryDataUpdate( $dataUpdate );
+               $po = unserialize( serialize( $po ) );
+
+               $this->setExpectedException( 'MWException' );
+               $po->getSecondaryDataUpdates( $title );
+       }
+
 }
diff --git a/tests/phpunit/includes/registration/ExtensionProcessorTest.php b/tests/phpunit/includes/registration/ExtensionProcessorTest.php
new file mode 100644 (file)
index 0000000..221c258
--- /dev/null
@@ -0,0 +1,135 @@
+<?php
+
+class ExtensionProcessorTest extends MediaWikiTestCase {
+
+       private $dir;
+
+       public function setUp() {
+               parent::setUp();
+               $this->dir = __DIR__ . '/FooBar/extension.json';
+       }
+
+       /**
+        * 'name' is absolutely required
+        *
+        * @var array
+        */
+       static $default = array(
+               'name' => 'FooBar',
+       );
+
+       public static function provideRegisterHooks() {
+               return array(
+                       // No hooks
+                       array(
+                               array(),
+                               self::$default,
+                               array(),
+                       ),
+                       // No current hooks, adding one for "FooBaz"
+                       array(
+                               array(),
+                               array( 'Hooks' => array( 'FooBaz' => 'FooBazCallback' ) ) + self::$default,
+                               array( 'FooBaz' => array( 'FooBazCallback' ) ),
+                       ),
+                       // Hook for "FooBaz", adding another one
+                       array(
+                               array( 'FooBaz' => array( 'PriorCallback' ) ),
+                               array( 'Hooks' => array( 'FooBaz' => 'FooBazCallback' ) ) + self::$default,
+                               array( 'FooBaz' => array( 'PriorCallback', 'FooBazCallback' ) ),
+                       ),
+                       // Hook for "BarBaz", adding one for "FooBaz"
+                       array(
+                               array( 'BarBaz' => array( 'BarBazCallback' ) ),
+                               array( 'Hooks' => array( 'FooBaz' => 'FooBazCallback' ) ) + self::$default,
+                               array(
+                                       'BarBaz' => array( 'BarBazCallback' ),
+                                       'FooBaz' => array( 'FooBazCallback' ),
+                               ),
+                       ),
+               );
+       }
+
+       /**
+        * @covers ExtensionProcessor::extractHooks
+        * @dataProvider provideRegisterHooks
+        */
+       public function testRegisterHooks( $pre, $info, $expected ) {
+               $processor = new MockExtensionProcessor( array( 'wgHooks' => $pre ) );
+               $processor->extractInfo( $this->dir, $info );
+               $extracted = $processor->getExtractedInfo();
+               $this->assertEquals( $expected, $extracted['globals']['wgHooks'] );
+       }
+
+       /**
+        * @covers ExtensionProcessor::extractConfig
+        */
+       public function testExtractConfig() {
+               $processor = new ExtensionProcessor;
+               $info = array(
+                       'config' => array(
+                               'Bar' => 'somevalue',
+                               'Foo' => 10,
+                       ),
+               ) + self::$default;
+               $processor->extractInfo( $this->dir, $info );
+               $extracted = $processor->getExtractedInfo();
+               $this->assertEquals( 'somevalue', $extracted['globals']['wgBar'] );
+               $this->assertEquals( 10, $extracted['globals']['wgFoo'] );
+       }
+
+       public static function provideSetToGlobal() {
+               return array(
+                       array(
+                               array( 'wgAPIModules', 'wgAvailableRights' ),
+                               array(),
+                               array(
+                                       'APIModules' => array( 'foobar' => 'ApiFooBar' ),
+                                       'AvailableRights' => array( 'foobar', 'unfoobar' ),
+                               ),
+                               array(
+                                       'wgAPIModules' => array( 'foobar' => 'ApiFooBar' ),
+                                       'wgAvailableRights' => array( 'foobar', 'unfoobar' ),
+                               ),
+                       ),
+                       array(
+                               array( 'wgAPIModules', 'wgAvailableRights' ),
+                               array(
+                                       'wgAPIModules' => array( 'barbaz' => 'ApiBarBaz' ),
+                                       'wgAvailableRights' => array( 'barbaz' )
+                               ),
+                               array(
+                                       'APIModules' => array( 'foobar' => 'ApiFooBar' ),
+                                       'AvailableRights' => array( 'foobar', 'unfoobar' ),
+                               ),
+                               array(
+                                       'wgAPIModules' => array( 'barbaz' => 'ApiBarBaz', 'foobar' => 'ApiFooBar' ),
+                                       'wgAvailableRights' => array( 'barbaz', 'foobar', 'unfoobar' ),
+                               ),
+                       ),
+                       array(
+                               array( 'wgGroupPermissions' ),
+                               array(
+                                       'wgGroupPermissions' => array( 'sysop' => array( 'delete' ) ),
+                               ),
+                               array(
+                                       'GroupPermissions' => array( 'sysop' => array( 'undelete' ), 'user' => array( 'edit' ) ),
+                               ),
+                               array(
+                                       'wgGroupPermissions' => array( 'sysop' => array( 'delete', 'undelete' ), 'user' => array( 'edit' ) ),
+                               )
+                       )
+               );
+       }
+}
+
+
+/**
+ * Allow overriding the default value of $this->globals
+ * so we can test merging
+ */
+class MockExtensionProcessor extends ExtensionProcessor {
+       public function __construct( $globals = array() ) {
+               $this->globals = $globals + $this->globals;
+       }
+}
diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderStartUpModuleTest.php
new file mode 100644 (file)
index 0000000..7f3506c
--- /dev/null
@@ -0,0 +1,388 @@
+<?php
+
+class ResourceLoaderStartUpModuleTest extends ResourceLoaderTestCase {
+
+       public static function provideGetModuleRegistrations() {
+               return array(
+                       array( array(
+                               'msg' => 'Empty registry',
+                               'modules' => array(),
+                               'out' => '
+mw.loader.addSource( {
+    "local": "/w/load.php"
+} );mw.loader.register( [] );'
+                       ) ),
+                       array( array(
+                               'msg' => 'Basic registry',
+                               'modules' => array(
+                                       'test.blank' => new ResourceLoaderTestModule(),
+                               ),
+                               'out' => '
+mw.loader.addSource( {
+    "local": "/w/load.php"
+} );mw.loader.register( [
+    [
+        "test.blank",
+        1388534400
+    ]
+] );',
+                       ) ),
+                       array( array(
+                               'msg' => 'Group signature',
+                               'modules' => array(
+                                       'test.blank' => new ResourceLoaderTestModule(),
+                                       'test.group.foo' => new ResourceLoaderTestModule( array( 'group' => 'x-foo' ) ),
+                                       'test.group.bar' => new ResourceLoaderTestModule( array( 'group' => 'x-bar' ) ),
+                               ),
+                               'out' => '
+mw.loader.addSource( {
+    "local": "/w/load.php"
+} );mw.loader.register( [
+    [
+        "test.blank",
+        1388534400
+    ],
+    [
+        "test.group.foo",
+        1388534400,
+        [],
+        "x-foo"
+    ],
+    [
+        "test.group.bar",
+        1388534400,
+        [],
+        "x-bar"
+    ]
+] );'
+                       ) ),
+                       array( array(
+                               'msg' => 'Different target (non-test should not be registered)',
+                               'modules' => array(
+                                       'test.blank' => new ResourceLoaderTestModule(),
+                                       'test.target.foo' => new ResourceLoaderTestModule( array( 'targets' => array( 'x-foo' ) ) ),
+                               ),
+                               'out' => '
+mw.loader.addSource( {
+    "local": "/w/load.php"
+} );mw.loader.register( [
+    [
+        "test.blank",
+        1388534400
+    ]
+] );'
+                       ) ),
+                       array( array(
+                               'msg' => 'Foreign source',
+                               'sources' => array(
+                                       'example' => array(
+                                               'loadScript' => 'http://example.org/w/load.php',
+                                               'apiScript' => 'http://example.org/w/api.php',
+                                       ),
+                               ),
+                               'modules' => array(
+                                       'test.blank' => new ResourceLoaderTestModule( array( 'source' => 'example' ) ),
+                               ),
+                               'out' => '
+mw.loader.addSource( {
+    "local": "/w/load.php",
+    "example": "http://example.org/w/load.php"
+} );mw.loader.register( [
+    [
+        "test.blank",
+        1388534400,
+        [],
+        null,
+        "example"
+    ]
+] );'
+                       ) ),
+                       array( array(
+                               'msg' => 'Conditional dependency function',
+                               'modules' => array(
+                                       'test.x.core' => new ResourceLoaderTestModule(),
+                                       'test.x.polyfill' => new ResourceLoaderTestModule( array(
+                                               'skipFunction' => 'return true;'
+                                       ) ),
+                                       'test.y.polyfill' => new ResourceLoaderTestModule( array(
+                                               'skipFunction' =>
+                                                       'return !!(' .
+                                                       '    window.JSON &&' .
+                                                       '    JSON.parse &&' .
+                                                       '    JSON.stringify' .
+                                                       ');'
+                                       ) ),
+                                       'test.z.foo' => new ResourceLoaderTestModule( array(
+                                               'dependencies' => array(
+                                                       'test.x.core',
+                                                       'test.x.polyfill',
+                                                       'test.y.polyfill',
+                                               ),
+                                       ) ),
+                               ),
+                               'out' => '
+mw.loader.addSource( {
+    "local": "/w/load.php"
+} );mw.loader.register( [
+    [
+        "test.x.core",
+        1388534400
+    ],
+    [
+        "test.x.polyfill",
+        1388534400,
+        [],
+        null,
+        null,
+        "return true;"
+    ],
+    [
+        "test.y.polyfill",
+        1388534400,
+        [],
+        null,
+        null,
+        "return !!(    window.JSON \u0026\u0026    JSON.parse \u0026\u0026    JSON.stringify);"
+    ],
+    [
+        "test.z.foo",
+        1388534400,
+        [
+            0,
+            1,
+            2
+        ]
+    ]
+] );',
+                       ) ),
+                       array( array(
+                               // This may seem like an edge case, but a plain MediaWiki core install
+                               // with a few extensions installed is likely far more complex than this
+                               // even, not to mention an install like Wikipedia.
+                               // TODO: Make this even more realistic.
+                               'msg' => 'Advanced (everything combined)',
+                               'sources' => array(
+                                       'example' => array(
+                                               'loadScript' => 'http://example.org/w/load.php',
+                                               'apiScript' => 'http://example.org/w/api.php',
+                                       ),
+                               ),
+                               'modules' => array(
+                                       'test.blank' => new ResourceLoaderTestModule(),
+                                       'test.x.core' => new ResourceLoaderTestModule(),
+                                       'test.x.util' => new ResourceLoaderTestModule( array(
+                                               'dependencies' => array(
+                                                       'test.x.core',
+                                               ),
+                                       ) ),
+                                       'test.x.foo' => new ResourceLoaderTestModule( array(
+                                               'dependencies' => array(
+                                                       'test.x.core',
+                                               ),
+                                       ) ),
+                                       'test.x.bar' => new ResourceLoaderTestModule( array(
+                                               'dependencies' => array(
+                                                       'test.x.core',
+                                                       'test.x.util',
+                                               ),
+                                       ) ),
+                                       'test.x.quux' => new ResourceLoaderTestModule( array(
+                                               'dependencies' => array(
+                                                       'test.x.foo',
+                                                       'test.x.bar',
+                                                       'test.x.util',
+                                                       'test.x.unknown',
+                                               ),
+                                       ) ),
+                                       'test.group.foo.1' => new ResourceLoaderTestModule( array(
+                                               'group' => 'x-foo',
+                                       ) ),
+                                       'test.group.foo.2' => new ResourceLoaderTestModule( array(
+                                               'group' => 'x-foo',
+                                       ) ),
+                                       'test.group.bar.1' => new ResourceLoaderTestModule( array(
+                                               'group' => 'x-bar',
+                                       ) ),
+                                       'test.group.bar.2' => new ResourceLoaderTestModule( array(
+                                               'group' => 'x-bar',
+                                               'source' => 'example',
+                                       ) ),
+                                       'test.target.foo' => new ResourceLoaderTestModule( array(
+                                               'targets' => array( 'x-foo' ),
+                                       ) ),
+                                       'test.target.bar' => new ResourceLoaderTestModule( array(
+                                               'source' => 'example',
+                                               'targets' => array( 'x-foo' ),
+                                       ) ),
+                               ),
+                               'out' => '
+mw.loader.addSource( {
+    "local": "/w/load.php",
+    "example": "http://example.org/w/load.php"
+} );mw.loader.register( [
+    [
+        "test.blank",
+        1388534400
+    ],
+    [
+        "test.x.core",
+        1388534400
+    ],
+    [
+        "test.x.util",
+        1388534400,
+        [
+            1
+        ]
+    ],
+    [
+        "test.x.foo",
+        1388534400,
+        [
+            1
+        ]
+    ],
+    [
+        "test.x.bar",
+        1388534400,
+        [
+            2
+        ]
+    ],
+    [
+        "test.x.quux",
+        1388534400,
+        [
+            3,
+            4,
+            "test.x.unknown"
+        ]
+    ],
+    [
+        "test.group.foo.1",
+        1388534400,
+        [],
+        "x-foo"
+    ],
+    [
+        "test.group.foo.2",
+        1388534400,
+        [],
+        "x-foo"
+    ],
+    [
+        "test.group.bar.1",
+        1388534400,
+        [],
+        "x-bar"
+    ],
+    [
+        "test.group.bar.2",
+        1388534400,
+        [],
+        "x-bar",
+        "example"
+    ]
+] );'
+                       ) ),
+               );
+       }
+
+       /**
+        * @dataProvider provideGetModuleRegistrations
+        * @covers ResourceLoaderStartUpModule::compileUnresolvedDependencies
+        * @covers ResourceLoaderStartUpModule::getModuleRegistrations
+        * @covers ResourceLoader::makeLoaderSourcesScript
+        * @covers ResourceLoader::makeLoaderRegisterScript
+        */
+       public function testGetModuleRegistrations( $case ) {
+               if ( isset( $case['sources'] ) ) {
+                       $this->setMwGlobals( 'wgResourceLoaderSources', $case['sources'] );
+               }
+
+               $context = $this->getResourceLoaderContext();
+               $rl = $context->getResourceLoader();
+
+               $rl->register( $case['modules'] );
+
+               $module = new ResourceLoaderStartUpModule();
+               $this->assertEquals(
+                       ltrim( $case['out'], "\n" ),
+                       $module->getModuleRegistrations( $context ),
+                       $case['msg']
+               );
+       }
+
+       public static function provideRegistrations() {
+               return array(
+                       array( array(
+                               'test.blank' => new ResourceLoaderTestModule(),
+                               'test.min' => new ResourceLoaderTestModule( array(
+                                       'skipFunction' =>
+                                               'return !!(' .
+                                               '    window.JSON &&' .
+                                               '    JSON.parse &&' .
+                                               '    JSON.stringify' .
+                                               ');',
+                                       'dependencies' => array(
+                                               'test.blank',
+                                       ),
+                               ) ),
+                       ) )
+               );
+       }
+       /**
+        * @dataProvider provideRegistrations
+        */
+       public function testRegistrationsMinified( $modules ) {
+               $this->setMwGlobals( 'wgResourceLoaderDebug', false );
+
+               $context = $this->getResourceLoaderContext();
+               $rl = $context->getResourceLoader();
+               $rl->register( $modules );
+               $module = new ResourceLoaderStartUpModule();
+               $this->assertEquals(
+'mw.loader.addSource({"local":"/w/load.php"});'
+. 'mw.loader.register(['
+. '["test.blank",1388534400],'
+. '["test.min",1388534400,[0],null,null,'
+. '"return!!(window.JSON\u0026\u0026JSON.parse\u0026\u0026JSON.stringify);"'
+. ']]);',
+                       $module->getModuleRegistrations( $context ),
+                       'Minified output'
+               );
+       }
+
+       /**
+        * @dataProvider provideRegistrations
+        */
+       public function testRegistrationsUnminified( $modules ) {
+               $context = $this->getResourceLoaderContext();
+               $rl = $context->getResourceLoader();
+               $rl->register( $modules );
+               $module = new ResourceLoaderStartUpModule();
+               $this->assertEquals(
+'mw.loader.addSource( {
+    "local": "/w/load.php"
+} );mw.loader.register( [
+    [
+        "test.blank",
+        1388534400
+    ],
+    [
+        "test.min",
+        1388534400,
+        [
+            0
+        ],
+        null,
+        null,
+        "return !!(    window.JSON \u0026\u0026    JSON.parse \u0026\u0026    JSON.stringify);"
+    ]
+] );',
+                       $module->getModuleRegistrations( $context ),
+                       'Unminified output'
+               );
+       }
+
+}
diff --git a/tests/phpunit/includes/resourceloader/ResourceLoaderStartupModuleTest.php b/tests/phpunit/includes/resourceloader/ResourceLoaderStartupModuleTest.php
deleted file mode 100644 (file)
index 69854d5..0000000
+++ /dev/null
@@ -1,388 +0,0 @@
-<?php
-
-class ResourceLoaderStartupModuleTest extends ResourceLoaderTestCase {
-
-       public static function provideGetModuleRegistrations() {
-               return array(
-                       array( array(
-                               'msg' => 'Empty registry',
-                               'modules' => array(),
-                               'out' => '
-mw.loader.addSource( {
-    "local": "/w/load.php"
-} );mw.loader.register( [] );'
-                       ) ),
-                       array( array(
-                               'msg' => 'Basic registry',
-                               'modules' => array(
-                                       'test.blank' => new ResourceLoaderTestModule(),
-                               ),
-                               'out' => '
-mw.loader.addSource( {
-    "local": "/w/load.php"
-} );mw.loader.register( [
-    [
-        "test.blank",
-        1388534400
-    ]
-] );',
-                       ) ),
-                       array( array(
-                               'msg' => 'Group signature',
-                               'modules' => array(
-                                       'test.blank' => new ResourceLoaderTestModule(),
-                                       'test.group.foo' => new ResourceLoaderTestModule( array( 'group' => 'x-foo' ) ),
-                                       'test.group.bar' => new ResourceLoaderTestModule( array( 'group' => 'x-bar' ) ),
-                               ),
-                               'out' => '
-mw.loader.addSource( {
-    "local": "/w/load.php"
-} );mw.loader.register( [
-    [
-        "test.blank",
-        1388534400
-    ],
-    [
-        "test.group.foo",
-        1388534400,
-        [],
-        "x-foo"
-    ],
-    [
-        "test.group.bar",
-        1388534400,
-        [],
-        "x-bar"
-    ]
-] );'
-                       ) ),
-                       array( array(
-                               'msg' => 'Different target (non-test should not be registered)',
-                               'modules' => array(
-                                       'test.blank' => new ResourceLoaderTestModule(),
-                                       'test.target.foo' => new ResourceLoaderTestModule( array( 'targets' => array( 'x-foo' ) ) ),
-                               ),
-                               'out' => '
-mw.loader.addSource( {
-    "local": "/w/load.php"
-} );mw.loader.register( [
-    [
-        "test.blank",
-        1388534400
-    ]
-] );'
-                       ) ),
-                       array( array(
-                               'msg' => 'Foreign source',
-                               'sources' => array(
-                                       'example' => array(
-                                               'loadScript' => 'http://example.org/w/load.php',
-                                               'apiScript' => 'http://example.org/w/api.php',
-                                       ),
-                               ),
-                               'modules' => array(
-                                       'test.blank' => new ResourceLoaderTestModule( array( 'source' => 'example' ) ),
-                               ),
-                               'out' => '
-mw.loader.addSource( {
-    "local": "/w/load.php",
-    "example": "http://example.org/w/load.php"
-} );mw.loader.register( [
-    [
-        "test.blank",
-        1388534400,
-        [],
-        null,
-        "example"
-    ]
-] );'
-                       ) ),
-                       array( array(
-                               'msg' => 'Conditional dependency function',
-                               'modules' => array(
-                                       'test.x.core' => new ResourceLoaderTestModule(),
-                                       'test.x.polyfill' => new ResourceLoaderTestModule( array(
-                                               'skipFunction' => 'return true;'
-                                       ) ),
-                                       'test.y.polyfill' => new ResourceLoaderTestModule( array(
-                                               'skipFunction' =>
-                                                       'return !!(' .
-                                                       '    window.JSON &&' .
-                                                       '    JSON.parse &&' .
-                                                       '    JSON.stringify' .
-                                                       ');'
-                                       ) ),
-                                       'test.z.foo' => new ResourceLoaderTestModule( array(
-                                               'dependencies' => array(
-                                                       'test.x.core',
-                                                       'test.x.polyfill',
-                                                       'test.y.polyfill',
-                                               ),
-                                       ) ),
-                               ),
-                               'out' => '
-mw.loader.addSource( {
-    "local": "/w/load.php"
-} );mw.loader.register( [
-    [
-        "test.x.core",
-        1388534400
-    ],
-    [
-        "test.x.polyfill",
-        1388534400,
-        [],
-        null,
-        null,
-        "return true;"
-    ],
-    [
-        "test.y.polyfill",
-        1388534400,
-        [],
-        null,
-        null,
-        "return !!(    window.JSON \u0026\u0026    JSON.parse \u0026\u0026    JSON.stringify);"
-    ],
-    [
-        "test.z.foo",
-        1388534400,
-        [
-            0,
-            1,
-            2
-        ]
-    ]
-] );',
-                       ) ),
-                       array( array(
-                               // This may seem like an edge case, but a plain MediaWiki core install
-                               // with a few extensions installed is likely far more complex than this
-                               // even, not to mention an install like Wikipedia.
-                               // TODO: Make this even more realistic.
-                               'msg' => 'Advanced (everything combined)',
-                               'sources' => array(
-                                       'example' => array(
-                                               'loadScript' => 'http://example.org/w/load.php',
-                                               'apiScript' => 'http://example.org/w/api.php',
-                                       ),
-                               ),
-                               'modules' => array(
-                                       'test.blank' => new ResourceLoaderTestModule(),
-                                       'test.x.core' => new ResourceLoaderTestModule(),
-                                       'test.x.util' => new ResourceLoaderTestModule( array(
-                                               'dependencies' => array(
-                                                       'test.x.core',
-                                               ),
-                                       ) ),
-                                       'test.x.foo' => new ResourceLoaderTestModule( array(
-                                               'dependencies' => array(
-                                                       'test.x.core',
-                                               ),
-                                       ) ),
-                                       'test.x.bar' => new ResourceLoaderTestModule( array(
-                                               'dependencies' => array(
-                                                       'test.x.core',
-                                                       'test.x.util',
-                                               ),
-                                       ) ),
-                                       'test.x.quux' => new ResourceLoaderTestModule( array(
-                                               'dependencies' => array(
-                                                       'test.x.foo',
-                                                       'test.x.bar',
-                                                       'test.x.util',
-                                                       'test.x.unknown',
-                                               ),
-                                       ) ),
-                                       'test.group.foo.1' => new ResourceLoaderTestModule( array(
-                                               'group' => 'x-foo',
-                                       ) ),
-                                       'test.group.foo.2' => new ResourceLoaderTestModule( array(
-                                               'group' => 'x-foo',
-                                       ) ),
-                                       'test.group.bar.1' => new ResourceLoaderTestModule( array(
-                                               'group' => 'x-bar',
-                                       ) ),
-                                       'test.group.bar.2' => new ResourceLoaderTestModule( array(
-                                               'group' => 'x-bar',
-                                               'source' => 'example',
-                                       ) ),
-                                       'test.target.foo' => new ResourceLoaderTestModule( array(
-                                               'targets' => array( 'x-foo' ),
-                                       ) ),
-                                       'test.target.bar' => new ResourceLoaderTestModule( array(
-                                               'source' => 'example',
-                                               'targets' => array( 'x-foo' ),
-                                       ) ),
-                               ),
-                               'out' => '
-mw.loader.addSource( {
-    "local": "/w/load.php",
-    "example": "http://example.org/w/load.php"
-} );mw.loader.register( [
-    [
-        "test.blank",
-        1388534400
-    ],
-    [
-        "test.x.core",
-        1388534400
-    ],
-    [
-        "test.x.util",
-        1388534400,
-        [
-            1
-        ]
-    ],
-    [
-        "test.x.foo",
-        1388534400,
-        [
-            1
-        ]
-    ],
-    [
-        "test.x.bar",
-        1388534400,
-        [
-            2
-        ]
-    ],
-    [
-        "test.x.quux",
-        1388534400,
-        [
-            3,
-            4,
-            "test.x.unknown"
-        ]
-    ],
-    [
-        "test.group.foo.1",
-        1388534400,
-        [],
-        "x-foo"
-    ],
-    [
-        "test.group.foo.2",
-        1388534400,
-        [],
-        "x-foo"
-    ],
-    [
-        "test.group.bar.1",
-        1388534400,
-        [],
-        "x-bar"
-    ],
-    [
-        "test.group.bar.2",
-        1388534400,
-        [],
-        "x-bar",
-        "example"
-    ]
-] );'
-                       ) ),
-               );
-       }
-
-       /**
-        * @dataProvider provideGetModuleRegistrations
-        * @covers ResourceLoaderStartupModule::compileUnresolvedDependencies
-        * @covers ResourceLoaderStartUpModule::getModuleRegistrations
-        * @covers ResourceLoader::makeLoaderSourcesScript
-        * @covers ResourceLoader::makeLoaderRegisterScript
-        */
-       public function testGetModuleRegistrations( $case ) {
-               if ( isset( $case['sources'] ) ) {
-                       $this->setMwGlobals( 'wgResourceLoaderSources', $case['sources'] );
-               }
-
-               $context = $this->getResourceLoaderContext();
-               $rl = $context->getResourceLoader();
-
-               $rl->register( $case['modules'] );
-
-               $module = new ResourceLoaderStartUpModule();
-               $this->assertEquals(
-                       ltrim( $case['out'], "\n" ),
-                       $module->getModuleRegistrations( $context ),
-                       $case['msg']
-               );
-       }
-
-       public static function provideRegistrations() {
-               return array(
-                       array( array(
-                               'test.blank' => new ResourceLoaderTestModule(),
-                               'test.min' => new ResourceLoaderTestModule( array(
-                                       'skipFunction' =>
-                                               'return !!(' .
-                                               '    window.JSON &&' .
-                                               '    JSON.parse &&' .
-                                               '    JSON.stringify' .
-                                               ');',
-                                       'dependencies' => array(
-                                               'test.blank',
-                                       ),
-                               ) ),
-                       ) )
-               );
-       }
-       /**
-        * @dataProvider provideRegistrations
-        */
-       public function testRegistrationsMinified( $modules ) {
-               $this->setMwGlobals( 'wgResourceLoaderDebug', false );
-
-               $context = $this->getResourceLoaderContext();
-               $rl = $context->getResourceLoader();
-               $rl->register( $modules );
-               $module = new ResourceLoaderStartUpModule();
-               $this->assertEquals(
-'mw.loader.addSource({"local":"/w/load.php"});'
-. 'mw.loader.register(['
-. '["test.blank",1388534400],'
-. '["test.min",1388534400,[0],null,null,'
-. '"return!!(window.JSON\u0026\u0026JSON.parse\u0026\u0026JSON.stringify);"'
-. ']]);',
-                       $module->getModuleRegistrations( $context ),
-                       'Minified output'
-               );
-       }
-
-       /**
-        * @dataProvider provideRegistrations
-        */
-       public function testRegistrationsUnminified( $modules ) {
-               $context = $this->getResourceLoaderContext();
-               $rl = $context->getResourceLoader();
-               $rl->register( $modules );
-               $module = new ResourceLoaderStartUpModule();
-               $this->assertEquals(
-'mw.loader.addSource( {
-    "local": "/w/load.php"
-} );mw.loader.register( [
-    [
-        "test.blank",
-        1388534400
-    ],
-    [
-        "test.min",
-        1388534400,
-        [
-            0
-        ],
-        null,
-        null,
-        "return !!(    window.JSON \u0026\u0026    JSON.parse \u0026\u0026    JSON.stringify);"
-    ]
-] );',
-                       $module->getModuleRegistrations( $context ),
-                       'Unminified output'
-               );
-       }
-
-}
index af02429..bbe8cc7 100644 (file)
  */
 class SiteListFileCacheBuilderTest extends PHPUnit_Framework_TestCase {
 
-       public function testBuild() {
-               $cacheFile = $this->getCacheFile();
+       protected function setUp() {
+               $this->cacheFile = $this->getCacheFile();
+       }
 
-               $cacheBuilder = $this->newSiteListFileCacheBuilder( $this->getSites(), $cacheFile );
+       protected function tearDown() {
+               unlink( $this->cacheFile );
+       }
+
+       public function testBuild() {
+               $cacheBuilder = $this->newSiteListFileCacheBuilder( $this->getSites() );
                $cacheBuilder->build();
 
-               $contents = file_get_contents( $cacheFile );
+               $contents = file_get_contents( $this->cacheFile );
                $this->assertEquals( json_encode( $this->getExpectedData() ), $contents );
        }
 
@@ -85,10 +91,10 @@ class SiteListFileCacheBuilderTest extends PHPUnit_Framework_TestCase {
                );
        }
 
-       private function newSiteListFileCacheBuilder( SiteList $sites, $cacheFile ) {
+       private function newSiteListFileCacheBuilder( SiteList $sites ) {
                return new SiteListFileCacheBuilder(
                        $this->getSiteSQLStore( $sites ),
-                       $cacheFile
+                       $this->cacheFile
                );
        }
 
@@ -124,7 +130,7 @@ class SiteListFileCacheBuilderTest extends PHPUnit_Framework_TestCase {
        }
 
        private function getCacheFile() {
-               return sys_get_temp_dir() . '/sites-' . time() . '.json';
+               return tempnam( sys_get_temp_dir(), 'mw-test-sitelist' );
        }
 
 }
index b598eed..05dcd8a 100644 (file)
  */
 class SiteListFileCacheTest extends PHPUnit_Framework_TestCase {
 
-       public function testGetSites() {
-               $cacheFile = $this->getCacheFile();
+       protected function setUp() {
+               $this->cacheFile = $this->getCacheFile();
+       }
+
+       protected function tearDown() {
+               unlink( $this->cacheFile );
+       }
 
+       public function testGetSites() {
                $sites = $this->getSites();
-               $cacheBuilder = $this->newSiteListFileCacheBuilder( $sites, $cacheFile );
+               $cacheBuilder = $this->newSiteListFileCacheBuilder( $sites );
                $cacheBuilder->build();
 
-               $cache = new SiteListFileCache( $cacheFile );
+               $cache = new SiteListFileCache( $this->cacheFile );
                $this->assertEquals( $sites, $cache->getSites() );
        }
 
        public function testGetSite() {
-               $cacheFile = $this->getCacheFile();
-
                $sites = $this->getSites();
-               $cacheBuilder = $this->newSiteListFileCacheBuilder( $sites, $cacheFile );
+               $cacheBuilder = $this->newSiteListFileCacheBuilder( $sites );
                $cacheBuilder->build();
 
-               $cache = new SiteListFileCache( $cacheFile );
+               $cache = new SiteListFileCache( $this->cacheFile );
 
                $this->assertEquals( $sites->getSite( 'enwiktionary' ), $cache->getSite( 'enwiktionary' ) );
        }
 
-       private function newSiteListFileCacheBuilder( SiteList $sites, $cacheFile ) {
+       private function newSiteListFileCacheBuilder( SiteList $sites ) {
                return new SiteListFileCacheBuilder(
                        $this->getSiteSQLStore( $sites ),
-                       $cacheFile
+                       $this->cacheFile
                );
        }
 
@@ -92,7 +96,7 @@ class SiteListFileCacheTest extends PHPUnit_Framework_TestCase {
        }
 
        private function getCacheFile() {
-               return sys_get_temp_dir() . '/sites-' . time() . '.json';
+               return tempnam( sys_get_temp_dir(), 'mw-test-sitelist' );
        }
 
 }
diff --git a/tests/phpunit/includes/title/ForeignTitleTest.php b/tests/phpunit/includes/title/ForeignTitleTest.php
new file mode 100644 (file)
index 0000000..04af871
--- /dev/null
@@ -0,0 +1,104 @@
+<?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
+ * @license GPL 2+
+ * @author This, that and the other
+ */
+
+/**
+ * @covers ForeignTitle
+ *
+ * @group Title
+ */
+class ForeignTitleTest extends MediaWikiTestCase {
+
+       public function basicProvider() {
+               return array(
+                       array(
+                               new ForeignTitle( 20, 'Contributor', 'JohnDoe' ),
+                               20, 'Contributor', 'JohnDoe'
+                       ),
+                       array(
+                               new ForeignTitle( '1', 'Discussion', 'Capital' ),
+                               1, 'Discussion', 'Capital'
+                       ),
+                       array(
+                               new ForeignTitle( 0, '', 'MainNamespace' ),
+                               0, '', 'MainNamespace'
+                       ),
+                       array(
+                               new ForeignTitle( 4, 'Some ns', 'Article title with spaces' ),
+                               4, 'Some_ns', 'Article_title_with_spaces'
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider basicProvider
+        */
+       public function testBasic( ForeignTitle $title, $expectedId, $expectedName,
+               $expectedText ) {
+
+               $this->assertEquals( true, $title->isNamespaceIdKnown() );
+               $this->assertEquals( $expectedId, $title->getNamespaceId() );
+               $this->assertEquals( $expectedName, $title->getNamespaceName() );
+               $this->assertEquals( $expectedText, $title->getText() );
+       }
+
+       public function testUnknownNamespaceCheck( ) {
+               $title = new ForeignTitle( null, 'this', 'that' );
+
+               $this->assertEquals( false, $title->isNamespaceIdKnown() );
+               $this->assertEquals( 'this', $title->getNamespaceName() );
+               $this->assertEquals( 'that', $title->getText() );
+       }
+
+       public function testUnknownNamespaceError( ) {
+               $this->setExpectedException( 'MWException' );
+               $title = new ForeignTitle( null, 'this', 'that' );
+               $title->getNamespaceId();
+       }
+
+       public function fullTextProvider() {
+               return array(
+                       array(
+                               new ForeignTitle( 20, 'Contributor', 'JohnDoe' ),
+                               'Contributor:JohnDoe'
+                       ),
+                       array(
+                               new ForeignTitle( '1', 'Discussion', 'Capital' ),
+                               'Discussion:Capital'
+                       ),
+                       array(
+                               new ForeignTitle( 0, '', 'MainNamespace' ),
+                               'MainNamespace'
+                       ),
+                       array(
+                               new ForeignTitle( 4, 'Some ns', 'Article title with spaces' ),
+                               'Some_ns:Article_title_with_spaces'
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider fullTextProvider
+        */
+       public function testFullText( ForeignTitle $title, $fullText ) {
+               $this->assertEquals( $fullText, $title->getFullText() );
+       }
+}
diff --git a/tests/phpunit/includes/title/NaiveForeignTitleFactoryTest.php b/tests/phpunit/includes/title/NaiveForeignTitleFactoryTest.php
new file mode 100644 (file)
index 0000000..5d613db
--- /dev/null
@@ -0,0 +1,92 @@
+<?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
+ * @license GPL 2+
+ * @author This, that and the other
+ */
+
+/**
+ * @covers NaiveForeignTitleFactory
+ *
+ * @group Title
+ */
+class NaiveForeignTitleFactoryTest extends MediaWikiTestCase {
+
+       public function basicProvider() {
+               return array(
+                       array(
+                               'MainNamespaceArticle', 0,
+                               new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+                       ),
+                       array(
+                               'MainNamespaceArticle', null,
+                               new ForeignTitle( null, '', 'MainNamespaceArticle' ),
+                       ),
+                       array(
+                               'Talk:Nice_talk', 1,
+                               new ForeignTitle( 1, 'Talk', 'Nice_talk' ),
+                       ),
+                       array(
+                               'Bogus:Nice_talk', 0,
+                               new ForeignTitle( 0, '', 'Bogus:Nice_talk' ),
+                       ),
+                       array(
+                               'Bogus:Nice_talk', 9000, // non-existent local namespace ID
+                               new ForeignTitle( 9000, 'Bogus', 'Nice_talk' ),
+                       ),
+                       array(
+                               'Bogus:Nice_talk', 4, // existing local namespace ID
+                               new ForeignTitle( 4, 'Bogus', 'Nice_talk' ),
+                       ),
+                       array(
+                               'Talk:Extra:Nice_talk', 1,
+                               new ForeignTitle( 1, 'Talk', 'Extra:Nice_talk' ),
+                       ),
+                       array(
+                               'Talk:Extra:Nice_talk', null,
+                               new ForeignTitle( null, 'Talk', 'Extra:Nice_talk' ),
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider basicProvider
+        */
+       public function testBasic( $title, $ns, ForeignTitle $foreignTitle ) {
+               $factory = new NaiveForeignTitleFactory();
+               $testTitle = $factory->createForeignTitle( $title, $ns );
+
+               $this->assertEquals( $testTitle->isNamespaceIdKnown(),
+                       $foreignTitle->isNamespaceIdKnown() );
+
+               if (
+                       $testTitle->isNamespaceIdKnown() &&
+                       $foreignTitle->isNamespaceIdKnown()
+               ) {
+                       $this->assertEquals( $testTitle->getNamespaceId(),
+                               $foreignTitle->getNamespaceId() );
+               }
+
+               $this->assertEquals( $testTitle->getNamespaceName(),
+                       $foreignTitle->getNamespaceName() );
+               $this->assertEquals( $testTitle->getText(), $foreignTitle->getText() );
+
+               $this->assertEquals( str_replace( ' ', '_', $title ),
+                       $foreignTitle->getFullText() );
+       }
+}
diff --git a/tests/phpunit/includes/title/NaiveImportTitleFactoryTest.php b/tests/phpunit/includes/title/NaiveImportTitleFactoryTest.php
new file mode 100644 (file)
index 0000000..a46698a
--- /dev/null
@@ -0,0 +1,90 @@
+<?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
+ * @license GPL 2+
+ * @author This, that and the other
+ */
+
+/**
+ * @covers NaiveImportTitleFactory
+ *
+ * @group Title
+ */
+class NaiveImportTitleFactoryTest extends MediaWikiTestCase {
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       'wgLanguageCode' => 'en',
+                       'wgContLang' => Language::factory( 'en' ),
+                       'wgExtraNamespaces' => array( 100 => 'Portal' ),
+               ) );
+       }
+
+       public function basicProvider() {
+               return array(
+                       array(
+                               new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+                               Title::newFromText( 'MainNamespaceArticle' )
+                       ),
+                       array(
+                               new ForeignTitle( null, '', 'MainNamespaceArticle' ),
+                               Title::newFromText( 'MainNamespaceArticle' )
+                       ),
+                       array(
+                               new ForeignTitle( 1, 'Discussion', 'Nice_talk' ),
+                               Title::newFromText( 'Talk:Nice_talk' )
+                       ),
+                       array(
+                               new ForeignTitle( 0, '', 'Bogus:Nice_talk' ),
+                               Title::newFromText( 'Bogus:Nice_talk' )
+                       ),
+                       array(
+                               new ForeignTitle( 100, 'Bogus', 'Nice_talk' ),
+                               Title::newFromText( 'Bogus:Nice_talk' ) // not Portal:Nice_talk
+                       ),
+                       array(
+                               new ForeignTitle( 1, 'Bogus', 'Nice_talk' ),
+                               Title::newFromText( 'Talk:Nice_talk' ) // not Bogus:Nice_talk
+                       ),
+                       array(
+                               new ForeignTitle( 100, 'Portal', 'Nice_talk' ),
+                               Title::newFromText( 'Portal:Nice_talk' )
+                       ),
+                       array(
+                               new ForeignTitle( 724, 'Portal', 'Nice_talk' ),
+                               Title::newFromText( 'Portal:Nice_talk' )
+                       ),
+                       array(
+                               new ForeignTitle( 2, 'Portal', 'Nice_talk' ),
+                               Title::newFromText( 'User:Nice_talk' )
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider basicProvider
+        */
+       public function testBasic( ForeignTitle $foreignTitle, Title $title ) {
+               $factory = new NaiveImportTitleFactory();
+               $testTitle = $factory->createTitleFromForeignTitle( $foreignTitle );
+
+               $this->assertTrue( $title->equals( $testTitle ) );
+       }
+}
diff --git a/tests/phpunit/includes/title/NamespaceAwareForeignTitleFactoryTest.php b/tests/phpunit/includes/title/NamespaceAwareForeignTitleFactoryTest.php
new file mode 100644 (file)
index 0000000..4d68ab4
--- /dev/null
@@ -0,0 +1,90 @@
+<?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
+ * @license GPL 2+
+ * @author This, that and the other
+ */
+
+/**
+ * @covers NamespaceAwareForeignTitleFactory
+ *
+ * @group Title
+ */
+class NamespaceAwareForeignTitleFactoryTest extends MediaWikiTestCase {
+
+       public function basicProvider() {
+               return array(
+                       array(
+                               'MainNamespaceArticle', 0,
+                               new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+                       ),
+                       array(
+                               'MainNamespaceArticle', null,
+                               new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+                       ),
+                       array(
+                               'Talk:Nice_talk', 1,
+                               new ForeignTitle( 1, 'Talk', 'Nice_talk' ),
+                       ),
+                       array(
+                               'Bogus:Nice_talk', 0,
+                               new ForeignTitle( 0, '', 'Bogus:Nice_talk' ),
+                       ),
+                       array(
+                               'Bogus:Nice_talk', null,
+                               new ForeignTitle( 9000, 'Bogus', 'Nice_talk' ),
+                       ),
+                       array(
+                               'Bogus:Nice_talk', 4,
+                               new ForeignTitle( 4, 'Bogus', 'Nice_talk' ),
+                       ),
+                       array(
+                               'Bogus:Nice_talk', 1,
+                               new ForeignTitle( 1, 'Talk', 'Nice_talk' ),
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider basicProvider
+        */
+       public function testBasic( $title, $ns, ForeignTitle $foreignTitle ) {
+
+               $foreignNamespaces = array(
+                       0 => '', 1 => 'Talk', 100 => 'Portal', 9000 => 'Bogus'
+               );
+
+               $factory = new NamespaceAwareForeignTitleFactory( $foreignNamespaces );
+               $testTitle = $factory->createForeignTitle( $title, $ns );
+
+               $this->assertEquals( $testTitle->isNamespaceIdKnown(),
+                       $foreignTitle->isNamespaceIdKnown() );
+
+               if (
+                       $testTitle->isNamespaceIdKnown() &&
+                       $foreignTitle->isNamespaceIdKnown()
+               ) {
+                       $this->assertEquals( $testTitle->getNamespaceId(),
+                               $foreignTitle->getNamespaceId() );
+               }
+
+               $this->assertEquals( $testTitle->getNamespaceName(),
+                       $foreignTitle->getNamespaceName() );
+               $this->assertEquals( $testTitle->getText(), $foreignTitle->getText() );
+       }
+}
diff --git a/tests/phpunit/includes/title/NamespaceImportTitleFactoryTest.php b/tests/phpunit/includes/title/NamespaceImportTitleFactoryTest.php
new file mode 100644 (file)
index 0000000..f0ffdb3
--- /dev/null
@@ -0,0 +1,78 @@
+<?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
+ * @license GPL 2+
+ * @author This, that and the other
+ */
+
+/**
+ * @covers NamespaceImportTitleFactory
+ *
+ * @group Title
+ */
+class NamespaceImportTitleFactoryTest extends MediaWikiTestCase {
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       'wgLanguageCode' => 'en',
+                       'wgContLang' => Language::factory( 'en' ),
+               ) );
+       }
+
+       public function basicProvider() {
+               return array(
+                       array(
+                               new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+                               0,
+                               Title::newFromText( 'MainNamespaceArticle' )
+                       ),
+                       array(
+                               new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+                               2,
+                               Title::newFromText( 'User:MainNamespaceArticle' )
+                       ),
+                       array(
+                               new ForeignTitle( 1, 'Discussion', 'Nice_talk' ),
+                               0,
+                               Title::newFromText( 'Nice_talk' )
+                       ),
+                       array(
+                               new ForeignTitle( 0, '', 'Bogus:Nice_talk' ),
+                               0,
+                               Title::newFromText( 'Bogus:Nice_talk' )
+                       ),
+                       array(
+                               new ForeignTitle( 0, '', 'Bogus:Nice_talk' ),
+                               2,
+                               Title::newFromText( 'User:Bogus:Nice_talk' )
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider basicProvider
+        */
+       public function testBasic( ForeignTitle $foreignTitle, $ns, Title $title ) {
+               $factory = new NamespaceImportTitleFactory( $ns );
+               $testTitle = $factory->createTitleFromForeignTitle( $foreignTitle );
+
+               $this->assertTrue( $title->equals( $testTitle ) );
+       }
+}
diff --git a/tests/phpunit/includes/title/SubpageImportTitleFactoryTest.php b/tests/phpunit/includes/title/SubpageImportTitleFactoryTest.php
new file mode 100644 (file)
index 0000000..71c9c70
--- /dev/null
@@ -0,0 +1,87 @@
+<?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
+ * @license GPL 2+
+ * @author This, that and the other
+ */
+
+/**
+ * @covers SubpageImportTitleFactory
+ *
+ * @group Title
+ */
+class SubpageImportTitleFactoryTest extends MediaWikiTestCase {
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       'wgLanguageCode' => 'en',
+                       'wgContLang' => Language::factory( 'en' ),
+                       'wgNamespacesWithSubpages' => array( 0 => false, 2 => true ),
+               ) );
+       }
+
+       public function basicProvider() {
+               return array(
+                       array(
+                               new ForeignTitle( 0, '', 'MainNamespaceArticle' ),
+                               Title::newFromText( 'User:Graham' ),
+                               Title::newFromText( 'User:Graham/MainNamespaceArticle' )
+                       ),
+                       array(
+                               new ForeignTitle( 1, 'Discussion', 'Nice_talk' ),
+                               Title::newFromText( 'User:Graham' ),
+                               Title::newFromText( 'User:Graham/Discussion:Nice_talk' )
+                       ),
+                       array(
+                               new ForeignTitle( 0, '', 'Bogus:Nice_talk' ),
+                               Title::newFromText( 'User:Graham' ),
+                               Title::newFromText( 'User:Graham/Bogus:Nice_talk' )
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider basicProvider
+        */
+       public function testBasic( ForeignTitle $foreignTitle, Title $rootPage,
+               Title $title ) {
+
+               $factory = new SubpageImportTitleFactory( $rootPage );
+               $testTitle = $factory->createTitleFromForeignTitle( $foreignTitle );
+
+               $this->assertTrue( $testTitle->equals( $title ) );
+       }
+
+       public function failureProvider() {
+               return array(
+                       array(
+                               Title::newFromText( 'Graham' ),
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider failureProvider
+        */
+       public function testFailures( Title $rootPage ) {
+               $this->setExpectedException( 'MWException' );
+               new SubpageImportTitleFactory( $rootPage );
+       }
+}
diff --git a/tests/phpunit/languages/LanguageAmTest.php b/tests/phpunit/languages/LanguageAmTest.php
deleted file mode 100644 (file)
index a644f5e..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/LanguageAm.php */
-class LanguageAmTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageArTest.php b/tests/phpunit/languages/LanguageArTest.php
deleted file mode 100644 (file)
index 7b48f23..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-<?php
-/**
- * Based on LanguagMlTest
- * @file
- */
-
-/** Tests for MediaWiki languages/LanguageAr.php */
-class LanguageArTest extends LanguageClassesTestCase {
-       /**
-        * @covers Language::formatNum
-        * @todo split into a test and a dataprovider
-        */
-       public function testFormatNum() {
-               $this->assertEquals( '١٬٢٣٤٬٥٦٧', $this->getLang()->formatNum( '1234567' ) );
-               $this->assertEquals( '-١٢٫٨٩', $this->getLang()->formatNum( -12.89 ) );
-       }
-
-       /**
-        * Mostly to test the raw ascii feature.
-        * @dataProvider providerSprintfDate
-        * @covers Language::sprintfDate
-        */
-       public function testSprintfDate( $format, $date, $expected ) {
-               $this->assertEquals( $expected, $this->getLang()->sprintfDate( $format, $date ) );
-       }
-
-       public static function providerSprintfDate() {
-               return array(
-                       array(
-                               'xg "vs" g',
-                               '20120102030410',
-                               'يناير vs ٣'
-                       ),
-                       array(
-                               'xmY',
-                               '20120102030410',
-                               '١٤٣٣'
-                       ),
-                       array(
-                               'xnxmY',
-                               '20120102030410',
-                               '1433'
-                       ),
-                       array(
-                               'xN xmj xmn xN xmY',
-                               '20120102030410',
-                               ' 7 2  ١٤٣٣'
-                       ),
-               );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'zero', 'one', 'two', 'few', 'many', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'zero', 0 ),
-                       array( 'one', 1 ),
-                       array( 'two', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 9 ),
-                       array( 'few', 110 ),
-                       array( 'many', 11 ),
-                       array( 'many', 15 ),
-                       array( 'many', 99 ),
-                       array( 'many', 9999 ),
-                       array( 'other', 100 ),
-                       array( 'other', 102 ),
-                       array( 'other', 1000 ),
-                       array( 'other', 1.7 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageArqTest.php b/tests/phpunit/languages/LanguageArqTest.php
deleted file mode 100644 (file)
index 3fa56d7..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-/**
- * Based on LanguageMlTest
- * @author Joel Sahleen
- * @copyright Copyright © 2014, Joel Sahleen
- * @file
- */
-
-/** Tests for MediaWiki languages/LanguageArq.php */
-class LanguageArqTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider provideNumber
-        * @covers Language::formatNum
-        */
-       public function testFormatNum( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->formatNum( $value ) );
-       }
-
-       public static function provideNumber() {
-               return array(
-                       array( '1.234.567', '1234567'),
-                       array( '-12,89', -12.89 ),
-                       );
-       }
-
-}
diff --git a/tests/phpunit/languages/LanguageBeTest.php b/tests/phpunit/languages/LanguageBeTest.php
deleted file mode 100644 (file)
index 7bd586a..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/LanguageBe.php */
-class LanguageBeTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'many', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 1 ),
-                       array( 'many', 11 ),
-                       array( 'one', 91 ),
-                       array( 'one', 121 ),
-                       array( 'few', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 4 ),
-                       array( 'few', 334 ),
-                       array( 'many', 5 ),
-                       array( 'many', 15 ),
-                       array( 'many', 120 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageBe_taraskTest.php b/tests/phpunit/languages/LanguageBe_taraskTest.php
deleted file mode 100644 (file)
index 4dd5cdd..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-<?php
-
-// @codingStandardsIgnoreStart Ignore Squiz.Classes.ValidClassName.NotCamelCaps
-class LanguageBe_taraskTest extends LanguageClassesTestCase {
-       // @codingStandardsIgnoreEnd
-       /**
-        * Make sure the language code we are given is indeed
-        * be-tarask. This is to ensure LanguageClassesTestCase
-        * does not give us the wrong language.
-        */
-       public function testBeTaraskTestsUsesBeTaraskCode() {
-               $this->assertEquals( 'be-tarask',
-                       $this->getLang()->getCode()
-               );
-       }
-
-       /**
-        * @see bug 23156 & r64981
-        * @covers Language::commafy
-        */
-       public function testSearchRightSingleQuotationMarkAsApostroph() {
-               $this->assertEquals(
-                       "'",
-                       $this->getLang()->normalizeForSearch( '’' ),
-                       'bug 23156: U+2019 conversion to U+0027'
-               );
-       }
-
-       /**
-        * @see bug 23156 & r64981
-        * @covers Language::commafy
-        */
-       public function testCommafy() {
-               $this->assertEquals( '1,234,567', $this->getLang()->commafy( '1234567' ) );
-               $this->assertEquals( '12,345', $this->getLang()->commafy( '12345' ) );
-       }
-
-       /**
-        * @see bug 23156 & r64981
-        * @covers Language::commafy
-        */
-       public function testDoesNotCommafyFourDigitsNumber() {
-               $this->assertEquals( '1234', $this->getLang()->commafy( '1234' ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'many', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 1 ),
-                       array( 'many', 11 ),
-                       array( 'one', 91 ),
-                       array( 'one', 121 ),
-                       array( 'few', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 4 ),
-                       array( 'few', 334 ),
-                       array( 'many', 5 ),
-                       array( 'many', 15 ),
-                       array( 'many', 120 ),
-               );
-       }
-
-       /**
-        * @dataProvider providePluralTwoForms
-        * @covers Language::convertPlural
-        */
-       public function testPluralTwoForms( $result, $value ) {
-               $forms = array( '1=one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       public static function providePluralTwoForms() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 11 ),
-                       array( 'other', 91 ),
-                       array( 'other', 121 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageBhoTest.php b/tests/phpunit/languages/LanguageBhoTest.php
deleted file mode 100644 (file)
index 187bfbb..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/LanguageBho.php */
-class LanguageBhoTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageBsTest.php b/tests/phpunit/languages/LanguageBsTest.php
deleted file mode 100644 (file)
index 7aca2ab..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for Croatian (hrvatski) */
-class LanguageBsTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'few', 2 ),
-                       array( 'few', 4 ),
-                       array( 'other', 5 ),
-                       array( 'other', 11 ),
-                       array( 'other', 20 ),
-                       array( 'one', 21 ),
-                       array( 'few', 24 ),
-                       array( 'other', 25 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageConverterTest.php b/tests/phpunit/languages/LanguageConverterTest.php
new file mode 100644 (file)
index 0000000..d4ccca9
--- /dev/null
@@ -0,0 +1,187 @@
+<?php
+
+class LanguageConverterTest extends MediaWikiLangTestCase {
+       /** @var LanguageToTest */
+       protected $lang = null;
+       /** @var TestConverter */
+       protected $lc = null;
+
+       protected function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( array(
+                       'wgContLang' => Language::factory( 'tg' ),
+                       'wgLanguageCode' => 'tg',
+                       'wgDefaultLanguageVariant' => false,
+                       'wgMemc' => new EmptyBagOStuff,
+                       'wgRequest' => new FauxRequest( array() ),
+                       'wgUser' => new User,
+               ) );
+
+               $this->lang = new LanguageToTest();
+               $this->lc = new TestConverter(
+                       $this->lang, 'tg',
+                       array( 'tg', 'tg-latn' )
+               );
+       }
+
+       protected function tearDown() {
+               unset( $this->lc );
+               unset( $this->lang );
+
+               parent::tearDown();
+       }
+
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        */
+       public function testGetPreferredVariantDefaults() {
+               $this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
+       }
+
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getHeaderVariant
+        */
+       public function testGetPreferredVariantHeaders() {
+               global $wgRequest;
+               $wgRequest->setHeader( 'Accept-Language', 'tg-latn' );
+
+               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
+       }
+
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getHeaderVariant
+        */
+       public function testGetPreferredVariantHeaderWeight() {
+               global $wgRequest;
+               $wgRequest->setHeader( 'Accept-Language', 'tg;q=1' );
+
+               $this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
+       }
+
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getHeaderVariant
+        */
+       public function testGetPreferredVariantHeaderWeight2() {
+               global $wgRequest;
+               $wgRequest->setHeader( 'Accept-Language', 'tg-latn;q=1' );
+
+               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
+       }
+
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getHeaderVariant
+        */
+       public function testGetPreferredVariantHeaderMulti() {
+               global $wgRequest;
+               $wgRequest->setHeader( 'Accept-Language', 'en, tg-latn;q=1' );
+
+               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
+       }
+
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        */
+       public function testGetPreferredVariantUserOption() {
+               global $wgUser;
+
+               $wgUser = new User;
+               $wgUser->load(); // from 'defaults'
+               $wgUser->mId = 1;
+               $wgUser->mDataLoaded = true;
+               $wgUser->mOptionsLoaded = true;
+               $wgUser->setOption( 'variant', 'tg-latn' );
+
+               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
+       }
+
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getUserVariant
+        */
+       public function testGetPreferredVariantUserOptionForForeignLanguage() {
+               global $wgContLang, $wgUser;
+
+               $wgContLang = Language::factory( 'en' );
+               $wgUser = new User;
+               $wgUser->load(); // from 'defaults'
+               $wgUser->mId = 1;
+               $wgUser->mDataLoaded = true;
+               $wgUser->mOptionsLoaded = true;
+               $wgUser->setOption( 'variant-tg', 'tg-latn' );
+
+               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
+       }
+
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getUserVariant
+        * @covers LanguageConverter::getURLVariant
+        */
+       public function testGetPreferredVariantHeaderUserVsUrl() {
+               global $wgContLang, $wgRequest, $wgUser;
+
+               $wgContLang = Language::factory( 'tg-latn' );
+               $wgRequest->setVal( 'variant', 'tg' );
+               $wgUser = User::newFromId( "admin" );
+               $wgUser->setId( 1 );
+               $wgUser->mFrom = 'defaults';
+               $wgUser->mOptionsLoaded = true;
+               // The user's data is ignored because the variant is set in the URL.
+               $wgUser->setOption( 'variant', 'tg-latn' );
+               $this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
+       }
+
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        */
+       public function testGetPreferredVariantDefaultLanguageVariant() {
+               global $wgDefaultLanguageVariant;
+
+               $wgDefaultLanguageVariant = 'tg-latn';
+               $this->assertEquals( 'tg-latn', $this->lc->getPreferredVariant() );
+       }
+
+       /**
+        * @covers LanguageConverter::getPreferredVariant
+        * @covers LanguageConverter::getURLVariant
+        */
+       public function testGetPreferredVariantDefaultLanguageVsUrlVariant() {
+               global $wgDefaultLanguageVariant, $wgRequest, $wgContLang;
+
+               $wgContLang = Language::factory( 'tg-latn' );
+               $wgDefaultLanguageVariant = 'tg';
+               $wgRequest->setVal( 'variant', null );
+               $this->assertEquals( 'tg', $this->lc->getPreferredVariant() );
+       }
+}
+
+/**
+ * Test converter (from Tajiki to latin orthography)
+ */
+class TestConverter extends LanguageConverter {
+       private $table = array(
+               'б' => 'b',
+               'в' => 'v',
+               'г' => 'g',
+       );
+
+       function loadDefaultTables() {
+               $this->mTables = array(
+                       'tg-latn' => new ReplacementArray( $this->table ),
+                       'tg' => new ReplacementArray()
+               );
+       }
+}
+
+class LanguageToTest extends Language {
+       function __construct() {
+               parent::__construct();
+               $variants = array( 'tg', 'tg-latn' );
+               $this->mConverter = new TestConverter( $this, 'tg', $variants );
+       }
+}
diff --git a/tests/phpunit/languages/LanguageCsTest.php b/tests/phpunit/languages/LanguageCsTest.php
deleted file mode 100644 (file)
index da9e6b8..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/Languagecs.php */
-class LanguageCsTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'few', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 4 ),
-                       array( 'other', 5 ),
-                       array( 'other', 11 ),
-                       array( 'other', 20 ),
-                       array( 'other', 25 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageCuTest.php b/tests/phpunit/languages/LanguageCuTest.php
deleted file mode 100644 (file)
index 0719317..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/LanguageCu.php */
-class LanguageCuTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'two', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'two', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 4 ),
-                       array( 'other', 5 ),
-                       array( 'one', 11 ),
-                       array( 'other', 20 ),
-                       array( 'two', 22 ),
-                       array( 'few', 223 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageCyTest.php b/tests/phpunit/languages/LanguageCyTest.php
deleted file mode 100644 (file)
index eaf663a..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageCy.php */
-class LanguageCyTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'zero', 'one', 'two', 'few', 'many', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'zero', 0 ),
-                       array( 'one', 1 ),
-                       array( 'two', 2 ),
-                       array( 'few', 3 ),
-                       array( 'many', 6 ),
-                       array( 'other', 4 ),
-                       array( 'other', 5 ),
-                       array( 'other', 11 ),
-                       array( 'other', 20 ),
-                       array( 'other', 22 ),
-                       array( 'other', 223 ),
-                       array( 'other', 200.00 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageDsbTest.php b/tests/phpunit/languages/LanguageDsbTest.php
deleted file mode 100644 (file)
index 94c11bc..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageDsb.php */
-class LanguageDsbTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'two', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'one', 101 ),
-                       array( 'one', 90001 ),
-                       array( 'two', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 203 ),
-                       array( 'few', 4 ),
-                       array( 'other', 99 ),
-                       array( 'other', 555 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageFrTest.php b/tests/phpunit/languages/LanguageFrTest.php
deleted file mode 100644 (file)
index 46b6501..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageFr.php */
-class LanguageFrTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageGaTest.php b/tests/phpunit/languages/LanguageGaTest.php
deleted file mode 100644 (file)
index c009f56..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageGa.php */
-class LanguageGaTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'two', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'two', 2 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageGdTest.php b/tests/phpunit/languages/LanguageGdTest.php
deleted file mode 100644 (file)
index b89b4df..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012-2013, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageGd.php */
-class LanguageGdTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providerPlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'two', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       public static function providerPlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'two', 2 ),
-                       array( 'one', 11 ),
-                       array( 'two', 12 ),
-                       array( 'few', 3 ),
-                       array( 'few', 19 ),
-                       array( 'other', 200 ),
-               );
-       }
-
-       /**
-        * @dataProvider providerPluralExplicit
-        * @covers Language::convertPlural
-        */
-       public function testExplicitPlural( $result, $value ) {
-               $forms = array( 'one', 'two', 'few', 'other', '11=Form11', '12=Form12' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       public static function providerPluralExplicit() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'two', 2 ),
-                       array( 'Form11', 11 ),
-                       array( 'Form12', 12 ),
-                       array( 'few', 3 ),
-                       array( 'few', 19 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageGvTest.php b/tests/phpunit/languages/LanguageGvTest.php
deleted file mode 100644 (file)
index e6a0cf0..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-/**
- * Test for Manx (Gaelg) language
- *
- * @author Santhosh Thottingal
- * @copyright Copyright © 2013, Santhosh Thottingal
- * @file
- */
-
-class LanguageGvTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'two', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'few', 0 ),
-                       array( 'one', 1 ),
-                       array( 'two', 2 ),
-                       array( 'other', 3 ),
-                       array( 'few', 20 ),
-                       array( 'one', 21 ),
-                       array( 'two', 22 ),
-                       array( 'other', 23 ),
-                       array( 'other', 50 ),
-                       array( 'few', 60 ),
-                       array( 'few', 80 ),
-                       array( 'few', 100 )
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageHeTest.php b/tests/phpunit/languages/LanguageHeTest.php
deleted file mode 100644 (file)
index c382244..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageHe.php */
-class LanguageHeTest extends LanguageClassesTestCase {
-       /**
-        * The most common usage for the plural forms is two forms,
-        * for singular and plural. In this case, the second form
-        * is technically dual, but in practice it's used as plural.
-        * In some cases, usually with expressions of time, three forms
-        * are needed - singular, dual and plural.
-        * CLDR also specifies a fourth form for multiples of 10,
-        * which is very rare. It also has a mistake, because
-        * the number 10 itself is supposed to be just plural,
-        * so currently it's overridden in MediaWiki.
-        */
-
-       // @todo the below test*PluralForms test methods can be refactored
-       //  to use a single test method and data provider..
-
-       /**
-        * @dataProvider provideTwoPluralForms
-        * @covers Language::convertPlural
-        */
-       public function testTwoPluralForms( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider provideThreePluralForms
-        * @covers Language::convertPlural
-        */
-       public function testThreePluralForms( $result, $value ) {
-               $forms = array( 'one', 'two', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider provideFourPluralForms
-        * @covers Language::convertPlural
-        */
-       public function testFourPluralForms( $result, $value ) {
-               $forms = array( 'one', 'two', 'many', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider provideFourPluralForms
-        * @covers Language::convertPlural
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function provideTwoPluralForms() {
-               return array(
-                       array( 'other', 0 ), // Zero - plural
-                       array( 'one', 1 ), // Singular
-                       array( 'other', 2 ), // No third form provided, use it as plural
-                       array( 'other', 3 ), // Plural - other
-                       array( 'other', 10 ), // No fourth form provided, use it as plural
-                       array( 'other', 20 ), // No fourth form provided, use it as plural
-               );
-       }
-
-       public static function provideThreePluralForms() {
-               return array(
-                       array( 'other', 0 ), // Zero - plural
-                       array( 'one', 1 ), // Singular
-                       array( 'two', 2 ), // Dual
-                       array( 'other', 3 ), // Plural - other
-                       array( 'other', 10 ), // No fourth form provided, use it as plural
-                       array( 'other', 20 ), // No fourth form provided, use it as plural
-               );
-       }
-
-       public static function provideFourPluralForms() {
-               return array(
-                       array( 'other', 0 ), // Zero - plural
-                       array( 'one', 1 ), // Singular
-                       array( 'two', 2 ), // Dual
-                       array( 'other', 3 ), // Plural - other
-                       array( 'other', 10 ), // 10 is supposed to be plural (other), not "many"
-                       array( 'many', 20 ), // Fourth form provided - rare, but supported by CLDR
-               );
-       }
-
-       /**
-        * @dataProvider provideGrammar
-        * @covers Language::convertGrammar
-        */
-       public function testGrammar( $result, $word, $case ) {
-               $this->assertEquals( $result, $this->getLang()->convertGrammar( $word, $case ) );
-       }
-
-       // The comments in the beginning of the line help avoid RTL problems
-       // with text editors.
-       public static function provideGrammar() {
-               return array(
-                       array(
-                               /* result */'וויקיפדיה',
-                               /* word   */'ויקיפדיה',
-                               /* case   */'תחילית',
-                       ),
-                       array(
-                               /* result */'וולפגנג',
-                               /* word   */'וולפגנג',
-                               /* case   */'prefixed',
-                       ),
-                       array(
-                               /* result */'קובץ',
-                               /* word   */'הקובץ',
-                               /* case   */'תחילית',
-                       ),
-                       array(
-                               /* result */'־Wikipedia',
-                               /* word   */'Wikipedia',
-                               /* case   */'תחילית',
-                       ),
-                       array(
-                               /* result */'־1995',
-                               /* word   */'1995',
-                               /* case   */'תחילית',
-                       ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageHiTest.php b/tests/phpunit/languages/LanguageHiTest.php
deleted file mode 100644 (file)
index f6d2c9e..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/LanguageHi.php */
-class LanguageHiTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageHrTest.php b/tests/phpunit/languages/LanguageHrTest.php
deleted file mode 100644 (file)
index 644c525..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageHr.php */
-class LanguageHrTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'few', 2 ),
-                       array( 'few', 4 ),
-                       array( 'other', 5 ),
-                       array( 'other', 11 ),
-                       array( 'other', 20 ),
-                       array( 'one', 21 ),
-                       array( 'few', 24 ),
-                       array( 'other', 25 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageHsbTest.php b/tests/phpunit/languages/LanguageHsbTest.php
deleted file mode 100644 (file)
index f95a43b..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageHsb.php */
-class LanguageHsbTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'two', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'one', 101 ),
-                       array( 'one', 90001 ),
-                       array( 'two', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 203 ),
-                       array( 'few', 4 ),
-                       array( 'other', 99 ),
-                       array( 'other', 555 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageHuTest.php b/tests/phpunit/languages/LanguageHuTest.php
deleted file mode 100644 (file)
index ee9197d..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/LanguageHu.php */
-class LanguageHuTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageHyTest.php b/tests/phpunit/languages/LanguageHyTest.php
deleted file mode 100644 (file)
index 92e0ef9..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for Armenian (Հայերեն) */
-class LanguageHyTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageKshTest.php b/tests/phpunit/languages/LanguageKshTest.php
deleted file mode 100644 (file)
index 568a378..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageKsh.php */
-class LanguageKshTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other', 'zero' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'zero', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageLnTest.php b/tests/phpunit/languages/LanguageLnTest.php
deleted file mode 100644 (file)
index 10b3234..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageLn.php */
-class LanguageLnTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageLtTest.php b/tests/phpunit/languages/LanguageLtTest.php
deleted file mode 100644 (file)
index 30642f6..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/LanguageLt.php */
-class LanguageLtTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'few', 2 ),
-                       array( 'few', 9 ),
-                       array( 'other', 10 ),
-                       array( 'other', 11 ),
-                       array( 'other', 20 ),
-                       array( 'one', 21 ),
-                       array( 'few', 32 ),
-                       array( 'one', 41 ),
-                       array( 'one', 40001 ),
-               );
-       }
-
-       /**
-        * @dataProvider providePluralTwoForms
-        * @covers Language::convertPlural
-        */
-       public function testOneFewPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               // This fails for 21, but not sure why.
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       public static function providePluralTwoForms() {
-               return array(
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 15 ),
-                       array( 'other', 20 ),
-                       array( 'one', 21 ),
-                       array( 'other', 22 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageLvTest.php b/tests/phpunit/languages/LanguageLvTest.php
deleted file mode 100644 (file)
index 7120cfe..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for Latvian */
-class LanguageLvTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'zero', 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'zero', 0 ),
-                       array( 'one', 1 ),
-                       array( 'zero', 11 ),
-                       array( 'one', 21 ),
-                       array( 'zero', 411 ),
-                       array( 'other', 2 ),
-                       array( 'other', 9 ),
-                       array( 'zero', 12 ),
-                       array( 'other', 12.345 ),
-                       array( 'zero', 20 ),
-                       array( 'other', 22 ),
-                       array( 'one', 31 ),
-                       array( 'zero', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageMgTest.php b/tests/phpunit/languages/LanguageMgTest.php
deleted file mode 100644 (file)
index 65e8fd7..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageMg.php */
-class LanguageMgTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 200 ),
-                       array( 'other', 123.3434 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageMkTest.php b/tests/phpunit/languages/LanguageMkTest.php
deleted file mode 100644 (file)
index ed15526..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for македонски/Macedonian */
-class LanguageMkTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'one', 11 ),
-                       array( 'one', 21 ),
-                       array( 'one', 411 ),
-                       array( 'other', 12.345 ),
-                       array( 'other', 20 ),
-                       array( 'one', 31 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageMlTest.php b/tests/phpunit/languages/LanguageMlTest.php
deleted file mode 100644 (file)
index 4fa45ce..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2011, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/LanguageMl.php */
-class LanguageMlTest extends LanguageClassesTestCase {
-
-       /**
-        * @dataProvider providerFormatNum
-        * @see bug 29495
-        * @covers Language::formatNum
-        */
-       public function testFormatNum( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->formatNum( $value ) );
-       }
-
-       public static function providerFormatNum() {
-               return array(
-                       array( '12,34,567', '1234567' ),
-                       array( '12,345', '12345' ),
-                       array( '1', '1' ),
-                       array( '123', '123' ),
-                       array( '1,234', '1234' ),
-                       array( '12,345.56', '12345.56' ),
-                       array( '12,34,56,79,81,23,45,678', '12345679812345678' ),
-                       array( '.12345', '.12345' ),
-                       array( '-12,00,000', '-1200000' ),
-                       array( '-98', '-98' ),
-                       array( '-98', -98 ),
-                       array( '-1,23,45,678', -12345678 ),
-                       array( '', '' ),
-                       array( '', null ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageMoTest.php b/tests/phpunit/languages/LanguageMoTest.php
deleted file mode 100644 (file)
index e0e54ca..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageMo.php */
-class LanguageMoTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'few', 0 ),
-                       array( 'one', 1 ),
-                       array( 'few', 2 ),
-                       array( 'few', 19 ),
-                       array( 'other', 20 ),
-                       array( 'other', 99 ),
-                       array( 'other', 100 ),
-                       array( 'few', 101 ),
-                       array( 'few', 119 ),
-                       array( 'other', 120 ),
-                       array( 'other', 200 ),
-                       array( 'few', 201 ),
-                       array( 'few', 219 ),
-                       array( 'other', 220 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageMtTest.php b/tests/phpunit/languages/LanguageMtTest.php
deleted file mode 100644 (file)
index 96d2bc9..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageMt.php */
-class LanguageMtTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'many', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'few', 0 ),
-                       array( 'one', 1 ),
-                       array( 'few', 2 ),
-                       array( 'few', 10 ),
-                       array( 'many', 11 ),
-                       array( 'many', 19 ),
-                       array( 'other', 20 ),
-                       array( 'other', 99 ),
-                       array( 'other', 100 ),
-                       array( 'other', 101 ),
-                       array( 'few', 102 ),
-                       array( 'few', 110 ),
-                       array( 'many', 111 ),
-                       array( 'many', 119 ),
-                       array( 'other', 120 ),
-                       array( 'other', 201 ),
-               );
-       }
-
-       /**
-        * @dataProvider providePluralTwoForms
-        * @covers Language::convertPlural
-        */
-       public function testPluralTwoForms( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       public static function providePluralTwoForms() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 10 ),
-                       array( 'other', 11 ),
-                       array( 'other', 19 ),
-                       array( 'other', 20 ),
-                       array( 'other', 99 ),
-                       array( 'other', 100 ),
-                       array( 'other', 101 ),
-                       array( 'other', 102 ),
-                       array( 'other', 110 ),
-                       array( 'other', 111 ),
-                       array( 'other', 119 ),
-                       array( 'other', 120 ),
-                       array( 'other', 201 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageNlTest.php b/tests/phpunit/languages/LanguageNlTest.php
deleted file mode 100644 (file)
index 26bd691..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2011, Santhosh Thottingal
- * @file
- */
-
-/** Tests for MediaWiki languages/LanguageNl.php */
-class LanguageNlTest extends LanguageClassesTestCase {
-
-       /**
-        * @covers Language::formatNum
-        * @todo split into a test and a dataprovider
-        */
-       public function testFormatNum() {
-               $this->assertEquals( '1.234.567', $this->getLang()->formatNum( '1234567' ) );
-               $this->assertEquals( '12.345', $this->getLang()->formatNum( '12345' ) );
-               $this->assertEquals( '1', $this->getLang()->formatNum( '1' ) );
-               $this->assertEquals( '123', $this->getLang()->formatNum( '123' ) );
-               $this->assertEquals( '1.234', $this->getLang()->formatNum( '1234' ) );
-               $this->assertEquals( '12.345,56', $this->getLang()->formatNum( '12345.56' ) );
-               $this->assertEquals( ',1234556', $this->getLang()->formatNum( '.1234556' ) );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageNsoTest.php b/tests/phpunit/languages/LanguageNsoTest.php
deleted file mode 100644 (file)
index 18efd73..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageNso.php */
-class LanguageNsoTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguagePlTest.php b/tests/phpunit/languages/LanguagePlTest.php
deleted file mode 100644 (file)
index d180037..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguagePl.php */
-class LanguagePlTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'many' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'many', 0 ),
-                       array( 'one', 1 ),
-                       array( 'few', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 4 ),
-                       array( 'many', 5 ),
-                       array( 'many', 9 ),
-                       array( 'many', 10 ),
-                       array( 'many', 11 ),
-                       array( 'many', 21 ),
-                       array( 'few', 22 ),
-                       array( 'few', 23 ),
-                       array( 'few', 24 ),
-                       array( 'many', 25 ),
-                       array( 'many', 200 ),
-                       array( 'many', 201 ),
-               );
-       }
-
-       /**
-        * @dataProvider providePluralTwoForms
-        * @covers Language::convertPlural
-        */
-       public function testPluralTwoForms( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       public static function providePluralTwoForms() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 3 ),
-                       array( 'other', 4 ),
-                       array( 'other', 5 ),
-                       array( 'other', 9 ),
-                       array( 'other', 10 ),
-                       array( 'other', 11 ),
-                       array( 'other', 21 ),
-                       array( 'other', 22 ),
-                       array( 'other', 23 ),
-                       array( 'other', 24 ),
-                       array( 'other', 25 ),
-                       array( 'other', 200 ),
-                       array( 'other', 201 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageRoTest.php b/tests/phpunit/languages/LanguageRoTest.php
deleted file mode 100644 (file)
index ae7816b..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageRo.php */
-class LanguageRoTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'few', 0 ),
-                       array( 'one', 1 ),
-                       array( 'few', 2 ),
-                       array( 'few', 19 ),
-                       array( 'other', 20 ),
-                       array( 'other', 99 ),
-                       array( 'other', 100 ),
-                       array( 'few', 101 ),
-                       array( 'few', 119 ),
-                       array( 'other', 120 ),
-                       array( 'other', 200 ),
-                       array( 'few', 201 ),
-                       array( 'few', 219 ),
-                       array( 'other', 220 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageRuTest.php b/tests/phpunit/languages/LanguageRuTest.php
deleted file mode 100644 (file)
index 1381afb..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * based on LanguageBe_tarask.php
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageRu.php */
-class LanguageRuTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'many', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * Test explicit plural forms - n=FormN forms
-        * @covers Language::convertPlural
-        */
-       public function testExplicitPlural() {
-               $forms = array( 'one', 'few', 'many', 'other', '12=dozen' );
-               $this->assertEquals( 'dozen', $this->getLang()->convertPlural( 12, $forms ) );
-               $forms = array( 'one', 'few', 'many', '100=hundred', 'other', '12=dozen' );
-               $this->assertEquals( 'hundred', $this->getLang()->convertPlural( 100, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 1 ),
-                       array( 'many', 11 ),
-                       array( 'one', 91 ),
-                       array( 'one', 121 ),
-                       array( 'few', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 4 ),
-                       array( 'few', 334 ),
-                       array( 'many', 5 ),
-                       array( 'many', 15 ),
-                       array( 'many', 120 ),
-               );
-       }
-
-       /**
-        * @dataProvider providePluralTwoForms
-        * @covers Language::convertPlural
-        */
-       public function testPluralTwoForms( $result, $value ) {
-               $forms = array( '1=one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       public static function providePluralTwoForms() {
-               return array(
-                       array( 'one', 1 ),
-                       array( 'other', 11 ),
-                       array( 'other', 91 ),
-                       array( 'other', 121 ),
-               );
-       }
-
-       /**
-        * @dataProvider providerGrammar
-        * @covers Language::convertGrammar
-        */
-       public function testGrammar( $result, $word, $case ) {
-               $this->assertEquals( $result, $this->getLang()->convertGrammar( $word, $case ) );
-       }
-
-       public static function providerGrammar() {
-               return array(
-                       array(
-                               'Википедии',
-                               'Википедия',
-                               'genitive',
-                       ),
-                       array(
-                               'Викитеки',
-                               'Викитека',
-                               'genitive',
-                       ),
-                       array(
-                               'Викитеке',
-                               'Викитека',
-                               'prepositional',
-                       ),
-                       array(
-                               'Викисклада',
-                               'Викисклад',
-                               'genitive',
-                       ),
-                       array(
-                               'Викискладе',
-                               'Викисклад',
-                               'prepositional',
-                       ),
-                       array(
-                               'Викиданных',
-                               'Викиданные',
-                               'prepositional',
-                       ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageSeTest.php b/tests/phpunit/languages/LanguageSeTest.php
deleted file mode 100644 (file)
index 533aa2b..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageSe.php */
-class LanguageSeTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'two', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'two', 2 ),
-                       array( 'other', 3 ),
-               );
-       }
-
-       /**
-        * @dataProvider providePluralTwoForms
-        * @covers Language::convertPlural
-        */
-       public function testPluralTwoForms( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       public static function providePluralTwoForms() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 3 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageSgsTest.php b/tests/phpunit/languages/LanguageSgsTest.php
deleted file mode 100644 (file)
index fa49a4d..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for Samogitian */
-class LanguageSgsTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePluralAllForms
-        * @covers Language::convertPlural
-        */
-       public function testPluralAllForms( $result, $value ) {
-               $forms = array( 'one', 'two', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePluralAllForms
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePluralAllForms() {
-               return array(
-                       array( 'few', 0 ),
-                       array( 'one', 1 ),
-                       array( 'two', 2 ),
-                       array( 'other', 3 ),
-                       array( 'few', 10 ),
-                       array( 'few', 11 ),
-                       array( 'few', 12 ),
-                       array( 'few', 19 ),
-                       array( 'other', 20 ),
-                       array( 'few', 100 ),
-                       array( 'one', 101 ),
-                       array( 'few', 111 ),
-                       array( 'few', 112 ),
-               );
-       }
-
-       /**
-        * @dataProvider providePluralTwoForms
-        * @covers Language::convertPlural
-        */
-       public function testPluralTwoForms( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       public static function providePluralTwoForms() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 3 ),
-                       array( 'other', 10 ),
-                       array( 'other', 11 ),
-                       array( 'other', 12 ),
-                       array( 'other', 19 ),
-                       array( 'other', 20 ),
-                       array( 'other', 100 ),
-                       array( 'one', 101 ),
-                       array( 'other', 111 ),
-                       array( 'other', 112 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageShTest.php b/tests/phpunit/languages/LanguageShTest.php
deleted file mode 100644 (file)
index 1b39087..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for  srpskohrvatski / српскохрватски / Serbocroatian */
-class LanguageShTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'few', 2 ),
-                       array( 'few', 4 ),
-                       array( 'other', 5 ),
-                       array( 'other', 10 ),
-                       array( 'other', 11 ),
-                       array( 'other', 12 ),
-                       array( 'one', 101 ),
-                       array( 'few', 102 ),
-                       array( 'other', 111 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageSkTest.php b/tests/phpunit/languages/LanguageSkTest.php
deleted file mode 100644 (file)
index cb8a13b..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Amir E. Aharoni
- * based on LanguageSkTest.php
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageSk.php */
-class LanguageSkTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'few', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 4 ),
-                       array( 'other', 5 ),
-                       array( 'other', 11 ),
-                       array( 'other', 20 ),
-                       array( 'other', 25 ),
-                       array( 'other', 200 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageSlTest.php b/tests/phpunit/languages/LanguageSlTest.php
deleted file mode 100644 (file)
index 9783dd8..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-<?php
-/**
- * @author Santhosh Thottingal
- * @copyright Copyright © 2012, Amir E. Aharoni
- * based on LanguageSkTest.php
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageSl.php */
-class LanguageSlTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providerPlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'two', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providerPlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providerPlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'two', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 4 ),
-                       array( 'other', 5 ),
-                       array( 'other', 99 ),
-                       array( 'other', 100 ),
-                       array( 'one', 101 ),
-                       array( 'two', 102 ),
-                       array( 'few', 103 ),
-                       array( 'one', 201 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageSmaTest.php b/tests/phpunit/languages/LanguageSmaTest.php
deleted file mode 100644 (file)
index 95cb333..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageSma.php */
-class LanguageSmaTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'two', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'two', 2 ),
-                       array( 'other', 3 ),
-               );
-       }
-
-       /**
-        * @dataProvider providePluralTwoForms
-        * @covers Language::convertPlural
-        */
-       public function testPluralTwoForms( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       public static function providePluralTwoForms() {
-               return array(
-                       array( 'other', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-                       array( 'other', 3 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageSrTest.php b/tests/phpunit/languages/LanguageSrTest.php
deleted file mode 100644 (file)
index bfb199f..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-<?php
-/**
- * PHPUnit tests for the Serbian language.
- * The language can be represented using two scripts:
- *  - Latin (SR_el)
- *  - Cyrillic (SR_ec)
- * Both representations seems to be bijective, hence MediaWiki can convert
- * from one script to the other.
- *
- * @author Antoine Musso <hashar at free dot fr>
- * @copyright Copyright © 2011, Antoine Musso <hashar at free dot fr>
- * @file
- *
- * @todo methods in test class should be tidied:
- *  - Should be split into separate test methods and data providers
- *  - Tests for LanguageConverter and Language should probably be separate..
- */
-
-/** Tests for MediaWiki languages/LanguageSr.php */
-class LanguageSrTest extends LanguageClassesTestCase {
-       /**
-        * @covers LanguageConverter::convertTo
-        */
-       public function testEasyConversions() {
-               $this->assertCyrillic(
-                       'шђчћжШЂЧЋЖ',
-                       'Cyrillic guessing characters'
-               );
-               $this->assertLatin(
-                       'šđč枊ĐČĆŽ',
-                       'Latin guessing characters'
-               );
-       }
-
-       /**
-        * @covers LanguageConverter::convertTo
-        */
-       public function testMixedConversions() {
-               $this->assertCyrillic(
-                       'шђчћжШЂЧЋЖ - šđčćž',
-                       'Mostly cyrillic characters'
-               );
-               $this->assertLatin(
-                       'šđč枊ĐČĆŽ - шђчћж',
-                       'Mostly latin characters'
-               );
-       }
-
-       /**
-        * @covers LanguageConverter::convertTo
-        */
-       public function testSameAmountOfLatinAndCyrillicGetConverted() {
-               $this->assertConverted(
-                       '4 latin: šđčć | 4 cyrillic: шђчћ',
-                       'sr-ec'
-               );
-               $this->assertConverted(
-                       '4 latin: šđčć | 4 cyrillic: шђчћ',
-                       'sr-el'
-               );
-       }
-
-       /**
-        * @author Nikola Smolenski
-        * @covers LanguageConverter::convertTo
-        */
-       public function testConversionToCyrillic() {
-               //A simple convertion of Latin to Cyrillic
-               $this->assertEquals( 'абвг',
-                       $this->convertToCyrillic( 'abvg' )
-               );
-               //Same as above, but assert that -{}-s must be removed and not converted
-               $this->assertEquals( 'ljабnjвгdž',
-                       $this->convertToCyrillic( '-{lj}-ab-{nj}-vg-{dž}-' )
-               );
-               //A simple convertion of Cyrillic to Cyrillic
-               $this->assertEquals( 'абвг',
-                       $this->convertToCyrillic( 'абвг' )
-               );
-               //Same as above, but assert that -{}-s must be removed and not converted
-               $this->assertEquals( 'ljабnjвгdž',
-                       $this->convertToCyrillic( '-{lj}-аб-{nj}-вг-{dž}-' )
-               );
-               //This text has some Latin, but is recognized as Cyrillic, so it should not be converted
-               $this->assertEquals( 'abvgшђжчћ',
-                       $this->convertToCyrillic( 'abvgшђжчћ' )
-               );
-               //Same as above, but assert that -{}-s must be removed
-               $this->assertEquals( 'љabvgњшђжчћџ',
-                       $this->convertToCyrillic( '-{љ}-abvg-{њ}-шђжчћ-{џ}-' )
-               );
-               //This text has some Cyrillic, but is recognized as Latin, so it should be converted
-               $this->assertEquals( 'абвгшђжчћ',
-                       $this->convertToCyrillic( 'абвгšđžčć' )
-               );
-               //Same as above, but assert that -{}-s must be removed and not converted
-               $this->assertEquals( 'ljабвгnjшђжчћdž',
-                       $this->convertToCyrillic( '-{lj}-абвг-{nj}-šđžčć-{dž}-' )
-               );
-               // Roman numerals are not converted
-               $this->assertEquals( 'а I б II в III г IV шђжчћ',
-                       $this->convertToCyrillic( 'a I b II v III g IV šđžčć' )
-               );
-       }
-
-       /**
-        * @covers LanguageConverter::convertTo
-        */
-       public function testConversionToLatin() {
-               //A simple convertion of Latin to Latin
-               $this->assertEquals( 'abcd',
-                       $this->convertToLatin( 'abcd' )
-               );
-               //A simple convertion of Cyrillic to Latin
-               $this->assertEquals( 'abcd',
-                       $this->convertToLatin( 'абцд' )
-               );
-               //This text has some Latin, but is recognized as Cyrillic, so it should be converted
-               $this->assertEquals( 'abcdšđžčć',
-                       $this->convertToLatin( 'abcdшђжчћ' )
-               );
-               //This text has some Cyrillic, but is recognized as Latin, so it should not be converted
-               $this->assertEquals( 'абцдšđžčć',
-                       $this->convertToLatin( 'абцдšđžčć' )
-               );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 1 ),
-                       array( 'other', 11 ),
-                       array( 'one', 91 ),
-                       array( 'one', 121 ),
-                       array( 'few', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 4 ),
-                       array( 'few', 334 ),
-                       array( 'other', 5 ),
-                       array( 'other', 15 ),
-                       array( 'other', 120 ),
-               );
-       }
-
-       /**
-        * @dataProvider providePluralTwoForms
-        * @covers Language::convertPlural
-        */
-       public function testPluralTwoForms( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       public static function providePluralTwoForms() {
-               return array(
-                       array( 'one', 1 ),
-                       array( 'other', 11 ),
-                       array( 'other', 4 ),
-                       array( 'one', 91 ),
-                       array( 'one', 121 ),
-               );
-       }
-
-       ##### HELPERS #####################################################
-       /**
-        *Wrapper to verify text stay the same after applying conversion
-        * @param string $text Text to convert
-        * @param string $variant Language variant 'sr-ec' or 'sr-el'
-        * @param string $msg Optional message
-        */
-       protected function assertUnConverted( $text, $variant, $msg = '' ) {
-               $this->assertEquals(
-                       $text,
-                       $this->convertTo( $text, $variant ),
-                       $msg
-               );
-       }
-
-       /**
-        * Wrapper to verify a text is different once converted to a variant.
-        * @param string $text Text to convert
-        * @param string $variant Language variant 'sr-ec' or 'sr-el'
-        * @param string $msg Optional message
-        */
-       protected function assertConverted( $text, $variant, $msg = '' ) {
-               $this->assertNotEquals(
-                       $text,
-                       $this->convertTo( $text, $variant ),
-                       $msg
-               );
-       }
-
-       /**
-        * Verifiy the given Cyrillic text is not converted when using
-        * using the cyrillic variant and converted to Latin when using
-        * the Latin variant.
-        * @param string $text Text to convert
-        * @param string $msg Optional message
-        */
-       protected function assertCyrillic( $text, $msg = '' ) {
-               $this->assertUnConverted( $text, 'sr-ec', $msg );
-               $this->assertConverted( $text, 'sr-el', $msg );
-       }
-
-       /**
-        * Verifiy the given Latin text is not converted when using
-        * using the Latin variant and converted to Cyrillic when using
-        * the Cyrillic variant.
-        * @param string $text Text to convert
-        * @param string $msg Optional message
-        */
-       protected function assertLatin( $text, $msg = '' ) {
-               $this->assertUnConverted( $text, 'sr-el', $msg );
-               $this->assertConverted( $text, 'sr-ec', $msg );
-       }
-
-       /** Wrapper for converter::convertTo() method*/
-       protected function convertTo( $text, $variant ) {
-               return $this->getLang()
-                       ->mConverter
-                       ->convertTo(
-                               $text, $variant
-                       );
-       }
-
-       protected function convertToCyrillic( $text ) {
-               return $this->convertTo( $text, 'sr-ec' );
-       }
-
-       protected function convertToLatin( $text ) {
-               return $this->convertTo( $text, 'sr-el' );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageTiTest.php b/tests/phpunit/languages/LanguageTiTest.php
deleted file mode 100644 (file)
index e225af9..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageTi.php */
-class LanguageTiTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageTlTest.php b/tests/phpunit/languages/LanguageTlTest.php
deleted file mode 100644 (file)
index 20f5bd7..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageTl.php */
-class LanguageTlTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 0 ),
-                       array( 'one', 1 ),
-                       array( 'one', 2 ),
-                       array( 'other', 4 ),
-                       array( 'other', 6 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageTrTest.php b/tests/phpunit/languages/LanguageTrTest.php
deleted file mode 100644 (file)
index 2c9905f..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-/**
- * @author Antoine Musso
- * @copyright Copyright © 2011, Antoine Musso
- * @file
- */
-
-/** Tests for MediaWiki languages/LanguageTr.php */
-class LanguageTrTest extends LanguageClassesTestCase {
-
-       /**
-        * See @bug 28040
-        * Credits to irc://irc.freenode.net/wikipedia-tr users:
-        *  - berm
-        *  - []LuCkY[]
-        *  - Emperyan
-        * @see http://en.wikipedia.org/wiki/Dotted_and_dotless_I
-        * @dataProvider provideDottedAndDotlessI
-        * @covers Language::ucfirst
-        * @covers Language::lcfirst
-        */
-       public function testDottedAndDotlessI( $func, $input, $inputCase, $expected ) {
-               if ( $func == 'ucfirst' ) {
-                       $res = $this->getLang()->ucfirst( $input );
-               } elseif ( $func == 'lcfirst' ) {
-                       $res = $this->getLang()->lcfirst( $input );
-               } else {
-                       throw new MWException( __METHOD__ . " given an invalid function name '$func'" );
-               }
-
-               $msg = "Converting $inputCase case '$input' with $func should give '$expected'";
-
-               $this->assertEquals( $expected, $res, $msg );
-       }
-
-       public static function provideDottedAndDotlessI() {
-               return array(
-                       # function, input, input case, expected
-                       # Case changed:
-                       array( 'ucfirst', 'ı', 'lower', 'I' ),
-                       array( 'ucfirst', 'i', 'lower', 'İ' ),
-                       array( 'lcfirst', 'I', 'upper', 'ı' ),
-                       array( 'lcfirst', 'İ', 'upper', 'i' ),
-
-                       # Already using the correct case
-                       array( 'ucfirst', 'I', 'upper', 'I' ),
-                       array( 'ucfirst', 'İ', 'upper', 'İ' ),
-                       array( 'lcfirst', 'ı', 'lower', 'ı' ),
-                       array( 'lcfirst', 'i', 'lower', 'i' ),
-
-                       # A real example taken from bug 28040 using
-                       # http://tr.wikipedia.org/wiki/%C4%B0Phone
-                       array( 'lcfirst', 'iPhone', 'lower', 'iPhone' ),
-
-                       # next case is valid in Turkish but are different words if we
-                       # consider IPhone is English!
-                       array( 'lcfirst', 'IPhone', 'upper', 'ıPhone' ),
-
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageUkTest.php b/tests/phpunit/languages/LanguageUkTest.php
deleted file mode 100644 (file)
index 9051bcf..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * based on LanguageBe_tarask.php
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for Ukrainian */
-class LanguageUkTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'few', 'many', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * Test explicit plural forms - n=FormN forms
-        * @covers Language::convertPlural
-        */
-       public function testExplicitPlural() {
-               $forms = array( 'one', 'few', 'many', 'other', '12=dozen' );
-               $this->assertEquals( 'dozen', $this->getLang()->convertPlural( 12, $forms ) );
-               $forms = array( 'one', 'few', 'many', '100=hundred', 'other', '12=dozen' );
-               $this->assertEquals( 'hundred', $this->getLang()->convertPlural( 100, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 1 ),
-                       array( 'many', 11 ),
-                       array( 'one', 91 ),
-                       array( 'one', 121 ),
-                       array( 'few', 2 ),
-                       array( 'few', 3 ),
-                       array( 'few', 4 ),
-                       array( 'few', 334 ),
-                       array( 'many', 5 ),
-                       array( 'many', 15 ),
-                       array( 'many', 120 ),
-               );
-       }
-
-       /**
-        * @dataProvider providePluralTwoForms
-        * @covers Language::convertPlural
-        */
-       public function testPluralTwoForms( $result, $value ) {
-               $forms = array( '1=one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       public static function providePluralTwoForms() {
-               return array(
-                       array( 'one', 1 ),
-                       array( 'other', 11 ),
-                       array( 'other', 91 ),
-                       array( 'other', 121 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageUzTest.php b/tests/phpunit/languages/LanguageUzTest.php
deleted file mode 100644 (file)
index 4881103..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-<?php
-/**
- * PHPUnit tests for the Uzbek language.
- * The language can be represented using two scripts:
- *  - Latin (uz-latn)
- *  - Cyrillic (uz-cyrl)
- *
- * @author Robin Pepermans
- * @author Antoine Musso <hashar at free dot fr>
- * @copyright Copyright © 2012, Robin Pepermans
- * @copyright Copyright © 2011, Antoine Musso <hashar at free dot fr>
- * @file
- *
- * @todo methods in test class should be tidied:
- *  - Should be split into separate test methods and data providers
- *  - Tests for LanguageConverter and Language should probably be separate..
- */
-
-/** Tests for MediaWiki languages/LanguageUz.php */
-class LanguageUzTest extends LanguageClassesTestCase {
-
-       /**
-        * @author Nikola Smolenski
-        * @covers LanguageConverter::convertTo
-        */
-       public function testConversionToCyrillic() {
-               // A convertion of Latin to Cyrillic
-               $this->assertEquals( 'абвгғ',
-                       $this->convertToCyrillic( 'abvggʻ' )
-               );
-               // Same as above, but assert that -{}-s must be removed and not converted
-               $this->assertEquals( 'ljабnjвгўоdb',
-                       $this->convertToCyrillic( '-{lj}-ab-{nj}-vgoʻo-{db}-' )
-               );
-               // A simple convertion of Cyrillic to Cyrillic
-               $this->assertEquals( 'абвг',
-                       $this->convertToCyrillic( 'абвг' )
-               );
-               // Same as above, but assert that -{}-s must be removed and not converted
-               $this->assertEquals( 'ljабnjвгdaž',
-                       $this->convertToCyrillic( '-{lj}-аб-{nj}-вг-{da}-ž' )
-               );
-       }
-
-       /**
-        * @covers LanguageConverter::convertTo
-        */
-       public function testConversionToLatin() {
-               // A simple convertion of Latin to Latin
-               $this->assertEquals( 'abdef',
-                       $this->convertToLatin( 'abdef' )
-               );
-               // A convertion of Cyrillic to Latin
-               $this->assertEquals( 'gʻabtsdOʻQyo',
-                       $this->convertToLatin( 'ғабцдЎҚё' )
-               );
-       }
-
-       ##### HELPERS #####################################################
-       /**
-        * Wrapper to verify text stay the same after applying conversion
-        * @param string $text Text to convert
-        * @param string $variant Language variant 'uz-cyrl' or 'uz-latn'
-        * @param string $msg Optional message
-        */
-       protected function assertUnConverted( $text, $variant, $msg = '' ) {
-               $this->assertEquals(
-                       $text,
-                       $this->convertTo( $text, $variant ),
-                       $msg
-               );
-       }
-
-       /**
-        * Wrapper to verify a text is different once converted to a variant.
-        * @param string $text Text to convert
-        * @param string $variant Language variant 'uz-cyrl' or 'uz-latn'
-        * @param string $msg Optional message
-        */
-       protected function assertConverted( $text, $variant, $msg = '' ) {
-               $this->assertNotEquals(
-                       $text,
-                       $this->convertTo( $text, $variant ),
-                       $msg
-               );
-       }
-
-       /**
-        * Verifiy the given Cyrillic text is not converted when using
-        * using the cyrillic variant and converted to Latin when using
-        * the Latin variant.
-        * @param string $text Text to convert
-        * @param string $msg Optional message
-        */
-       protected function assertCyrillic( $text, $msg = '' ) {
-               $this->assertUnConverted( $text, 'uz-cyrl', $msg );
-               $this->assertConverted( $text, 'uz-latn', $msg );
-       }
-
-       /**
-        * Verifiy the given Latin text is not converted when using
-        * using the Latin variant and converted to Cyrillic when using
-        * the Cyrillic variant.
-        * @param string $text Text to convert
-        * @param string $msg Optional message
-        */
-       protected function assertLatin( $text, $msg = '' ) {
-               $this->assertUnConverted( $text, 'uz-latn', $msg );
-               $this->assertConverted( $text, 'uz-cyrl', $msg );
-       }
-
-       /** Wrapper for converter::convertTo() method*/
-       protected function convertTo( $text, $variant ) {
-               return $this->getLang()->mConverter->convertTo( $text, $variant );
-       }
-
-       protected function convertToCyrillic( $text ) {
-               return $this->convertTo( $text, 'uz-cyrl' );
-       }
-
-       protected function convertToLatin( $text ) {
-               return $this->convertTo( $text, 'uz-latn' );
-       }
-}
diff --git a/tests/phpunit/languages/LanguageWaTest.php b/tests/phpunit/languages/LanguageWaTest.php
deleted file mode 100644 (file)
index d05196c..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-<?php
-/**
- * @author Amir E. Aharoni
- * @copyright Copyright © 2012, Amir E. Aharoni
- * @file
- */
-
-/** Tests for MediaWiki languages/classes/LanguageWa.php */
-class LanguageWaTest extends LanguageClassesTestCase {
-       /**
-        * @dataProvider providePlural
-        * @covers Language::convertPlural
-        */
-       public function testPlural( $result, $value ) {
-               $forms = array( 'one', 'other' );
-               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
-       }
-
-       /**
-        * @dataProvider providePlural
-        * @covers Language::getPluralRuleType
-        */
-       public function testGetPluralRuleType( $result, $value ) {
-               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
-       }
-
-       public static function providePlural() {
-               return array(
-                       array( 'one', 0 ),
-                       array( 'one', 1 ),
-                       array( 'other', 2 ),
-               );
-       }
-}
diff --git a/tests/phpunit/languages/classes/LanguageAmTest.php b/tests/phpunit/languages/classes/LanguageAmTest.php
new file mode 100644 (file)
index 0000000..a644f5e
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageAm.php */
+class LanguageAmTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageArTest.php b/tests/phpunit/languages/classes/LanguageArTest.php
new file mode 100644 (file)
index 0000000..7b48f23
--- /dev/null
@@ -0,0 +1,87 @@
+<?php
+/**
+ * Based on LanguagMlTest
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageAr.php */
+class LanguageArTest extends LanguageClassesTestCase {
+       /**
+        * @covers Language::formatNum
+        * @todo split into a test and a dataprovider
+        */
+       public function testFormatNum() {
+               $this->assertEquals( '١٬٢٣٤٬٥٦٧', $this->getLang()->formatNum( '1234567' ) );
+               $this->assertEquals( '-١٢٫٨٩', $this->getLang()->formatNum( -12.89 ) );
+       }
+
+       /**
+        * Mostly to test the raw ascii feature.
+        * @dataProvider providerSprintfDate
+        * @covers Language::sprintfDate
+        */
+       public function testSprintfDate( $format, $date, $expected ) {
+               $this->assertEquals( $expected, $this->getLang()->sprintfDate( $format, $date ) );
+       }
+
+       public static function providerSprintfDate() {
+               return array(
+                       array(
+                               'xg "vs" g',
+                               '20120102030410',
+                               'يناير vs ٣'
+                       ),
+                       array(
+                               'xmY',
+                               '20120102030410',
+                               '١٤٣٣'
+                       ),
+                       array(
+                               'xnxmY',
+                               '20120102030410',
+                               '1433'
+                       ),
+                       array(
+                               'xN xmj xmn xN xmY',
+                               '20120102030410',
+                               ' 7 2  ١٤٣٣'
+                       ),
+               );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'zero', 'one', 'two', 'few', 'many', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'zero', 0 ),
+                       array( 'one', 1 ),
+                       array( 'two', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 9 ),
+                       array( 'few', 110 ),
+                       array( 'many', 11 ),
+                       array( 'many', 15 ),
+                       array( 'many', 99 ),
+                       array( 'many', 9999 ),
+                       array( 'other', 100 ),
+                       array( 'other', 102 ),
+                       array( 'other', 1000 ),
+                       array( 'other', 1.7 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageArqTest.php b/tests/phpunit/languages/classes/LanguageArqTest.php
new file mode 100644 (file)
index 0000000..3fa56d7
--- /dev/null
@@ -0,0 +1,26 @@
+<?php
+/**
+ * Based on LanguageMlTest
+ * @author Joel Sahleen
+ * @copyright Copyright © 2014, Joel Sahleen
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageArq.php */
+class LanguageArqTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider provideNumber
+        * @covers Language::formatNum
+        */
+       public function testFormatNum( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->formatNum( $value ) );
+       }
+
+       public static function provideNumber() {
+               return array(
+                       array( '1.234.567', '1234567'),
+                       array( '-12,89', -12.89 ),
+                       );
+       }
+
+}
diff --git a/tests/phpunit/languages/classes/LanguageBeTest.php b/tests/phpunit/languages/classes/LanguageBeTest.php
new file mode 100644 (file)
index 0000000..7bd586a
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageBe.php */
+class LanguageBeTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'many', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 1 ),
+                       array( 'many', 11 ),
+                       array( 'one', 91 ),
+                       array( 'one', 121 ),
+                       array( 'few', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 4 ),
+                       array( 'few', 334 ),
+                       array( 'many', 5 ),
+                       array( 'many', 15 ),
+                       array( 'many', 120 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageBe_taraskTest.php b/tests/phpunit/languages/classes/LanguageBe_taraskTest.php
new file mode 100644 (file)
index 0000000..4dd5cdd
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+
+// @codingStandardsIgnoreStart Ignore Squiz.Classes.ValidClassName.NotCamelCaps
+class LanguageBe_taraskTest extends LanguageClassesTestCase {
+       // @codingStandardsIgnoreEnd
+       /**
+        * Make sure the language code we are given is indeed
+        * be-tarask. This is to ensure LanguageClassesTestCase
+        * does not give us the wrong language.
+        */
+       public function testBeTaraskTestsUsesBeTaraskCode() {
+               $this->assertEquals( 'be-tarask',
+                       $this->getLang()->getCode()
+               );
+       }
+
+       /**
+        * @see bug 23156 & r64981
+        * @covers Language::commafy
+        */
+       public function testSearchRightSingleQuotationMarkAsApostroph() {
+               $this->assertEquals(
+                       "'",
+                       $this->getLang()->normalizeForSearch( '’' ),
+                       'bug 23156: U+2019 conversion to U+0027'
+               );
+       }
+
+       /**
+        * @see bug 23156 & r64981
+        * @covers Language::commafy
+        */
+       public function testCommafy() {
+               $this->assertEquals( '1,234,567', $this->getLang()->commafy( '1234567' ) );
+               $this->assertEquals( '12,345', $this->getLang()->commafy( '12345' ) );
+       }
+
+       /**
+        * @see bug 23156 & r64981
+        * @covers Language::commafy
+        */
+       public function testDoesNotCommafyFourDigitsNumber() {
+               $this->assertEquals( '1234', $this->getLang()->commafy( '1234' ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'many', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 1 ),
+                       array( 'many', 11 ),
+                       array( 'one', 91 ),
+                       array( 'one', 121 ),
+                       array( 'few', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 4 ),
+                       array( 'few', 334 ),
+                       array( 'many', 5 ),
+                       array( 'many', 15 ),
+                       array( 'many', 120 ),
+               );
+       }
+
+       /**
+        * @dataProvider providePluralTwoForms
+        * @covers Language::convertPlural
+        */
+       public function testPluralTwoForms( $result, $value ) {
+               $forms = array( '1=one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       public static function providePluralTwoForms() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 11 ),
+                       array( 'other', 91 ),
+                       array( 'other', 121 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageBhoTest.php b/tests/phpunit/languages/classes/LanguageBhoTest.php
new file mode 100644 (file)
index 0000000..187bfbb
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageBho.php */
+class LanguageBhoTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageBsTest.php b/tests/phpunit/languages/classes/LanguageBsTest.php
new file mode 100644 (file)
index 0000000..7aca2ab
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for Croatian (hrvatski) */
+class LanguageBsTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'few', 2 ),
+                       array( 'few', 4 ),
+                       array( 'other', 5 ),
+                       array( 'other', 11 ),
+                       array( 'other', 20 ),
+                       array( 'one', 21 ),
+                       array( 'few', 24 ),
+                       array( 'other', 25 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageCsTest.php b/tests/phpunit/languages/classes/LanguageCsTest.php
new file mode 100644 (file)
index 0000000..da9e6b8
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/Languagecs.php */
+class LanguageCsTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'few', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 4 ),
+                       array( 'other', 5 ),
+                       array( 'other', 11 ),
+                       array( 'other', 20 ),
+                       array( 'other', 25 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageCuTest.php b/tests/phpunit/languages/classes/LanguageCuTest.php
new file mode 100644 (file)
index 0000000..0719317
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageCu.php */
+class LanguageCuTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'two', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'two', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 4 ),
+                       array( 'other', 5 ),
+                       array( 'one', 11 ),
+                       array( 'other', 20 ),
+                       array( 'two', 22 ),
+                       array( 'few', 223 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageCyTest.php b/tests/phpunit/languages/classes/LanguageCyTest.php
new file mode 100644 (file)
index 0000000..eaf663a
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageCy.php */
+class LanguageCyTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'zero', 'one', 'two', 'few', 'many', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'zero', 0 ),
+                       array( 'one', 1 ),
+                       array( 'two', 2 ),
+                       array( 'few', 3 ),
+                       array( 'many', 6 ),
+                       array( 'other', 4 ),
+                       array( 'other', 5 ),
+                       array( 'other', 11 ),
+                       array( 'other', 20 ),
+                       array( 'other', 22 ),
+                       array( 'other', 223 ),
+                       array( 'other', 200.00 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageDsbTest.php b/tests/phpunit/languages/classes/LanguageDsbTest.php
new file mode 100644 (file)
index 0000000..94c11bc
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageDsb.php */
+class LanguageDsbTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'two', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'one', 101 ),
+                       array( 'one', 90001 ),
+                       array( 'two', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 203 ),
+                       array( 'few', 4 ),
+                       array( 'other', 99 ),
+                       array( 'other', 555 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageFrTest.php b/tests/phpunit/languages/classes/LanguageFrTest.php
new file mode 100644 (file)
index 0000000..46b6501
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageFr.php */
+class LanguageFrTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageGaTest.php b/tests/phpunit/languages/classes/LanguageGaTest.php
new file mode 100644 (file)
index 0000000..c009f56
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageGa.php */
+class LanguageGaTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'two', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'two', 2 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageGdTest.php b/tests/phpunit/languages/classes/LanguageGdTest.php
new file mode 100644 (file)
index 0000000..b89b4df
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012-2013, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageGd.php */
+class LanguageGdTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providerPlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'two', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       public static function providerPlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'two', 2 ),
+                       array( 'one', 11 ),
+                       array( 'two', 12 ),
+                       array( 'few', 3 ),
+                       array( 'few', 19 ),
+                       array( 'other', 200 ),
+               );
+       }
+
+       /**
+        * @dataProvider providerPluralExplicit
+        * @covers Language::convertPlural
+        */
+       public function testExplicitPlural( $result, $value ) {
+               $forms = array( 'one', 'two', 'few', 'other', '11=Form11', '12=Form12' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       public static function providerPluralExplicit() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'two', 2 ),
+                       array( 'Form11', 11 ),
+                       array( 'Form12', 12 ),
+                       array( 'few', 3 ),
+                       array( 'few', 19 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageGvTest.php b/tests/phpunit/languages/classes/LanguageGvTest.php
new file mode 100644 (file)
index 0000000..e6a0cf0
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * Test for Manx (Gaelg) language
+ *
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2013, Santhosh Thottingal
+ * @file
+ */
+
+class LanguageGvTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'two', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'few', 0 ),
+                       array( 'one', 1 ),
+                       array( 'two', 2 ),
+                       array( 'other', 3 ),
+                       array( 'few', 20 ),
+                       array( 'one', 21 ),
+                       array( 'two', 22 ),
+                       array( 'other', 23 ),
+                       array( 'other', 50 ),
+                       array( 'few', 60 ),
+                       array( 'few', 80 ),
+                       array( 'few', 100 )
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageHeTest.php b/tests/phpunit/languages/classes/LanguageHeTest.php
new file mode 100644 (file)
index 0000000..c382244
--- /dev/null
@@ -0,0 +1,132 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageHe.php */
+class LanguageHeTest extends LanguageClassesTestCase {
+       /**
+        * The most common usage for the plural forms is two forms,
+        * for singular and plural. In this case, the second form
+        * is technically dual, but in practice it's used as plural.
+        * In some cases, usually with expressions of time, three forms
+        * are needed - singular, dual and plural.
+        * CLDR also specifies a fourth form for multiples of 10,
+        * which is very rare. It also has a mistake, because
+        * the number 10 itself is supposed to be just plural,
+        * so currently it's overridden in MediaWiki.
+        */
+
+       // @todo the below test*PluralForms test methods can be refactored
+       //  to use a single test method and data provider..
+
+       /**
+        * @dataProvider provideTwoPluralForms
+        * @covers Language::convertPlural
+        */
+       public function testTwoPluralForms( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider provideThreePluralForms
+        * @covers Language::convertPlural
+        */
+       public function testThreePluralForms( $result, $value ) {
+               $forms = array( 'one', 'two', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider provideFourPluralForms
+        * @covers Language::convertPlural
+        */
+       public function testFourPluralForms( $result, $value ) {
+               $forms = array( 'one', 'two', 'many', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider provideFourPluralForms
+        * @covers Language::convertPlural
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function provideTwoPluralForms() {
+               return array(
+                       array( 'other', 0 ), // Zero - plural
+                       array( 'one', 1 ), // Singular
+                       array( 'other', 2 ), // No third form provided, use it as plural
+                       array( 'other', 3 ), // Plural - other
+                       array( 'other', 10 ), // No fourth form provided, use it as plural
+                       array( 'other', 20 ), // No fourth form provided, use it as plural
+               );
+       }
+
+       public static function provideThreePluralForms() {
+               return array(
+                       array( 'other', 0 ), // Zero - plural
+                       array( 'one', 1 ), // Singular
+                       array( 'two', 2 ), // Dual
+                       array( 'other', 3 ), // Plural - other
+                       array( 'other', 10 ), // No fourth form provided, use it as plural
+                       array( 'other', 20 ), // No fourth form provided, use it as plural
+               );
+       }
+
+       public static function provideFourPluralForms() {
+               return array(
+                       array( 'other', 0 ), // Zero - plural
+                       array( 'one', 1 ), // Singular
+                       array( 'two', 2 ), // Dual
+                       array( 'other', 3 ), // Plural - other
+                       array( 'other', 10 ), // 10 is supposed to be plural (other), not "many"
+                       array( 'many', 20 ), // Fourth form provided - rare, but supported by CLDR
+               );
+       }
+
+       /**
+        * @dataProvider provideGrammar
+        * @covers Language::convertGrammar
+        */
+       public function testGrammar( $result, $word, $case ) {
+               $this->assertEquals( $result, $this->getLang()->convertGrammar( $word, $case ) );
+       }
+
+       // The comments in the beginning of the line help avoid RTL problems
+       // with text editors.
+       public static function provideGrammar() {
+               return array(
+                       array(
+                               /* result */'וויקיפדיה',
+                               /* word   */'ויקיפדיה',
+                               /* case   */'תחילית',
+                       ),
+                       array(
+                               /* result */'וולפגנג',
+                               /* word   */'וולפגנג',
+                               /* case   */'prefixed',
+                       ),
+                       array(
+                               /* result */'קובץ',
+                               /* word   */'הקובץ',
+                               /* case   */'תחילית',
+                       ),
+                       array(
+                               /* result */'־Wikipedia',
+                               /* word   */'Wikipedia',
+                               /* case   */'תחילית',
+                       ),
+                       array(
+                               /* result */'־1995',
+                               /* word   */'1995',
+                               /* case   */'תחילית',
+                       ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageHiTest.php b/tests/phpunit/languages/classes/LanguageHiTest.php
new file mode 100644 (file)
index 0000000..f6d2c9e
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageHi.php */
+class LanguageHiTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageHrTest.php b/tests/phpunit/languages/classes/LanguageHrTest.php
new file mode 100644 (file)
index 0000000..644c525
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageHr.php */
+class LanguageHrTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'few', 2 ),
+                       array( 'few', 4 ),
+                       array( 'other', 5 ),
+                       array( 'other', 11 ),
+                       array( 'other', 20 ),
+                       array( 'one', 21 ),
+                       array( 'few', 24 ),
+                       array( 'other', 25 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageHsbTest.php b/tests/phpunit/languages/classes/LanguageHsbTest.php
new file mode 100644 (file)
index 0000000..f95a43b
--- /dev/null
@@ -0,0 +1,41 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageHsb.php */
+class LanguageHsbTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'two', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'one', 101 ),
+                       array( 'one', 90001 ),
+                       array( 'two', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 203 ),
+                       array( 'few', 4 ),
+                       array( 'other', 99 ),
+                       array( 'other', 555 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageHuTest.php b/tests/phpunit/languages/classes/LanguageHuTest.php
new file mode 100644 (file)
index 0000000..ee9197d
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageHu.php */
+class LanguageHuTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageHyTest.php b/tests/phpunit/languages/classes/LanguageHyTest.php
new file mode 100644 (file)
index 0000000..92e0ef9
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for Armenian (Հայերեն) */
+class LanguageHyTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageKshTest.php b/tests/phpunit/languages/classes/LanguageKshTest.php
new file mode 100644 (file)
index 0000000..568a378
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageKsh.php */
+class LanguageKshTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other', 'zero' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'zero', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageLnTest.php b/tests/phpunit/languages/classes/LanguageLnTest.php
new file mode 100644 (file)
index 0000000..10b3234
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageLn.php */
+class LanguageLnTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageLtTest.php b/tests/phpunit/languages/classes/LanguageLtTest.php
new file mode 100644 (file)
index 0000000..30642f6
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageLt.php */
+class LanguageLtTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'few', 2 ),
+                       array( 'few', 9 ),
+                       array( 'other', 10 ),
+                       array( 'other', 11 ),
+                       array( 'other', 20 ),
+                       array( 'one', 21 ),
+                       array( 'few', 32 ),
+                       array( 'one', 41 ),
+                       array( 'one', 40001 ),
+               );
+       }
+
+       /**
+        * @dataProvider providePluralTwoForms
+        * @covers Language::convertPlural
+        */
+       public function testOneFewPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               // This fails for 21, but not sure why.
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       public static function providePluralTwoForms() {
+               return array(
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 15 ),
+                       array( 'other', 20 ),
+                       array( 'one', 21 ),
+                       array( 'other', 22 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageLvTest.php b/tests/phpunit/languages/classes/LanguageLvTest.php
new file mode 100644 (file)
index 0000000..7120cfe
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for Latvian */
+class LanguageLvTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'zero', 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'zero', 0 ),
+                       array( 'one', 1 ),
+                       array( 'zero', 11 ),
+                       array( 'one', 21 ),
+                       array( 'zero', 411 ),
+                       array( 'other', 2 ),
+                       array( 'other', 9 ),
+                       array( 'zero', 12 ),
+                       array( 'other', 12.345 ),
+                       array( 'zero', 20 ),
+                       array( 'other', 22 ),
+                       array( 'one', 31 ),
+                       array( 'zero', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageMgTest.php b/tests/phpunit/languages/classes/LanguageMgTest.php
new file mode 100644 (file)
index 0000000..65e8fd7
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageMg.php */
+class LanguageMgTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 200 ),
+                       array( 'other', 123.3434 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageMkTest.php b/tests/phpunit/languages/classes/LanguageMkTest.php
new file mode 100644 (file)
index 0000000..ed15526
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for македонски/Macedonian */
+class LanguageMkTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'one', 11 ),
+                       array( 'one', 21 ),
+                       array( 'one', 411 ),
+                       array( 'other', 12.345 ),
+                       array( 'other', 20 ),
+                       array( 'one', 31 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageMlTest.php b/tests/phpunit/languages/classes/LanguageMlTest.php
new file mode 100644 (file)
index 0000000..4fa45ce
--- /dev/null
@@ -0,0 +1,38 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2011, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageMl.php */
+class LanguageMlTest extends LanguageClassesTestCase {
+
+       /**
+        * @dataProvider providerFormatNum
+        * @see bug 29495
+        * @covers Language::formatNum
+        */
+       public function testFormatNum( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->formatNum( $value ) );
+       }
+
+       public static function providerFormatNum() {
+               return array(
+                       array( '12,34,567', '1234567' ),
+                       array( '12,345', '12345' ),
+                       array( '1', '1' ),
+                       array( '123', '123' ),
+                       array( '1,234', '1234' ),
+                       array( '12,345.56', '12345.56' ),
+                       array( '12,34,56,79,81,23,45,678', '12345679812345678' ),
+                       array( '.12345', '.12345' ),
+                       array( '-12,00,000', '-1200000' ),
+                       array( '-98', '-98' ),
+                       array( '-98', -98 ),
+                       array( '-1,23,45,678', -12345678 ),
+                       array( '', '' ),
+                       array( '', null ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageMoTest.php b/tests/phpunit/languages/classes/LanguageMoTest.php
new file mode 100644 (file)
index 0000000..e0e54ca
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageMo.php */
+class LanguageMoTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'few', 0 ),
+                       array( 'one', 1 ),
+                       array( 'few', 2 ),
+                       array( 'few', 19 ),
+                       array( 'other', 20 ),
+                       array( 'other', 99 ),
+                       array( 'other', 100 ),
+                       array( 'few', 101 ),
+                       array( 'few', 119 ),
+                       array( 'other', 120 ),
+                       array( 'other', 200 ),
+                       array( 'few', 201 ),
+                       array( 'few', 219 ),
+                       array( 'other', 220 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageMtTest.php b/tests/phpunit/languages/classes/LanguageMtTest.php
new file mode 100644 (file)
index 0000000..96d2bc9
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageMt.php */
+class LanguageMtTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'many', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'few', 0 ),
+                       array( 'one', 1 ),
+                       array( 'few', 2 ),
+                       array( 'few', 10 ),
+                       array( 'many', 11 ),
+                       array( 'many', 19 ),
+                       array( 'other', 20 ),
+                       array( 'other', 99 ),
+                       array( 'other', 100 ),
+                       array( 'other', 101 ),
+                       array( 'few', 102 ),
+                       array( 'few', 110 ),
+                       array( 'many', 111 ),
+                       array( 'many', 119 ),
+                       array( 'other', 120 ),
+                       array( 'other', 201 ),
+               );
+       }
+
+       /**
+        * @dataProvider providePluralTwoForms
+        * @covers Language::convertPlural
+        */
+       public function testPluralTwoForms( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       public static function providePluralTwoForms() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 10 ),
+                       array( 'other', 11 ),
+                       array( 'other', 19 ),
+                       array( 'other', 20 ),
+                       array( 'other', 99 ),
+                       array( 'other', 100 ),
+                       array( 'other', 101 ),
+                       array( 'other', 102 ),
+                       array( 'other', 110 ),
+                       array( 'other', 111 ),
+                       array( 'other', 119 ),
+                       array( 'other', 120 ),
+                       array( 'other', 201 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageNlTest.php b/tests/phpunit/languages/classes/LanguageNlTest.php
new file mode 100644 (file)
index 0000000..26bd691
--- /dev/null
@@ -0,0 +1,24 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2011, Santhosh Thottingal
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageNl.php */
+class LanguageNlTest extends LanguageClassesTestCase {
+
+       /**
+        * @covers Language::formatNum
+        * @todo split into a test and a dataprovider
+        */
+       public function testFormatNum() {
+               $this->assertEquals( '1.234.567', $this->getLang()->formatNum( '1234567' ) );
+               $this->assertEquals( '12.345', $this->getLang()->formatNum( '12345' ) );
+               $this->assertEquals( '1', $this->getLang()->formatNum( '1' ) );
+               $this->assertEquals( '123', $this->getLang()->formatNum( '123' ) );
+               $this->assertEquals( '1.234', $this->getLang()->formatNum( '1234' ) );
+               $this->assertEquals( '12.345,56', $this->getLang()->formatNum( '12345.56' ) );
+               $this->assertEquals( ',1234556', $this->getLang()->formatNum( '.1234556' ) );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageNsoTest.php b/tests/phpunit/languages/classes/LanguageNsoTest.php
new file mode 100644 (file)
index 0000000..18efd73
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageNso.php */
+class LanguageNsoTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguagePlTest.php b/tests/phpunit/languages/classes/LanguagePlTest.php
new file mode 100644 (file)
index 0000000..d180037
--- /dev/null
@@ -0,0 +1,77 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguagePl.php */
+class LanguagePlTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'many' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'many', 0 ),
+                       array( 'one', 1 ),
+                       array( 'few', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 4 ),
+                       array( 'many', 5 ),
+                       array( 'many', 9 ),
+                       array( 'many', 10 ),
+                       array( 'many', 11 ),
+                       array( 'many', 21 ),
+                       array( 'few', 22 ),
+                       array( 'few', 23 ),
+                       array( 'few', 24 ),
+                       array( 'many', 25 ),
+                       array( 'many', 200 ),
+                       array( 'many', 201 ),
+               );
+       }
+
+       /**
+        * @dataProvider providePluralTwoForms
+        * @covers Language::convertPlural
+        */
+       public function testPluralTwoForms( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       public static function providePluralTwoForms() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 3 ),
+                       array( 'other', 4 ),
+                       array( 'other', 5 ),
+                       array( 'other', 9 ),
+                       array( 'other', 10 ),
+                       array( 'other', 11 ),
+                       array( 'other', 21 ),
+                       array( 'other', 22 ),
+                       array( 'other', 23 ),
+                       array( 'other', 24 ),
+                       array( 'other', 25 ),
+                       array( 'other', 200 ),
+                       array( 'other', 201 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageRoTest.php b/tests/phpunit/languages/classes/LanguageRoTest.php
new file mode 100644 (file)
index 0000000..ae7816b
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageRo.php */
+class LanguageRoTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'few', 0 ),
+                       array( 'one', 1 ),
+                       array( 'few', 2 ),
+                       array( 'few', 19 ),
+                       array( 'other', 20 ),
+                       array( 'other', 99 ),
+                       array( 'other', 100 ),
+                       array( 'few', 101 ),
+                       array( 'few', 119 ),
+                       array( 'other', 120 ),
+                       array( 'other', 200 ),
+                       array( 'few', 201 ),
+                       array( 'few', 219 ),
+                       array( 'other', 220 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageRuTest.php b/tests/phpunit/languages/classes/LanguageRuTest.php
new file mode 100644 (file)
index 0000000..1381afb
--- /dev/null
@@ -0,0 +1,115 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * based on LanguageBe_tarask.php
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageRu.php */
+class LanguageRuTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'many', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * Test explicit plural forms - n=FormN forms
+        * @covers Language::convertPlural
+        */
+       public function testExplicitPlural() {
+               $forms = array( 'one', 'few', 'many', 'other', '12=dozen' );
+               $this->assertEquals( 'dozen', $this->getLang()->convertPlural( 12, $forms ) );
+               $forms = array( 'one', 'few', 'many', '100=hundred', 'other', '12=dozen' );
+               $this->assertEquals( 'hundred', $this->getLang()->convertPlural( 100, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 1 ),
+                       array( 'many', 11 ),
+                       array( 'one', 91 ),
+                       array( 'one', 121 ),
+                       array( 'few', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 4 ),
+                       array( 'few', 334 ),
+                       array( 'many', 5 ),
+                       array( 'many', 15 ),
+                       array( 'many', 120 ),
+               );
+       }
+
+       /**
+        * @dataProvider providePluralTwoForms
+        * @covers Language::convertPlural
+        */
+       public function testPluralTwoForms( $result, $value ) {
+               $forms = array( '1=one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       public static function providePluralTwoForms() {
+               return array(
+                       array( 'one', 1 ),
+                       array( 'other', 11 ),
+                       array( 'other', 91 ),
+                       array( 'other', 121 ),
+               );
+       }
+
+       /**
+        * @dataProvider providerGrammar
+        * @covers Language::convertGrammar
+        */
+       public function testGrammar( $result, $word, $case ) {
+               $this->assertEquals( $result, $this->getLang()->convertGrammar( $word, $case ) );
+       }
+
+       public static function providerGrammar() {
+               return array(
+                       array(
+                               'Википедии',
+                               'Википедия',
+                               'genitive',
+                       ),
+                       array(
+                               'Викитеки',
+                               'Викитека',
+                               'genitive',
+                       ),
+                       array(
+                               'Викитеке',
+                               'Викитека',
+                               'prepositional',
+                       ),
+                       array(
+                               'Викисклада',
+                               'Викисклад',
+                               'genitive',
+                       ),
+                       array(
+                               'Викискладе',
+                               'Викисклад',
+                               'prepositional',
+                       ),
+                       array(
+                               'Викиданных',
+                               'Викиданные',
+                               'prepositional',
+                       ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageSeTest.php b/tests/phpunit/languages/classes/LanguageSeTest.php
new file mode 100644 (file)
index 0000000..533aa2b
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageSe.php */
+class LanguageSeTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'two', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'two', 2 ),
+                       array( 'other', 3 ),
+               );
+       }
+
+       /**
+        * @dataProvider providePluralTwoForms
+        * @covers Language::convertPlural
+        */
+       public function testPluralTwoForms( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       public static function providePluralTwoForms() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 3 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageSgsTest.php b/tests/phpunit/languages/classes/LanguageSgsTest.php
new file mode 100644 (file)
index 0000000..fa49a4d
--- /dev/null
@@ -0,0 +1,71 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for Samogitian */
+class LanguageSgsTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePluralAllForms
+        * @covers Language::convertPlural
+        */
+       public function testPluralAllForms( $result, $value ) {
+               $forms = array( 'one', 'two', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePluralAllForms
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePluralAllForms() {
+               return array(
+                       array( 'few', 0 ),
+                       array( 'one', 1 ),
+                       array( 'two', 2 ),
+                       array( 'other', 3 ),
+                       array( 'few', 10 ),
+                       array( 'few', 11 ),
+                       array( 'few', 12 ),
+                       array( 'few', 19 ),
+                       array( 'other', 20 ),
+                       array( 'few', 100 ),
+                       array( 'one', 101 ),
+                       array( 'few', 111 ),
+                       array( 'few', 112 ),
+               );
+       }
+
+       /**
+        * @dataProvider providePluralTwoForms
+        * @covers Language::convertPlural
+        */
+       public function testPluralTwoForms( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       public static function providePluralTwoForms() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 3 ),
+                       array( 'other', 10 ),
+                       array( 'other', 11 ),
+                       array( 'other', 12 ),
+                       array( 'other', 19 ),
+                       array( 'other', 20 ),
+                       array( 'other', 100 ),
+                       array( 'one', 101 ),
+                       array( 'other', 111 ),
+                       array( 'other', 112 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageShTest.php b/tests/phpunit/languages/classes/LanguageShTest.php
new file mode 100644 (file)
index 0000000..1b39087
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for  srpskohrvatski / српскохрватски / Serbocroatian */
+class LanguageShTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'few', 2 ),
+                       array( 'few', 4 ),
+                       array( 'other', 5 ),
+                       array( 'other', 10 ),
+                       array( 'other', 11 ),
+                       array( 'other', 12 ),
+                       array( 'one', 101 ),
+                       array( 'few', 102 ),
+                       array( 'other', 111 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageSkTest.php b/tests/phpunit/languages/classes/LanguageSkTest.php
new file mode 100644 (file)
index 0000000..cb8a13b
--- /dev/null
@@ -0,0 +1,42 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * based on LanguageSkTest.php
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageSk.php */
+class LanguageSkTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'few', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 4 ),
+                       array( 'other', 5 ),
+                       array( 'other', 11 ),
+                       array( 'other', 20 ),
+                       array( 'other', 25 ),
+                       array( 'other', 200 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageSlTest.php b/tests/phpunit/languages/classes/LanguageSlTest.php
new file mode 100644 (file)
index 0000000..9783dd8
--- /dev/null
@@ -0,0 +1,44 @@
+<?php
+/**
+ * @author Santhosh Thottingal
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * based on LanguageSkTest.php
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageSl.php */
+class LanguageSlTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providerPlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'two', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providerPlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providerPlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'two', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 4 ),
+                       array( 'other', 5 ),
+                       array( 'other', 99 ),
+                       array( 'other', 100 ),
+                       array( 'one', 101 ),
+                       array( 'two', 102 ),
+                       array( 'few', 103 ),
+                       array( 'one', 201 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageSmaTest.php b/tests/phpunit/languages/classes/LanguageSmaTest.php
new file mode 100644 (file)
index 0000000..95cb333
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageSma.php */
+class LanguageSmaTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'two', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'two', 2 ),
+                       array( 'other', 3 ),
+               );
+       }
+
+       /**
+        * @dataProvider providePluralTwoForms
+        * @covers Language::convertPlural
+        */
+       public function testPluralTwoForms( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       public static function providePluralTwoForms() {
+               return array(
+                       array( 'other', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+                       array( 'other', 3 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageSrTest.php b/tests/phpunit/languages/classes/LanguageSrTest.php
new file mode 100644 (file)
index 0000000..bfb199f
--- /dev/null
@@ -0,0 +1,249 @@
+<?php
+/**
+ * PHPUnit tests for the Serbian language.
+ * The language can be represented using two scripts:
+ *  - Latin (SR_el)
+ *  - Cyrillic (SR_ec)
+ * Both representations seems to be bijective, hence MediaWiki can convert
+ * from one script to the other.
+ *
+ * @author Antoine Musso <hashar at free dot fr>
+ * @copyright Copyright © 2011, Antoine Musso <hashar at free dot fr>
+ * @file
+ *
+ * @todo methods in test class should be tidied:
+ *  - Should be split into separate test methods and data providers
+ *  - Tests for LanguageConverter and Language should probably be separate..
+ */
+
+/** Tests for MediaWiki languages/LanguageSr.php */
+class LanguageSrTest extends LanguageClassesTestCase {
+       /**
+        * @covers LanguageConverter::convertTo
+        */
+       public function testEasyConversions() {
+               $this->assertCyrillic(
+                       'шђчћжШЂЧЋЖ',
+                       'Cyrillic guessing characters'
+               );
+               $this->assertLatin(
+                       'šđč枊ĐČĆŽ',
+                       'Latin guessing characters'
+               );
+       }
+
+       /**
+        * @covers LanguageConverter::convertTo
+        */
+       public function testMixedConversions() {
+               $this->assertCyrillic(
+                       'шђчћжШЂЧЋЖ - šđčćž',
+                       'Mostly cyrillic characters'
+               );
+               $this->assertLatin(
+                       'šđč枊ĐČĆŽ - шђчћж',
+                       'Mostly latin characters'
+               );
+       }
+
+       /**
+        * @covers LanguageConverter::convertTo
+        */
+       public function testSameAmountOfLatinAndCyrillicGetConverted() {
+               $this->assertConverted(
+                       '4 latin: šđčć | 4 cyrillic: шђчћ',
+                       'sr-ec'
+               );
+               $this->assertConverted(
+                       '4 latin: šđčć | 4 cyrillic: шђчћ',
+                       'sr-el'
+               );
+       }
+
+       /**
+        * @author Nikola Smolenski
+        * @covers LanguageConverter::convertTo
+        */
+       public function testConversionToCyrillic() {
+               //A simple convertion of Latin to Cyrillic
+               $this->assertEquals( 'абвг',
+                       $this->convertToCyrillic( 'abvg' )
+               );
+               //Same as above, but assert that -{}-s must be removed and not converted
+               $this->assertEquals( 'ljабnjвгdž',
+                       $this->convertToCyrillic( '-{lj}-ab-{nj}-vg-{dž}-' )
+               );
+               //A simple convertion of Cyrillic to Cyrillic
+               $this->assertEquals( 'абвг',
+                       $this->convertToCyrillic( 'абвг' )
+               );
+               //Same as above, but assert that -{}-s must be removed and not converted
+               $this->assertEquals( 'ljабnjвгdž',
+                       $this->convertToCyrillic( '-{lj}-аб-{nj}-вг-{dž}-' )
+               );
+               //This text has some Latin, but is recognized as Cyrillic, so it should not be converted
+               $this->assertEquals( 'abvgшђжчћ',
+                       $this->convertToCyrillic( 'abvgшђжчћ' )
+               );
+               //Same as above, but assert that -{}-s must be removed
+               $this->assertEquals( 'љabvgњшђжчћџ',
+                       $this->convertToCyrillic( '-{љ}-abvg-{њ}-шђжчћ-{џ}-' )
+               );
+               //This text has some Cyrillic, but is recognized as Latin, so it should be converted
+               $this->assertEquals( 'абвгшђжчћ',
+                       $this->convertToCyrillic( 'абвгšđžčć' )
+               );
+               //Same as above, but assert that -{}-s must be removed and not converted
+               $this->assertEquals( 'ljабвгnjшђжчћdž',
+                       $this->convertToCyrillic( '-{lj}-абвг-{nj}-šđžčć-{dž}-' )
+               );
+               // Roman numerals are not converted
+               $this->assertEquals( 'а I б II в III г IV шђжчћ',
+                       $this->convertToCyrillic( 'a I b II v III g IV šđžčć' )
+               );
+       }
+
+       /**
+        * @covers LanguageConverter::convertTo
+        */
+       public function testConversionToLatin() {
+               //A simple convertion of Latin to Latin
+               $this->assertEquals( 'abcd',
+                       $this->convertToLatin( 'abcd' )
+               );
+               //A simple convertion of Cyrillic to Latin
+               $this->assertEquals( 'abcd',
+                       $this->convertToLatin( 'абцд' )
+               );
+               //This text has some Latin, but is recognized as Cyrillic, so it should be converted
+               $this->assertEquals( 'abcdšđžčć',
+                       $this->convertToLatin( 'abcdшђжчћ' )
+               );
+               //This text has some Cyrillic, but is recognized as Latin, so it should not be converted
+               $this->assertEquals( 'абцдšđžčć',
+                       $this->convertToLatin( 'абцдšđžčć' )
+               );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 1 ),
+                       array( 'other', 11 ),
+                       array( 'one', 91 ),
+                       array( 'one', 121 ),
+                       array( 'few', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 4 ),
+                       array( 'few', 334 ),
+                       array( 'other', 5 ),
+                       array( 'other', 15 ),
+                       array( 'other', 120 ),
+               );
+       }
+
+       /**
+        * @dataProvider providePluralTwoForms
+        * @covers Language::convertPlural
+        */
+       public function testPluralTwoForms( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       public static function providePluralTwoForms() {
+               return array(
+                       array( 'one', 1 ),
+                       array( 'other', 11 ),
+                       array( 'other', 4 ),
+                       array( 'one', 91 ),
+                       array( 'one', 121 ),
+               );
+       }
+
+       ##### HELPERS #####################################################
+       /**
+        *Wrapper to verify text stay the same after applying conversion
+        * @param string $text Text to convert
+        * @param string $variant Language variant 'sr-ec' or 'sr-el'
+        * @param string $msg Optional message
+        */
+       protected function assertUnConverted( $text, $variant, $msg = '' ) {
+               $this->assertEquals(
+                       $text,
+                       $this->convertTo( $text, $variant ),
+                       $msg
+               );
+       }
+
+       /**
+        * Wrapper to verify a text is different once converted to a variant.
+        * @param string $text Text to convert
+        * @param string $variant Language variant 'sr-ec' or 'sr-el'
+        * @param string $msg Optional message
+        */
+       protected function assertConverted( $text, $variant, $msg = '' ) {
+               $this->assertNotEquals(
+                       $text,
+                       $this->convertTo( $text, $variant ),
+                       $msg
+               );
+       }
+
+       /**
+        * Verifiy the given Cyrillic text is not converted when using
+        * using the cyrillic variant and converted to Latin when using
+        * the Latin variant.
+        * @param string $text Text to convert
+        * @param string $msg Optional message
+        */
+       protected function assertCyrillic( $text, $msg = '' ) {
+               $this->assertUnConverted( $text, 'sr-ec', $msg );
+               $this->assertConverted( $text, 'sr-el', $msg );
+       }
+
+       /**
+        * Verifiy the given Latin text is not converted when using
+        * using the Latin variant and converted to Cyrillic when using
+        * the Cyrillic variant.
+        * @param string $text Text to convert
+        * @param string $msg Optional message
+        */
+       protected function assertLatin( $text, $msg = '' ) {
+               $this->assertUnConverted( $text, 'sr-el', $msg );
+               $this->assertConverted( $text, 'sr-ec', $msg );
+       }
+
+       /** Wrapper for converter::convertTo() method*/
+       protected function convertTo( $text, $variant ) {
+               return $this->getLang()
+                       ->mConverter
+                       ->convertTo(
+                               $text, $variant
+                       );
+       }
+
+       protected function convertToCyrillic( $text ) {
+               return $this->convertTo( $text, 'sr-ec' );
+       }
+
+       protected function convertToLatin( $text ) {
+               return $this->convertTo( $text, 'sr-el' );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageTiTest.php b/tests/phpunit/languages/classes/LanguageTiTest.php
new file mode 100644 (file)
index 0000000..e225af9
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageTi.php */
+class LanguageTiTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageTlTest.php b/tests/phpunit/languages/classes/LanguageTlTest.php
new file mode 100644 (file)
index 0000000..20f5bd7
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageTl.php */
+class LanguageTlTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 0 ),
+                       array( 'one', 1 ),
+                       array( 'one', 2 ),
+                       array( 'other', 4 ),
+                       array( 'other', 6 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageTrTest.php b/tests/phpunit/languages/classes/LanguageTrTest.php
new file mode 100644 (file)
index 0000000..2c9905f
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+/**
+ * @author Antoine Musso
+ * @copyright Copyright © 2011, Antoine Musso
+ * @file
+ */
+
+/** Tests for MediaWiki languages/LanguageTr.php */
+class LanguageTrTest extends LanguageClassesTestCase {
+
+       /**
+        * See @bug 28040
+        * Credits to irc://irc.freenode.net/wikipedia-tr users:
+        *  - berm
+        *  - []LuCkY[]
+        *  - Emperyan
+        * @see http://en.wikipedia.org/wiki/Dotted_and_dotless_I
+        * @dataProvider provideDottedAndDotlessI
+        * @covers Language::ucfirst
+        * @covers Language::lcfirst
+        */
+       public function testDottedAndDotlessI( $func, $input, $inputCase, $expected ) {
+               if ( $func == 'ucfirst' ) {
+                       $res = $this->getLang()->ucfirst( $input );
+               } elseif ( $func == 'lcfirst' ) {
+                       $res = $this->getLang()->lcfirst( $input );
+               } else {
+                       throw new MWException( __METHOD__ . " given an invalid function name '$func'" );
+               }
+
+               $msg = "Converting $inputCase case '$input' with $func should give '$expected'";
+
+               $this->assertEquals( $expected, $res, $msg );
+       }
+
+       public static function provideDottedAndDotlessI() {
+               return array(
+                       # function, input, input case, expected
+                       # Case changed:
+                       array( 'ucfirst', 'ı', 'lower', 'I' ),
+                       array( 'ucfirst', 'i', 'lower', 'İ' ),
+                       array( 'lcfirst', 'I', 'upper', 'ı' ),
+                       array( 'lcfirst', 'İ', 'upper', 'i' ),
+
+                       # Already using the correct case
+                       array( 'ucfirst', 'I', 'upper', 'I' ),
+                       array( 'ucfirst', 'İ', 'upper', 'İ' ),
+                       array( 'lcfirst', 'ı', 'lower', 'ı' ),
+                       array( 'lcfirst', 'i', 'lower', 'i' ),
+
+                       # A real example taken from bug 28040 using
+                       # http://tr.wikipedia.org/wiki/%C4%B0Phone
+                       array( 'lcfirst', 'iPhone', 'lower', 'iPhone' ),
+
+                       # next case is valid in Turkish but are different words if we
+                       # consider IPhone is English!
+                       array( 'lcfirst', 'IPhone', 'upper', 'ıPhone' ),
+
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageUkTest.php b/tests/phpunit/languages/classes/LanguageUkTest.php
new file mode 100644 (file)
index 0000000..9051bcf
--- /dev/null
@@ -0,0 +1,72 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * based on LanguageBe_tarask.php
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for Ukrainian */
+class LanguageUkTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'few', 'many', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * Test explicit plural forms - n=FormN forms
+        * @covers Language::convertPlural
+        */
+       public function testExplicitPlural() {
+               $forms = array( 'one', 'few', 'many', 'other', '12=dozen' );
+               $this->assertEquals( 'dozen', $this->getLang()->convertPlural( 12, $forms ) );
+               $forms = array( 'one', 'few', 'many', '100=hundred', 'other', '12=dozen' );
+               $this->assertEquals( 'hundred', $this->getLang()->convertPlural( 100, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 1 ),
+                       array( 'many', 11 ),
+                       array( 'one', 91 ),
+                       array( 'one', 121 ),
+                       array( 'few', 2 ),
+                       array( 'few', 3 ),
+                       array( 'few', 4 ),
+                       array( 'few', 334 ),
+                       array( 'many', 5 ),
+                       array( 'many', 15 ),
+                       array( 'many', 120 ),
+               );
+       }
+
+       /**
+        * @dataProvider providePluralTwoForms
+        * @covers Language::convertPlural
+        */
+       public function testPluralTwoForms( $result, $value ) {
+               $forms = array( '1=one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       public static function providePluralTwoForms() {
+               return array(
+                       array( 'one', 1 ),
+                       array( 'other', 11 ),
+                       array( 'other', 91 ),
+                       array( 'other', 121 ),
+               );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageUzTest.php b/tests/phpunit/languages/classes/LanguageUzTest.php
new file mode 100644 (file)
index 0000000..4881103
--- /dev/null
@@ -0,0 +1,124 @@
+<?php
+/**
+ * PHPUnit tests for the Uzbek language.
+ * The language can be represented using two scripts:
+ *  - Latin (uz-latn)
+ *  - Cyrillic (uz-cyrl)
+ *
+ * @author Robin Pepermans
+ * @author Antoine Musso <hashar at free dot fr>
+ * @copyright Copyright © 2012, Robin Pepermans
+ * @copyright Copyright © 2011, Antoine Musso <hashar at free dot fr>
+ * @file
+ *
+ * @todo methods in test class should be tidied:
+ *  - Should be split into separate test methods and data providers
+ *  - Tests for LanguageConverter and Language should probably be separate..
+ */
+
+/** Tests for MediaWiki languages/LanguageUz.php */
+class LanguageUzTest extends LanguageClassesTestCase {
+
+       /**
+        * @author Nikola Smolenski
+        * @covers LanguageConverter::convertTo
+        */
+       public function testConversionToCyrillic() {
+               // A convertion of Latin to Cyrillic
+               $this->assertEquals( 'абвгғ',
+                       $this->convertToCyrillic( 'abvggʻ' )
+               );
+               // Same as above, but assert that -{}-s must be removed and not converted
+               $this->assertEquals( 'ljабnjвгўоdb',
+                       $this->convertToCyrillic( '-{lj}-ab-{nj}-vgoʻo-{db}-' )
+               );
+               // A simple convertion of Cyrillic to Cyrillic
+               $this->assertEquals( 'абвг',
+                       $this->convertToCyrillic( 'абвг' )
+               );
+               // Same as above, but assert that -{}-s must be removed and not converted
+               $this->assertEquals( 'ljабnjвгdaž',
+                       $this->convertToCyrillic( '-{lj}-аб-{nj}-вг-{da}-ž' )
+               );
+       }
+
+       /**
+        * @covers LanguageConverter::convertTo
+        */
+       public function testConversionToLatin() {
+               // A simple convertion of Latin to Latin
+               $this->assertEquals( 'abdef',
+                       $this->convertToLatin( 'abdef' )
+               );
+               // A convertion of Cyrillic to Latin
+               $this->assertEquals( 'gʻabtsdOʻQyo',
+                       $this->convertToLatin( 'ғабцдЎҚё' )
+               );
+       }
+
+       ##### HELPERS #####################################################
+       /**
+        * Wrapper to verify text stay the same after applying conversion
+        * @param string $text Text to convert
+        * @param string $variant Language variant 'uz-cyrl' or 'uz-latn'
+        * @param string $msg Optional message
+        */
+       protected function assertUnConverted( $text, $variant, $msg = '' ) {
+               $this->assertEquals(
+                       $text,
+                       $this->convertTo( $text, $variant ),
+                       $msg
+               );
+       }
+
+       /**
+        * Wrapper to verify a text is different once converted to a variant.
+        * @param string $text Text to convert
+        * @param string $variant Language variant 'uz-cyrl' or 'uz-latn'
+        * @param string $msg Optional message
+        */
+       protected function assertConverted( $text, $variant, $msg = '' ) {
+               $this->assertNotEquals(
+                       $text,
+                       $this->convertTo( $text, $variant ),
+                       $msg
+               );
+       }
+
+       /**
+        * Verifiy the given Cyrillic text is not converted when using
+        * using the cyrillic variant and converted to Latin when using
+        * the Latin variant.
+        * @param string $text Text to convert
+        * @param string $msg Optional message
+        */
+       protected function assertCyrillic( $text, $msg = '' ) {
+               $this->assertUnConverted( $text, 'uz-cyrl', $msg );
+               $this->assertConverted( $text, 'uz-latn', $msg );
+       }
+
+       /**
+        * Verifiy the given Latin text is not converted when using
+        * using the Latin variant and converted to Cyrillic when using
+        * the Cyrillic variant.
+        * @param string $text Text to convert
+        * @param string $msg Optional message
+        */
+       protected function assertLatin( $text, $msg = '' ) {
+               $this->assertUnConverted( $text, 'uz-latn', $msg );
+               $this->assertConverted( $text, 'uz-cyrl', $msg );
+       }
+
+       /** Wrapper for converter::convertTo() method*/
+       protected function convertTo( $text, $variant ) {
+               return $this->getLang()->mConverter->convertTo( $text, $variant );
+       }
+
+       protected function convertToCyrillic( $text ) {
+               return $this->convertTo( $text, 'uz-cyrl' );
+       }
+
+       protected function convertToLatin( $text ) {
+               return $this->convertTo( $text, 'uz-latn' );
+       }
+}
diff --git a/tests/phpunit/languages/classes/LanguageWaTest.php b/tests/phpunit/languages/classes/LanguageWaTest.php
new file mode 100644 (file)
index 0000000..d05196c
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+/**
+ * @author Amir E. Aharoni
+ * @copyright Copyright © 2012, Amir E. Aharoni
+ * @file
+ */
+
+/** Tests for MediaWiki languages/classes/LanguageWa.php */
+class LanguageWaTest extends LanguageClassesTestCase {
+       /**
+        * @dataProvider providePlural
+        * @covers Language::convertPlural
+        */
+       public function testPlural( $result, $value ) {
+               $forms = array( 'one', 'other' );
+               $this->assertEquals( $result, $this->getLang()->convertPlural( $value, $forms ) );
+       }
+
+       /**
+        * @dataProvider providePlural
+        * @covers Language::getPluralRuleType
+        */
+       public function testGetPluralRuleType( $result, $value ) {
+               $this->assertEquals( $result, $this->getLang()->getPluralRuleType( $value ) );
+       }
+
+       public static function providePlural() {
+               return array(
+                       array( 'one', 0 ),
+                       array( 'one', 1 ),
+                       array( 'other', 2 ),
+               );
+       }
+}
index 7294d62..03aaf4a 100644 (file)
@@ -36,7 +36,8 @@
        QUnit.config.urlConfig.push( {
                id: 'debug',
                label: 'Enable ResourceLoaderDebug',
-               tooltip: 'Enable debug mode in ResourceLoader'
+               tooltip: 'Enable debug mode in ResourceLoader',
+               value: 'true'
        } );
 
        /**
                };
        }() );
 
+       // Extend QUnit.module to provide a fixture element.
+       ( function () {
+               var orgModule = QUnit.module;
+
+               QUnit.module = function ( name, localEnv ) {
+                       var fixture;
+                       localEnv = localEnv || {};
+                       orgModule( name, {
+                               setup: function () {
+                                       fixture = document.createElement( 'div' );
+                                       fixture.id = 'qunit-fixture';
+                                       document.body.appendChild( fixture );
+
+                                       if ( localEnv.setup ) {
+                                               localEnv.setup.call( this );
+                                       }
+                               },
+                               teardown: function () {
+                                       if ( localEnv.teardown ) {
+                                               localEnv.teardown.call( this );
+                                       }
+
+                                       fixture.parentNode.removeChild( fixture );
+                               }
+                       } );
+               };
+       }() );
+
        // Initiate when enabled
        if ( QUnit.urlParams.completenesstest ) {
 
index a972b21..7352dc4 100644 (file)
--- a/thumb.php
+++ b/thumb.php
@@ -92,7 +92,6 @@ function wfThumbHandle404() {
 function wfStreamThumb( array $params ) {
        global $wgVaryOnXFP;
 
-       $section = new ProfileSection( __METHOD__ );
 
        $headers = array(); // HTTP headers to send