Merge "Don't call localisation functions when initializing pageset"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Fri, 9 Jan 2015 17:02:38 +0000 (17:02 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Fri, 9 Jan 2015 17:02:38 +0000 (17:02 +0000)
239 files changed:
.gitignore
RELEASE-NOTES-1.25
StartProfiler.sample
api.php
autoload.php
composer.json
docs/extension.schema.json [new file with mode: 0644]
img_auth.php
includes/AjaxDispatcher.php
includes/Block.php
includes/Category.php
includes/CategoryFinder.php
includes/CategoryViewer.php
includes/DefaultSettings.php
includes/EditPage.php
includes/Export.php
includes/FeedUtils.php
includes/GlobalFunctions.php
includes/Html.php
includes/HtmlFormatter.php
includes/HttpFunctions.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/ApiPageSet.php
includes/api/ApiParse.php
includes/api/ApiQuerySearch.php
includes/api/ApiQueryTokens.php
includes/api/ApiStashEdit.php
includes/api/ApiTokens.php
includes/api/i18n/be-tarask.json
includes/api/i18n/ca.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/WikitextContent.php
includes/context/RequestContext.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/filebackend/FSFile.php
includes/filebackend/FileBackendStore.php
includes/filebackend/FileOpBatch.php
includes/filebackend/SwiftFileBackend.php
includes/filebackend/TempFSFile.php
includes/filebackend/lockmanager/LockManager.php
includes/filerepo/file/File.php
includes/filerepo/file/LocalFile.php
includes/filerepo/file/OldLocalFile.php
includes/installer/i18n/az.json
includes/installer/i18n/cy.json
includes/installer/i18n/nap.json
includes/installer/i18n/tr.json
includes/jobqueue/JobQueue.php
includes/jobqueue/JobQueueGroup.php
includes/jobqueue/JobRunner.php
includes/jobqueue/aggregator/JobQueueAggregator.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/Bitmap.php
includes/media/DjVu.php
includes/media/DjVuImage.php
includes/media/FormatMetadata.php
includes/media/Jpeg.php
includes/media/SVG.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/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/SpecialJavaScriptTest.php
includes/specials/SpecialListusers.php
includes/specials/SpecialMergeHistory.php
includes/specials/SpecialProtectedtitles.php
includes/specials/SpecialSearch.php
includes/specials/SpecialVersion.php
includes/upload/UploadBase.php
includes/utils/IP.php
includes/utils/MWCryptRand.php
includes/utils/StringUtils.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/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/et.json
languages/i18n/fa.json
languages/i18n/fr.json
languages/i18n/gl.json
languages/i18n/he.json
languages/i18n/hu.json
languages/i18n/it.json
languages/i18n/ka.json
languages/i18n/ko.json
languages/i18n/lb.json
languages/i18n/mk.json
languages/i18n/nap.json
languages/i18n/nb.json
languages/i18n/nn.json
languages/i18n/pms.json
languages/i18n/pt.json
languages/i18n/ro.json
languages/i18n/scn.json
languages/i18n/si.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/zh-hans.json
languages/i18n/zh-hant.json
load.php
maintenance/convertExtensionToRegistration.php [new file with mode: 0644]
maintenance/doMaintenance.php
maintenance/eval.php
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/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/api/ApiMainTest.php
tests/phpunit/includes/api/query/ApiQueryTest.php
tests/phpunit/includes/libs/JavaScriptMinifierTest.php
tests/phpunit/includes/normal/CleanUpTest.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/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 8ca6ebf..6ba8bfa 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
@@ -75,6 +78,7 @@ 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.
 
 ==== External libraries ====
 * MediaWiki now requires certain external libraries to be installed. In the past
@@ -172,6 +176,10 @@ production.
   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 f2b0554..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',
@@ -374,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',
@@ -846,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',
@@ -888,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',
@@ -1265,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..4717aa9 100644 (file)
                "wiki": "https://www.mediawiki.org/"
        },
        "require": {
+               "cssjanus/cssjanus": "1.1.1",
                "leafo/lessphp": "0.5.0",
+               "oojs/oojs-ui": "0.6.1",
                "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 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..4d23ed2 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;
        }
 
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)
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 403566e..f516759 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
@@ -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 2bc36b1..10c6804 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;
        }
 
@@ -1515,7 +1498,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 +1556,6 @@ class Linker {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -1997,7 +1978,6 @@ class Linker {
                $section = false, $more = null
        ) {
                global $wgLang;
-               wfProfileIn( __METHOD__ );
 
                $outText = '';
                if ( count( $templates ) > 0 ) {
@@ -2077,7 +2057,6 @@ class Linker {
 
                        $outText .= '</ul>';
                }
-               wfProfileOut( __METHOD__ );
                return $outText;
        }
 
@@ -2089,7 +2068,6 @@ class Linker {
         * @return string HTML output
         */
        public static function formatHiddenCategories( $hiddencats ) {
-               wfProfileIn( __METHOD__ );
 
                $outText = '';
                if ( count( $hiddencats ) > 0 ) {
@@ -2106,7 +2084,6 @@ class Linker {
                        }
                        $outText .= '</ul>';
                }
-               wfProfileOut( __METHOD__ );
                return $outText;
        }
 
@@ -2135,7 +2112,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 +2140,6 @@ class Linker {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                return $tooltip;
        }
 
@@ -2184,7 +2159,6 @@ class Linker {
                if ( isset( self::$accesskeycache[$name] ) ) {
                        return self::$accesskeycache[$name];
                }
-               wfProfileIn( __METHOD__ );
 
                $message = wfMessage( "accesskey-$name" );
 
@@ -2200,7 +2174,6 @@ class Linker {
                        }
                }
 
-               wfProfileOut( __METHOD__ );
                self::$accesskeycache[$name] = $accesskey;
                return self::$accesskeycache[$name];
        }
@@ -2308,7 +2281,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 +2289,6 @@ class Linker {
 
                $ret = self::link( $nt, "$prefix$text$inside", array(), $query ) . $trail;
 
-               wfProfileOut( __METHOD__ );
                return $ret;
        }
 
@@ -2342,8 +2313,6 @@ class Linker {
        ) {
                wfDeprecated( __METHOD__, '1.21' );
 
-               wfProfileIn( __METHOD__ );
-
                if ( $text == '' ) {
                        $text = self::linkText( $title );
                }
@@ -2357,7 +2326,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 c7147cb..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;
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 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 938f6c0..4d181d6 100644 (file)
@@ -333,7 +333,14 @@ 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 ParserOtput::__sleep).
+               // The first data update returned by getSecondaryDataUpdates() is always a LinksUpdate
+               // instance generated on the fly, so it can be ignored in this context.
+               $hasCustomDataUpdates = count( $parserOutput->getSecondaryDataUpdates() ) > 1;
+
+               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 5fa8de0..c454531 100644 (file)
@@ -41,5 +41,7 @@
        "apihelp-compare-param-torev": "Другая вэрсія для параўнаньня.",
        "apihelp-compare-example-1": "Паказвае розьніцу паміж вэрсіямі 1 і 2",
        "apihelp-createaccount-description": "Стварэньне новага рахунку ўдзельніка.",
-       "apihelp-createaccount-param-name": "Імя ўдзельніка."
+       "apihelp-createaccount-param-name": "Імя ўдзельніка.",
+       "apihelp-createaccount-param-password": "Пароль (ігнаруецца, калі выстаўлена $1mailpassword).",
+       "apihelp-createaccount-param-domain": "Дамэн для вонкавай аўтэнтыфікацыі (неабавязкова)."
 }
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 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..2720933 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 {
@@ -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 {
@@ -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 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 a0e7f99..89ccd0b 100644 (file)
@@ -361,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 ) );
@@ -399,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 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..93c53ad 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;
                }
@@ -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 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..4fde124 100644 (file)
@@ -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 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..6d60012 100644 (file)
@@ -998,7 +998,6 @@ abstract class File {
        function transform( $params, $flags = 0 ) {
                global $wgThumbnailEpoch;
 
-               wfProfileIn( __METHOD__ );
                do {
                        if ( !$this->canRender() ) {
                                $thumb = $this->iconThumb();
@@ -1071,8 +1070,6 @@ abstract class File {
                        }
                } while ( false );
 
-               wfProfileOut( __METHOD__ );
-
                return is_object( $thumb ) ? $thumb : false;
        }
 
@@ -1102,9 +1099,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 94ef306..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,7 +1377,6 @@ 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
@@ -1473,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' );
@@ -1497,8 +1461,6 @@ class LocalFile extends File {
                        LinksUpdate::queueRecursiveJobsForTable( $this->getTitle(), 'imagelinks' );
                }
 
-               wfProfileOut( __METHOD__ );
-
                return true;
        }
 
@@ -2243,7 +2205,6 @@ class LocalFileDeleteBatch {
         * @return FileRepoStatus
         */
        function execute() {
-               wfProfileIn( __METHOD__ );
 
                $this->file->lock();
 
@@ -2292,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;
                }
@@ -2302,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 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 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 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..1f99b1e 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 {
@@ -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..ce3b3ff 100644 (file)
@@ -129,7 +129,6 @@ class JobRunner {
                                $this->runJobsLog( $job->toString() . " STARTING" );
 
                                // Run the job...
-                               wfProfileIn( __METHOD__ . '-' . get_class( $job ) );
                                $jobStartTime = microtime( true );
                                try {
                                        ++$jobsRun;
@@ -143,7 +142,6 @@ class JobRunner {
                                        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 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 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 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..810b9af 100644 (file)
@@ -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..3e8d9e5 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 );
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..5a09e65 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;
        }
 
index dcebe54..fa54f7c 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;
                                        }
 
@@ -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;
                                }
 
@@ -2018,7 +1982,6 @@ class WikiPage implements Page, IDBAccessObject {
                        $user->addAutopromoteOnceGroups( 'onEdit' );
                } );
 
-               wfProfileOut( __METHOD__ );
                return $status;
        }
 
@@ -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..7703c4b 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'] ) ) {
@@ -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..f155312 100644 (file)
@@ -53,7 +53,7 @@ class ParserOutput extends CacheTime {
                $mTOCEnabled = true;          # Whether TOC should be shown, can't override __NOTOC__
        private $mIndexPolicy = '';       # 'index' or 'noindex'?  Any other value will result in no change.
        private $mAccessedOptions = array(); # List of ParserOptions (stored in the keys)
-       private $mSecondaryDataUpdates = array(); # List of DataUpdate, used to save info from the page somewhere else.
+       private $mSecondaryDataUpdates = null; # List of DataUpdate, used to save info from the page somewhere else.
        private $mExtensionData = array(); # extra data used by extensions
        private $mLimitReportData = array(); # Parser limit report data
        private $mParseStartTime = array(); # Timestamps for getTimeSinceStart()
@@ -70,10 +70,11 @@ class ParserOutput extends CacheTime {
                $this->mCategories = $categoryLinks;
                $this->mContainsOldMagic = $containsOldMagic;
                $this->mTitleText = $titletext;
+
+               $this->mSecondaryDataUpdates = array();
        }
 
        public function getText() {
-               wfProfileIn( __METHOD__ );
                $text = $this->mText;
                if ( $this->mEditSectionTokens ) {
                        $text = preg_replace_callback(
@@ -111,7 +112,6 @@ class ParserOutput extends CacheTime {
                                $text
                        );
                }
-               wfProfileOut( __METHOD__ );
                return $text;
        }
 
@@ -704,6 +704,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 +714,15 @@ class ParserOutput extends CacheTime {
                        $title = Title::newFromText( $this->getTitleText() );
                }
 
+               if ( $this->mSecondaryDataUpdates === null ) {
+                       //NOTE: This happens when mSecondaryDataUpdates are lost during serialization
+                       // (see __sleep below). After (un)serialization, getSecondaryDataUpdates()
+                       // has no defined behavior, 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 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 ff63243..0caf6b4 100644 (file)
@@ -115,10 +115,16 @@ 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
                );
        }
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..c96fd14 100644 (file)
@@ -954,7 +954,6 @@ class ContribsPager extends ReverseChronologicalPager {
         * @return string
         */
        function formatRow( $row ) {
-               wfProfileIn( __METHOD__ );
 
                $ret = '';
                $classes = array();
@@ -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 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 28e980c..56c4eb5 100644 (file)
@@ -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 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 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 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 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 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 742364f..73d5d6f 100644 (file)
@@ -5,8 +5,8 @@
                ]
        },
        "tog-underline": "कड़ि अधोरेखन:",
-       "tog-hideminor": "हाल कय बदलावमें छोट बदलाव लुकुआवा जाय",
-       "tog-hidepatrolled": "हाल कय बदलावमें परीक्षित बदलाव लुकुआवा जाय",
+       "tog-hideminor": "à¤\85बहिन कय बदलावमें छोट बदलाव लुकुआवा जाय",
+       "tog-hidepatrolled": "à¤\85बहिन कय बदलावमें परीक्षित बदलाव लुकुआवा जाय",
        "tog-newpageshidepatrolled": "नवा पन्नन कय सूची में परीक्षित पन्ना लुकुआवा जाय",
        "tog-extendwatchlist": "खाली हालिए कय नाहीं, बल्कि कुल बदलाव कय देखावे कय लिए ध्यानसूची कय विस्तारित करा जाय",
        "tog-usenewrc": "अभिन कय बदलाव मे अउर ध्यानसूची में बदलाव कय पन्ना कय अनुसार समूह में बाँटा जाय",
        "redirectpagesub": "पुनर्निर्देश पन्ना",
        "redirectto": "पुनर्निर्देश करो:",
        "lastmodifiedat": "इ पन्ना कय पिछला बदलाव $1 कय $2 बजे भवा रहा।",
+       "viewcount": "ई पन्ना {{PLURAL:$1|एक|$1}} दाइँ देख़ गा है।",
        "protectedpage": "सुरक्षित पन्ना",
        "jumpto": "यहँ जावा जाय:",
        "jumptonavigation": "घुमाई",
        "nosuchaction": "अईसन कवनो काम नाई है",
        "nosuchactiontext": "इ यू॰आर॰एल से निर्दिष्ट काम अवैध है।\nआप यू॰आर॰एल गलत लिखा गा है, या कवनो गलत कड़ी कय प्रयोग करा गा है।\nई {{SITENAME}} कय सॉफ़्टवेयर में त्रुटि भी होई सकत है।",
        "nosuchspecialpage": "अईसन कौनो विशेष पन्ना नाई है",
+       "nospecialpagetext": "<strong>आप  अवैध विशेष पन्ना माँगा गा है।</strong>\nवैध विशेष पन्नन कय सूची [[Special:SpecialPages|{{int:specialpages}}]] पे देखी सका जात है।",
        "error": "त्रुटि",
        "databaseerror": "डाटाबेस त्रुटि",
        "databaseerror-text": "डाटाबेस अनुरोध त्रुटि हुई है।\nसंभवतः सॉफ़्टवेयर में गड़बड़ी है।",
        "viewsource": "स्रोत देखा जाय",
        "viewsource-title": "$1 कय लिए स्रोत देखा जाय",
        "actionthrottled": "काम खतम कई दिहा है",
+       "actionthrottledtext": "स्पैम कय रोकेक् लिये, इ काम एतना कम समय में एकठु सीमा से ढेर दाँइ करे कय मिनाही है, अव आप इ सीमा कय पार कई चुका गा है।\nकृपया कुछ समय बाद फिर से प्रयास करा जाय।",
        "protectedpagetext": "ई पन्ना संपादन अव अउर काम से सुरक्षित किहा है।",
        "viewsourcetext": "आप इ पन्ना कय स्रोत देखी सका जात है औ ओकर नकल उतार सका जात है:",
        "viewyourtext": "आप ई पन्ना में ''आपन सम्पादन'' कय स्रोत देखी सका जात है औ ओकर नकल उतार सका जात है:",
+       "protectedinterface": "इ पन्ना  विकी कय सॉफ़्टवेयर कय इंटरफ़ेस पाठ देत है,अव एकर गलत प्रयोग से बचावेक लिये सुरक्षित करा है।\nकुल विकिन् कय लिए अनुवाद जोड़य या बदलय कय लिए कृपया मीडियाविकि कय क्षेत्रीयकरण प्रकल्प [//translatewiki.net/ translatewiki.net] कय प्रयोग करा जाय।",
        "namespaceprotected": "आप कय '''$1''' नामस्थान में रहल पन्नन कय बदलै कय अनुमति नाइ है।",
        "customcssprotected": "आप कय इ CSS पन्ना कय संपादन करेक अनुमति नाई है, काहे से एहमा अउर सदस्य कय व्यक्तिगत सेटिंग्स शामिल है।",
        "customjsprotected": "आप कय इ जावास्क्रिप्ट पन्ना कय संपादन करेक अनुमति नाई है, काहे से एहमा अउर सदस्य कय व्यक्तिगत सेटिंग्स शामिल है।",
        "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 9302df6..97addac 100644 (file)
        "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 0adec37..79518cf 100644 (file)
        "javascripttest": "Тэставаньне JavaScript",
        "javascripttest-pagetext-noframework": "Гэтая старонка трымаецца для правядзеньня тэстаў JavaScript.",
        "javascripttest-pagetext-unknownframework": "Невядомая бібліятэка тэставаньня «$1».",
+       "javascripttest-pagetext-unknownaction": "Невядомае дзеяньне «$1».",
        "javascripttest-pagetext-frameworks": "Калі ласка, выберыце адну з прапанаваных бібліятэка тэставаньня: $1",
        "javascripttest-pagetext-skins": "Выберыце афармленьне для тэставаньня:",
        "javascripttest-qunit-intro": "Глядзіце [$1 дакумэнтацыю па тэставаньні] на mediawiki.org.",
index a0698db..9ab7220 100644 (file)
        "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|излезете]] и да влезете отново.'''",
        "movepagetalktext": "Ако съществува, съответната дискусионна страница ще бъде преместена автоматично заедно с нея, '''освен ако:'''\n* не местите страницата от едно именно пространство в друго,\n* вече съществува непразна дискусионна страница с това име или\n* не сте отметнали долната кутийка.\n\nВ тези случаи, ако желаете, ще е необходимо да преместите страницата ръчно.",
        "movearticle": "Преместване на страница:",
        "moveuserpage-warning": "'''Внимание:''' Предприели сте опит да преместите потребителска страница. Забележете, че от преместването на страницата '''няма''' да последва преименуване на потребителя.",
+       "movecategorypage-warning": "<strong>Внимание:</strong> На път сте да преместите категорийна страница. Моля, обърнете внимание, че ще бъде преместена само страницата на категорията. <em>Никоя</em> от страниците в старата категория <em>няма</em> да бъде прекатегоризирана.",
        "movenologintext": "Необходимо е да [[Special:UserLogin|влезете]], за да може да премествате страници.",
        "movenotallowed": "Нямате права за преместване на страници.",
        "movenotallowedfile": "Нямате права да премествате файлове.",
index efb7d71..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": "সাম্প্রতিক পরিবর্তনের পছন্দসমূহ",
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 fc6dd51..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-агӀо тая, иза кхечу декъашхочун гӀерс болу дера.",
index 05ccb38..ae6e5ef 100644 (file)
        "javascripttest": "Testování JavaScriptu",
        "javascripttest-pagetext-noframework": "Tato stránka je vyhrazena pro spouštění testů JavaScriptu.",
        "javascripttest-pagetext-unknownframework": "Neznámá testovací knihovna „$1“.",
+       "javascripttest-pagetext-unknownaction": "Neznámá akce „$1“.",
        "javascripttest-pagetext-frameworks": "Zvolte jednu z následujících testovacích knihoven: $1",
        "javascripttest-pagetext-skins": "Zvolte vzhled, pod kterým se mají testy spustit:",
        "javascripttest-qunit-intro": "Vizte [$1 dokumentaci testování] na mediawiki.org",
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 1870cde..c8508de 100644 (file)
        "javascripttest": "JavaScript-Test",
        "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",
        "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 0d162be..3338695 100644 (file)
        "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",
        "nchanges": "$1\n{{PLURAL:$1|mudéfica|mudéfichi}}",
        "recentchanges": "Ûltmi mudéfichi",
        "recentchanges-legend": "Siēlti ûltmi mudéfichi.",
        "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 5dd5ec3..0756359 100644 (file)
        "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 d094ad0..6800d03 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": "فرونشانی اطلاعات برای مدیران به همراه دیگران",
        "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 524de3b..2cb55bf 100644 (file)
        "javascripttest": "Test de JavaScript",
        "javascripttest-pagetext-noframework": "Cette page est réservée pour l'exécution des tests JavaScript.",
        "javascripttest-pagetext-unknownframework": "Structure « $1 » inconnue.",
+       "javascripttest-pagetext-unknownaction": "Action « $1 » inconnue.",
        "javascripttest-pagetext-frameworks": "Veuillez choisir l'une des structures de test suivantes : $1",
        "javascripttest-pagetext-skins": "Choisissez un habillage avec lequel lancer les tests :",
        "javascripttest-qunit-intro": "Voir [$1 la documentation de test] sur mediawiki.org.",
index 4099486..83c119c 100644 (file)
        "javascripttest": "Proba de JavaScript",
        "javascripttest-pagetext-noframework": "Esta páxina está reservada para executar probas do JavaScript.",
        "javascripttest-pagetext-unknownframework": "Descoñécese a infraestrutura dixital \"$1\" de probas.",
+       "javascripttest-pagetext-unknownaction": "Acción descoñecida \"$1\".",
        "javascripttest-pagetext-frameworks": "Seleccione unha das seguintes infraestruturas dixitais de probas: $1",
        "javascripttest-pagetext-skins": "Escolla a aparencia na que executar as probas:",
        "javascripttest-qunit-intro": "Bótelle unha ollada á [$1 documentación das probas] en mediawiki.org.",
index 8d0492e..60d74f3 100644 (file)
        "javascripttest": "בדיקת JavaScript",
        "javascripttest-pagetext-noframework": "דף זה שמור להרצת בדיקות JavaScript.",
        "javascripttest-pagetext-unknownframework": "סביבת הבדיקות \"$1\" אינה ידועה.",
+       "javascripttest-pagetext-unknownaction": "הפעולה \"$1\" אינה ידועה.",
        "javascripttest-pagetext-frameworks": "נא לבחור אחת מסביבות הבדיקות הבאות: $1",
        "javascripttest-pagetext-skins": "בחירת עיצוב שאיתו יורצו הבדיקות:",
        "javascripttest-qunit-intro": "ראו את [$1 תיעוד הבדיקות] באתר mediawiki.org.",
index 65bca7c..56049be 100644 (file)
        "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 9a17c9e..957d3ad 100644 (file)
        "javascripttest": "Sperimentazione JavaScript",
        "javascripttest-pagetext-noframework": "Questa pagina è riservata all'esecuzione di test di JavaScript.",
        "javascripttest-pagetext-unknownframework": "Framework di test sconosciuto \"$1\".",
+       "javascripttest-pagetext-unknownaction": "Azione sconosciuta \"$1\".",
        "javascripttest-pagetext-frameworks": "Per cortesia, scegli uno dei seguenti framework per i test: $1",
        "javascripttest-pagetext-skins": "Scegli una skin con cui eseguire i test:",
        "javascripttest-qunit-intro": "Vedi su mediawiki.org la [$1 documentazione riguardante i test].",
index c1c2ed7..1880c71 100644 (file)
        "javascripttest": "JavaScript-ის ტესტირება",
        "javascripttest-pagetext-noframework": "ეს გვერდი დარეგისტრირებულია JavaScript-ის ტესტების გასაშვებად.",
        "javascripttest-pagetext-unknownframework": "„$1-ის“ ტესტირების უცნობი გარემო.",
+       "javascripttest-pagetext-unknownaction": "უცნობი ქმედება „$1“.",
        "javascripttest-pagetext-frameworks": "გთხოვთ, აირჩიეთ ტესტირების ერთ-ერთი შემდეგი გარემო: $1",
        "javascripttest-pagetext-skins": "ტესტების გასაშვებად აირჩიეთ გაფორმების თემა:",
        "javascripttest-qunit-intro": "იხილეთ [$1 ტესტირების დოკუმენტები] mediawiki.org-ზე.",
index addafbf..2f14433 100644 (file)
        "protectedpages-timestamp": "시간 기록",
        "protectedpages-page": "문서",
        "protectedpages-expiry": "만료 기한",
-       "protectedpages-performer": "사용자를 보호",
+       "protectedpages-performer": "보호한 사용자",
        "protectedpages-params": "보호 변수",
        "protectedpages-reason": "이유",
        "protectedpages-unknown-timestamp": "알 수 없음",
        "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 9ddbefc..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",
index 6a94685..635177d 100644 (file)
        "javascripttest": "Проба на JavaScript",
        "javascripttest-pagetext-noframework": "Оваа страница е резервирана за вршење на проби со JavaScript.",
        "javascripttest-pagetext-unknownframework": "Непозната рамка „$1“.",
+       "javascripttest-pagetext-unknownaction": "Непознато дејство „$1“.",
        "javascripttest-pagetext-frameworks": "Изберете една од следниве рамки: $1",
        "javascripttest-pagetext-skins": "Одберете со кое руво да ја направите пробата:",
        "javascripttest-qunit-intro": "Вид. [$1 документација на испробувањето] на mediawiki.org.",
index 9c7fda4..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.",
        "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 f0a85d8..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.",
index 3acacab..3c63b4d 100644 (file)
        "javascripttest": "JavaScript-utrøyning",
        "javascripttest-pagetext-noframework": "Sida er reservert for køyring av JavaScript-utrøyningar.",
        "javascripttest-pagetext-unknownframework": "Ukjent utrøyningsrammeverk: «$1».",
+       "javascripttest-pagetext-unknownaction": "Ukjend handling \"$1\".",
        "javascripttest-pagetext-frameworks": "Vel eitt av dei fylgjande utrøyningsrammeverka: $1",
        "javascripttest-pagetext-skins": "Vel ei drakt som utrøyningane skal køyrast med:",
        "javascripttest-qunit-intro": "Sjå [$1 utrøyningsdokumentasjon] på mediawiki.org.",
index 86b55c4..f680753 100644 (file)
        "javascripttest": "Preuva ëd JavaScript",
        "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.",
index 047132b..b5540e0 100644 (file)
        "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 que contém o modelo de chamadas 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>.",
+       "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.",
        "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 maiores do que <span class=\"notranslate\" converter=\"não\">$1</span>",
+       "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",
        "javascripttest": "Teste de JavaScript",
        "javascripttest-pagetext-noframework": "Esta página é reservada para a execução de testes de JavaScript.",
        "javascripttest-pagetext-unknownframework": "Estrutura de testes \"$1\" desconhecida.",
+       "javascripttest-pagetext-unknownaction": "Ação \"$1\" desconhecida.",
        "javascripttest-pagetext-frameworks": "Escolha, por favor, uma das seguintes estruturas de teste: $1",
        "javascripttest-pagetext-skins": "Escolher um tema para executar os testes com:",
        "javascripttest-qunit-intro": "Consulte a [ $1 documentação de testes] no mediawiki.org.",
        "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> Página de estados de indicadores' <code>nome</code> atributo não deve estar vazia.",
+       "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",
        "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>Porque {{SITENAME}} foi matérias HTML ativado e houve uma perda de dados de sessão, a visualização é escondida como uma precaução contra os ataques do JavaScrips.</em>\n\n<strong>Se esta é uma legítima tentativa de visualização, por favor, tente novamente.</strong>\nSe ainda assim não funcionar, tente [[Special:UserLogout|sair]] e voltar a fazer o login.",
-       "expand_templates_preview_fail_html_anon": "<em>Porque {{SITENAME}} foi matérias HTML ativado e você não estiver ligado, a pré-visualização é escondida como uma precaução contra os ataques do JavaScript.</em>\n\n<strong>Se esta é uma legítima tentativa de visualização, por favor [[Especial:UserLogin|login]] e tente novamente.</strong>",
+       "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 f75fc76..447aa72 100644 (file)
        "javascripttest": "Testare JavaScript",
        "javascripttest-pagetext-noframework": "Această pagină este rezervată rulării testelor JavaScript.",
        "javascripttest-pagetext-unknownframework": "Cadru de testare „$1” necunoscut.",
+       "javascripttest-pagetext-unknownaction": "Acțiunea „$1” necunoscută.",
        "javascripttest-pagetext-frameworks": "Alegeți unul din următoarele cadre de testare: $1",
        "javascripttest-pagetext-skins": "Alegeți un aspect pentru care să rulați teste:",
        "javascripttest-qunit-intro": "A se vedea [$1 documentația de testare] pe mediawiki.org.",
index 21aac25..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.",
        "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.",
        "tooltip-pt-userpage": "La tò pàggina utenti",
        "tooltip-pt-anonuserpage": "La pàggina utenti di stu ndirizzu IP",
        "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 014dc40..ced5aca 100644 (file)
        "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": "දෝෂය: ආකෘති-පත්‍රය ඉදිරිපත් කල නොහැකි විය",
        "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": "ඇලකුරු පෙළ",
        "action-createpage": "පිටු තනන්න",
        "action-createtalk": "සංවාද පිටු තනන්න",
        "action-createaccount": "මෙම පරිශීලක ගිණුම තනන්න",
-       "action-history": "මà·\99ම à¶´à·\92ටà·\94à·\80à·\9a à¶\89තà·\92à·\84à·\8fà·\83ය පෙන්වන්න",
+       "action-history": "මà·\99ම à¶´à·\92ටà·\94à·\80à·\9a à¶\85තà·\93තය පෙන්වන්න",
        "action-minoredit": "මෙම සංස්කරණය සුළු ලෙස සලකුණු කරන්න",
        "action-move": "මෙම පිටුව ගෙනයන්න",
        "action-move-subpages": "මෙම පිටුව හා එහි උප පිටු ගෙන යන්න",
index 3fbb3c2..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": "Изгледа да је измена већ поништена.",
index 6e56d8a..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",
        "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 f60ce1a..b076ebf 100644 (file)
        "javascripttest": "JavaScript-testning",
        "javascripttest-pagetext-noframework": "Denna sida är reserverat för att köra JavaScript-tester.",
        "javascripttest-pagetext-unknownframework": "Okänd testmiljö \"$1\".",
+       "javascripttest-pagetext-unknownaction": "Okänd handling \"$1\".",
        "javascripttest-pagetext-frameworks": "Välj en av följande testmiljöer: $1",
        "javascripttest-pagetext-skins": "Välj ett utseende att köra tester med:",
        "javascripttest-qunit-intro": "Se [$1 testningsdokumentationen] på mediawiki.org.",
index df95da8..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",
        "javascripttest": "JavaScript denemesi",
        "javascripttest-pagetext-noframework": "Bu sayfa JavaScript testleri çalıştırmak için ayrılmıştır.",
        "javascripttest-pagetext-unknownframework": "Bilinmeyen test çerçevesi \"$1\".",
+       "javascripttest-pagetext-unknownaction": "Bilinmeyen eylem \"$1\".",
        "javascripttest-pagetext-frameworks": "Lütfen aşağıdaki test çerçevelerinden birini seçin: $1",
        "javascripttest-pagetext-skins": "Testleri koşmak için bir tema seçin:",
        "javascripttest-qunit-intro": "mediawiki.org üzerinden [$1 deneme belgelerine] bakınız.",
        "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 58fbf98..b8dc5e7 100644 (file)
        "javascripttest": "JavaScript测试",
        "javascripttest-pagetext-noframework": "本页面被保留进行JavaScript测试。",
        "javascripttest-pagetext-unknownframework": "未知的框架“$1”。",
+       "javascripttest-pagetext-unknownaction": "未知操作“$1”。",
        "javascripttest-pagetext-frameworks": "请选择以下的框架之一:$1",
        "javascripttest-pagetext-skins": "选择外观来运行测试:",
        "javascripttest-qunit-intro": "请见mediawiki.org的[$1 测试说明文件]。",
        "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 9354b40..2c86dac 100644 (file)
        "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 引用",
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.
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 e4380a7..6616057 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" ) ) {
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' )
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 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 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 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
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' );
        }
 
 }
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