Merge "Run structure tests on extensions"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 18 Dec 2014 09:14:14 +0000 (09:14 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 18 Dec 2014 09:14:14 +0000 (09:14 +0000)
63 files changed:
HISTORY
autoload.php
docs/hooks.txt
docs/skin.txt
includes/GlobalFunctions.php
includes/Html.php
includes/OutputPage.php
includes/User.php
includes/WikiMap.php
includes/api/ApiMain.php
includes/api/i18n/en.json
includes/api/i18n/ja.json
includes/api/i18n/zh-hans.json
includes/content/JsonContent.php
includes/db/IORMTable.php
includes/db/ORMTable.php
includes/debug/logger/Logger.php
includes/debug/logger/legacy/Logger.php
includes/debug/logger/monolog/LegacyFormatter.php
includes/diff/DairikiDiff.php
includes/filebackend/FileBackendStore.php
includes/installer/DatabaseUpdater.php
includes/installer/i18n/diq.json
includes/jobqueue/JobQueueDB.php
includes/jobqueue/jobs/HTMLCacheUpdateJob.php
includes/jobqueue/jobs/RefreshLinksJob.php
includes/libs/RunningStat.php
includes/libs/ScopedCallback.php
includes/normal/README
includes/page/ImagePage.php
includes/page/WikiPage.php
includes/parser/CoreParserFunctions.php
includes/parser/ParserOutput.php
includes/profiler/ProfilerStub.php
includes/profiler/ProfilerXhprof.php
includes/profiler/SectionProfiler.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/revisiondelete/RevisionDeleter.php
includes/specials/SpecialMostimages.php
languages/i18n/be-tarask.json
languages/i18n/bs.json
languages/i18n/diq.json
languages/i18n/egl.json
languages/i18n/en.json
languages/i18n/fa.json
languages/i18n/it.json
languages/i18n/ja.json
languages/i18n/kk-cyrl.json
languages/i18n/pl.json
languages/i18n/pt.json
languages/i18n/qqq.json
maintenance/Maintenance.php
maintenance/fetchText.php
maintenance/populateParentId.php
resources/assets/file-type-icons/COPYING
resources/src/jquery/jquery.makeCollapsible.js
resources/src/jquery/jquery.tablesorter.js
resources/src/mediawiki.toolbar/toolbar.js
resources/src/mediawiki/mediawiki.content.json.css
resources/src/mediawiki/mediawiki.js
tests/phpunit/includes/OutputPageTest.php
tests/phpunit/includes/content/JsonContentTest.php
thumb.php

diff --git a/HISTORY b/HISTORY
index 4343c5d..e5864fd 100644 (file)
--- a/HISTORY
+++ b/HISTORY
@@ -809,7 +809,7 @@ of files that are no longer available follows.
 * HTMLForm 'select', 'selectandother', 'selectorother', 'multiselect', and
   'radio' fields can now use message keys as labels via the 'options-messages'
   parameter, which overrides the 'options' parameter.
-* Admins can expire users users passwords manually, or on a schedule using the
+* Admins can expire users passwords manually, or on a schedule using the
   $wgPasswordExpirationDays configuration setting.
 * Add new hook SendWatchlistEmailNotification, this will be used to determine
   whether to send a watchlist email notification.
@@ -1899,7 +1899,7 @@ This is a maintenance release of the MediaWiki 1.21 branch.
 
 === New features in 1.21 ===
 * (bug 38110) Schema changes (adding or dropping tables, indices and
-  fields) can be now be done separately from from other changes that
+  fields) can be now be done separately from other changes that
   update.php makes.  This is useful in environments that use database
   permissions to restrict schema changes but allow the DB user that
   MediaWiki normally runs as to perform other changes that update.php
@@ -4300,7 +4300,7 @@ Selected changes since MediaWiki 1.16 that may be of interest:
 * (bug 20186) Allow filtering Special:Contributions for RevisionDeleted edits.
 * ajaxwatch now uses the API and JQuery, and can be used to animate arbitrary
   watch links, not just to watch the page the link is on.
-* (bug 20976) "searchmenu-new-nocreate" message now displayed when when there
+* (bug 20976) "searchmenu-new-nocreate" message now displayed when there
   is no title match in search and the user has no rights to create pages.
 * (bug 23429) Added new hook WatchlistEditorBuildRemoveLine.
 * (bug 22844) Added support for WinCache object caching (for IIS).
@@ -5270,7 +5270,7 @@ comment from another wiki.
 ** Note that this change will break some extensions which have not been adapted
    for it.
 * (bug 17020) Adding fallback encodings for Traditional and Simplified Chinese
-  languages while the the text is typed as URLs.
+  languages while the text is typed as URLs.
 * (bug 17614) Prev / Next links are not shown if all results are shown
 * (bug 18207) Strange spacing before [[irc:...]] links
 * Removed float from the user login form in RTL interface - caused display
@@ -5441,7 +5441,7 @@ comment from another wiki.
   enabled
 * (bug 19857) maintenance/deleteRevision.php on last revision no longer breaks
   target page
-* (bug 20365) Page name with with c/g/h/j/s/u + x are now correctly handled in
+* (bug 20365) Page name with c/g/h/j/s/u + x are now correctly handled in
   Special:MovePage with Esperanto as content language
 * (bug 20364) Fixed regression in GIF metadata loading
 * (bug 20299) MediaWiki:Move-subpages and MediaWiki:Move-talk-subpages can now
@@ -5451,7 +5451,7 @@ comment from another wiki.
 * (bug 19966) MediaWiki:License-header is now used for the licensing header in
   the file description page instead of MediaWiki:License
 * (bug 20380) Links to history/deleted edits at the top of
-  Special:RevisionDelete are no more displayed when when doing log suppression
+  Special:RevisionDelete are no more displayed when doing log suppression
 * (bug 8143) Localised parser function names are now correctly case insensitive
   if they contain non-ASCII characters
 * (bug 19055) maintenance/rebuildrecentchanges.php now purges
@@ -6236,7 +6236,7 @@ The following extensions are migrated into MediaWiki 1.14:
 * Extensions can use the SkinBuildSidebar hook to modify the content of the
   sidebar and add custom portlets to it
 * Added 'MakeGlobalVariablesScript' hook for extensions to be able to add vari-
-  ables into into the output of Skin::makeVariablesScript
+  ables into the output of Skin::makeVariablesScript
 * (bug 13846) Added $wgAddGroups and $wgRemoveGroups display on
   Special:ListGroupRights
 * (bug 14377) Add a date selector to history pages
@@ -9840,7 +9840,7 @@ they will be run along with the main tests by maintenance/parserTests.php
 * Fix formatting of titles on Special:Undelete
 * (bug 7026) Fix action=raw&templates=expand
 * (bug 6976) Add namespace and direction classes to classic skins
-* (bug 7144) Don't "return to main" from OutputPage::loginToUse() if the the user can't
+* (bug 7144) Don't "return to main" from OutputPage::loginToUse() if the user can't
   read the main page in the first place
 * (bug 7188) Fix minor borkage in HTMLForm
 * (bug 6675) Replaced message 'watchthis' with new message 'watchthisupload in Special:Upload
index fd2781c..d4a152a 100644 (file)
@@ -1018,6 +1018,7 @@ $wgAutoloadLocalClasses = array(
        'SearchResultSet' => __DIR__ . '/includes/search/SearchResultSet.php',
        'SearchSqlite' => __DIR__ . '/includes/search/SearchSqlite.php',
        'SearchUpdate' => __DIR__ . '/includes/deferred/SearchUpdate.php',
+       'SectionProfileCallback' => __DIR__ . '/includes/profiler/SectionProfiler.php',
        'SectionProfiler' => __DIR__ . '/includes/profiler/SectionProfiler.php',
        'SevenZipStream' => __DIR__ . '/maintenance/7zip.inc',
        'ShiConverter' => __DIR__ . '/languages/classes/LanguageShi.php',
index 369ad9f..f83a6c3 100644 (file)
@@ -1461,7 +1461,7 @@ $page: ImagePage object
 'ImgAuthBeforeStream': executed before file is streamed to user, but only when
 using img_auth.php.
 &$title: the Title object of the file as it would appear for the upload page
-&$path: the original file and path name when img_auth was invoked by the the web
+&$path: the original file and path name when img_auth was invoked by the web
   server
 &$name: the name only component of the file
 &$result: The location to pass back results of the hook routine (only used if
index e998ebd..a3c8c33 100644 (file)
@@ -7,7 +7,7 @@ MediaWiki includes four core skins:
   Monobook.
 
 * Monobook: Named after the black-and-white photo of a book in the page
-  background. Introduced in the 2004 release of 1.3, it had been been the
+  background. Introduced in the 2004 release of 1.3, it had been the
   default skin since then, before being replaced by Vector.
 
 * Modern: An attractive blue/grey theme with sidebar and top bar. Derived from
index 1dd6dc4..403566e 100644 (file)
@@ -1067,14 +1067,18 @@ function wfDebugMem( $exact = false ) {
 }
 
 /**
- * Send a line to a supplementary debug log file, if configured, or main debug log if not.
- * To configure a supplementary log file, set $wgDebugLogGroups[$logGroup] to a string
- * filename or an associative array mapping 'destination' to the desired filename. The
- * associative array may also contain a 'sample' key with an integer value, specifying
- * a sampling factor.
+ * Send a line to a supplementary debug log file, if configured, or main debug
+ * log if not.
+ *
+ * To configure a supplementary log file, set $wgDebugLogGroups[$logGroup] to
+ * a string filename or an associative array mapping 'destination' to the
+ * desired filename. The associative array may also contain a 'sample' key
+ * with an integer value, specifying a sampling factor. Sampled log events
+ * will be emitted with a 1 in N random chance.
  *
  * @since 1.23 support for sampling log messages via $wgDebugLogGroups.
  * @since 1.25 support for additional context data
+ * @since 1.25 sample behavior dependent on configured $wgMWLoggerDefaultSpi
  *
  * @param string $logGroup
  * @param string $text
@@ -1106,7 +1110,7 @@ function wfDebugLog(
 
        $logger = MWLogger::getInstance( $logGroup );
        $context['private'] = ( $dest === 'private' );
-       $logger->debug( $text, $context );
+       $logger->info( $text, $context );
 }
 
 /**
@@ -3893,7 +3897,7 @@ function wfBCP47( $code ) {
 /**
  * Get a cache object.
  *
- * @param int $inputType Cache type, one the the CACHE_* constants.
+ * @param int $inputType Cache type, one of the CACHE_* constants.
  * @return BagOStuff
  */
 function wfGetCache( $inputType ) {
index b3437d3..e033746 100644 (file)
@@ -893,7 +893,7 @@ class Html {
                                continue;
                        }
                        if ( $nsId === NS_MAIN ) {
-                               // For other namespaces use use the namespace prefix as label, but for
+                               // For other namespaces use the namespace prefix as label, but for
                                // main we don't use "" but the user message describing it (e.g. "(Main)" or "(Article)")
                                $nsName = wfMessage( 'blanknamespace' )->text();
                        } elseif ( is_int( $nsId ) ) {
index 24b9e46..411bb2e 100644 (file)
@@ -1075,7 +1075,7 @@ class OutputPage extends ContextSource {
        }
 
        /**
-        * Set the page as printable, i.e. it'll be displayed with with all
+        * Set the page as printable, i.e. it'll be displayed with all
         * print styles included
         */
        public function setPrintable() {
index bda825f..34af4c5 100644 (file)
@@ -2489,7 +2489,7 @@ class User implements IDBAccessObject {
                        $type = $oldaddr != '' ? 'changed' : 'set';
                        $result = $this->sendConfirmationMail( $type );
                        if ( $result->isGood() ) {
-                               // Say the the caller that a confirmation mail has been sent
+                               // Say to the caller that a confirmation mail has been sent
                                $result->value = 'eauth';
                        }
                } else {
index 34cd48d..f16f5aa 100644 (file)
@@ -161,7 +161,7 @@ class WikiReference {
        }
 
        /**
-        * Get the the URL in a way to de displayed to the user
+        * Get the URL in a way to be displayed to the user
         * More or less Wikimedia specific
         *
         * @return string
index 81353f6..c03e513 100644 (file)
@@ -575,7 +575,7 @@ class ApiMain extends ApiBase {
                        $wildcard
                );
 
-               return "/https?:\/\/$wildcard/";
+               return "/^https?:\/\/$wildcard$/";
        }
 
        protected function sendCacheHeaders() {
index 21b546c..52f7e33 100644 (file)
        "apihelp-query+revisions-example-last5": "Get last 5 revisions of the \"Main Page\"",
        "apihelp-query+revisions-example-first5": "Get first 5 revisions of the \"Main Page\"",
        "apihelp-query+revisions-example-first5-after": "Get first 5 revisions of the \"Main Page\" made after 2006-05-01",
-       "apihelp-query+revisions-example-first5-not-localhost": "Get first 5 revisions of the \"Main Page\" that were not made made by anonymous user \"127.0.0.1\"",
+       "apihelp-query+revisions-example-first5-not-localhost": "Get first 5 revisions of the \"Main Page\" that were not made by anonymous user \"127.0.0.1\"",
        "apihelp-query+revisions-example-first5-user": "Get first 5 revisions of the \"Main Page\" that were made by the user \"MediaWiki default\"",
 
        "apihelp-query+revisions+base-param-prop": "Which properties to get for each revision:\n;ids:The ID of the revision.\n;flags:Revision flags (minor).\n;timestamp:The timestamp of the revision.\n;user:User that made the revision.\n;userid:User ID of the revision creator.\n;size:Length (bytes) of the revision.\n;sha1:SHA-1 (base 16) of the revision.\n;contentmodel:Content model ID of the revision.\n;comment:Comment by the user for the revision.\n;parsedcomment:Parsed comment by the user for the revision.\n;content:Text of the revision.\n;tags:Tags for the revision.",
index a06db94..08f6ed5 100644 (file)
@@ -2,7 +2,8 @@
        "@metadata": {
                "authors": [
                        "Shirayuki",
-                       "2nd-player"
+                       "2nd-player",
+                       "Los688"
                ]
        },
        "apihelp-main-param-action": "実行する操作です。",
        "apihelp-main-param-curtimestamp": "現在のタイムスタンプを結果に含めます。",
        "apihelp-main-param-uselang": "メッセージの翻訳に使用する言語です。コードの一覧は [[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]] に siprop=languages を付けることで取得できます。\"user\" を指定することで現在の利用者の個人設定の言語を、\"content\" を指定することでこのウィキの本文の言語を使用することもできます。",
        "apihelp-block-description": "利用者をブロックします。",
+       "apihelp-block-param-reason": "ブロックの理由:",
        "apihelp-block-param-nocreate": "アカウントの作成を禁止します。",
        "apihelp-createaccount-description": "新しい利用者アカウントを作成します。",
+       "apihelp-createaccount-param-name": "利用者名:",
        "apihelp-createaccount-param-password": "パスワード ($1mailpassword が設定されると無視されます)。",
        "apihelp-createaccount-param-token": "最初のリクエストで得られたアカウント作成用トークンです。",
        "apihelp-createaccount-param-email": "利用者の電子メールアドレス (任意)。",
        "apihelp-edit-param-title": "編集するページ名です。$1pageid とは同時に使用できません。",
        "apihelp-edit-param-pageid": "編集するページIDです。$1title とは同時に使用できません。",
        "apihelp-edit-param-text": "ページの本文。",
+       "apihelp-edit-param-minor": "細部の編集",
        "apihelp-edit-param-createonly": "すでにそのページが存在する場合は編集を行いません。",
        "apihelp-edit-param-nocreate": "そのページが存在しない場合にエラーを返します。",
        "apihelp-edit-param-watch": "そのページをウォッチリストに追加します。",
        "apihelp-edit-param-unwatch": "そのページをウォッチリストから除去します。",
        "apihelp-edit-param-token": "このトークンは常に最後のパラメーターとして、または少なくとも $1text パラメーターより後に送信されるべきです。",
+       "apihelp-edit-example-edit": "ページを編集",
        "apihelp-emailuser-description": "利用者に電子メールを送信します。",
        "apihelp-emailuser-param-target": "送信先の利用者名。",
        "apihelp-emailuser-param-text": "電子メールの本文。",
@@ -53,6 +58,7 @@
        "apihelp-help-example-query": "2つの下位モジュールのヘルプ",
        "apihelp-login-param-name": "利用者名。",
        "apihelp-login-param-password": "パスワード。",
+       "apihelp-login-example-login": "ログイン",
        "apihelp-move-description": "ページを移動します。",
        "apihelp-move-param-from": "移動するページのページ名です。 $1fromid とは同時に使用できません。",
        "apihelp-move-param-fromid": "移動するページのページIDです。 $1from とは同時に使用できません。",
index 332a6e6..bb6b7f4 100644 (file)
        "apihelp-block-param-reason": "封禁的原因",
        "apihelp-block-param-anononly": "只封禁匿名用户(也就是说禁止此IP的匿名编辑)。",
        "apihelp-block-param-nocreate": "防止创建帐户。",
+       "apihelp-block-param-autoblock": "自动封禁最近使用的IP地址,以及以后他们尝试登陆使用的IP地址。",
        "apihelp-block-param-noemail": "阻止用户通过 wiki发送电子邮件。(要求\"blockemail\"权限)。",
        "apihelp-block-param-hidename": "从封禁日志中隐藏用户名。(需要“隐藏用户”权限)。",
        "apihelp-block-param-allowusertalk": "允许用户编辑自己的讨论页 (取决于 $wgBlockAllowsUTEdit)。",
        "apihelp-block-param-reblock": "如果该用户已被封禁,则覆盖已有的封禁。",
        "apihelp-block-param-watchuser": "监视该用户或该 IP 的用户页和讨论页。",
-       "apihelp-block-example-ip-simple": "封禁IP地址192.0.2.5三天,原因“首次罢工”",
+       "apihelp-block-example-ip-simple": "封禁IP地址192.0.2.5三天,原因“首次处理”",
+       "apihelp-block-example-user-complex": "无限期封禁破坏用户,原因“纯破坏用户”,并阻止新账户创建和电子邮件",
        "apihelp-clearhasmsg-description": "清除当前用户的 hasmsg 标志。",
        "apihelp-clearhasmsg-example-1": "清除当前用户的 hasmsg 标志",
        "apihelp-compare-description": "获取2个页面之间的差别。\n\n您必须为\"from\"和\"to\"传递特定的修订版本号、 页面标题或页面ID。",
@@ -60,7 +62,9 @@
        "apihelp-delete-param-pageid": "你所希望删除的页面的页面ID。不能与$1title一起使用。",
        "apihelp-delete-param-reason": "删除原因。如果未设置,将使用一个自动生成的原因。",
        "apihelp-delete-param-watch": "将该页面加入您的监视列表。",
+       "apihelp-delete-param-watchlist": "无条件地将页面加入至您的监视列表或将其移除,使用设置或不更改监视。",
        "apihelp-delete-param-unwatch": "将该页面从您的监视列表删除。",
+       "apihelp-delete-param-oldimage": "由[[Special:ApiHelp/query+imageinfo|action=query&prop=imageinfo&iiprop=archivename]]提供的要删除的旧图片名称。",
        "apihelp-delete-example-simple": "删除首页",
        "apihelp-delete-example-reason": "删除首页,原因“准备移动”",
        "apihelp-disabled-description": "此模块已禁用。",
index 1ce25c2..ff3b25b 100644 (file)
@@ -2,6 +2,8 @@
 /**
  * JSON Content Model
  *
+ * This class requires the root structure to be an object (not primitives or arrays).
+ *
  * @file
  *
  * @author Ori Livneh <ori@wikimedia.org>
  */
 class JsonContent extends TextContent {
 
-       public function __construct( $text, $modelId = CONTENT_MODEL_JSON ) {
-               parent::__construct( $text, $modelId );
+       /**
+        * @since 1.25
+        * @var Status
+        */
+       protected $jsonParse;
+
+       /**
+        * @param string $text JSON
+        */
+       public function __construct( $text ) {
+               parent::__construct( $text, CONTENT_MODEL_JSON );
        }
 
        /**
         * Decodes the JSON into a PHP associative array.
-        * @return array
+        *
+        * @deprecated since 1.25 Use getData instead.
+        * @return array|null
         */
        public function getJsonData() {
+               wfDeprecated( __METHOD__, '1.25' );
                return FormatJson::decode( $this->getNativeData(), true );
        }
 
        /**
-        * @return bool Whether content is valid JSON.
+        * Decodes the JSON string into a PHP object.
+        *
+        * @return Status
+        */
+       public function getData() {
+               if ( $this->jsonParse === null ) {
+                       $this->jsonParse = FormatJson::parse( $this->getNativeData() );
+               }
+               return $this->jsonParse;
+       }
+
+       /**
+        * @return bool Whether content is valid.
         */
        public function isValid() {
-               return $this->getJsonData() !== null;
+               return $this->getData()->isGood() && is_object( $this->getData()->getValue() );
        }
 
        /**
-        * Pretty-print JSON
+        * Pretty-print JSON.
+        *
+        * If called before validation, it may return JSON "null".
         *
-        * @return bool|null|string
+        * @return string
         */
        public function beautifyJSON() {
-               $decoded = $this->getJsonData();
-               if ( !is_array( $decoded ) ) {
-                       return null;
-               }
-               return FormatJson::encode( $decoded, true );
-
+               return FormatJson::encode( $this->getData()->getValue(), true );
        }
 
        /**
         * Beautifies JSON prior to save.
+        *
         * @param Title $title Title
         * @param User $user User
         * @param ParserOptions $popts
         * @return JsonContent
         */
        public function preSaveTransform( Title $title, User $user, ParserOptions $popts ) {
+               // FIXME: WikiPage::doEditContent invokes PST before validation. As such, native data
+               // may be invalid (though PST result is discarded later in that case).
+               if ( !$this->isValid() ) {
+                       return $this;
+               }
+
                return new static( $this->beautifyJSON() );
        }
 
        /**
-        * Set the HTML and add the appropriate styles
-        *
+        * Set the HTML and add the appropriate styles.
         *
         * @param Title $title
         * @param int $revId
@@ -71,50 +100,112 @@ class JsonContent extends TextContent {
        protected function fillParserOutput( Title $title, $revId,
                ParserOptions $options, $generateHtml, ParserOutput &$output
        ) {
-               if ( $generateHtml ) {
-                       $output->setText( $this->objectTable( $this->getJsonData() ) );
+               // FIXME: WikiPage::doEditContent generates parser output before validation.
+               // As such, native data may be invalid (though output is discarded later in that case).
+               if ( $generateHtml && $this->isValid() ) {
+                       $output->setText( $this->objectTable( $this->getData()->getValue() ) );
                        $output->addModuleStyles( 'mediawiki.content.json' );
                } else {
                        $output->setText( '' );
                }
        }
+
        /**
-        * Constructs an HTML representation of a JSON object.
-        * @param array $mapping
+        * Construct an HTML representation of a JSON object.
+        *
+        * Called recursively via valueCell().
+        *
+        * @param stdClass $mapping
         * @return string HTML
         */
        protected function objectTable( $mapping ) {
                $rows = array();
+               $empty = true;
 
                foreach ( $mapping as $key => $val ) {
                        $rows[] = $this->objectRow( $key, $val );
+                       $empty = false;
                }
-               return Xml::tags( 'table', array( 'class' => 'mw-json' ),
-                       Xml::tags( 'tbody', array(), join( "\n", $rows ) )
+               if ( $empty ) {
+                       $rows[] = Html::rawElement( 'tr', array(),
+                               Html::element( 'td', array( 'class' => 'mw-json-empty' ),
+                                       wfMessage( 'content-json-empty-object' )->text()
+                               )
+                       );
+               }
+               return Html::rawElement( 'table', array( 'class' => 'mw-json' ),
+                       Html::rawElement( 'tbody', array(), join( "\n", $rows ) )
                );
        }
 
        /**
-        * Constructs HTML representation of a single key-value pair.
+        * Construct HTML representation of a single key-value pair.
         * @param string $key
         * @param mixed $val
         * @return string HTML.
         */
        protected function objectRow( $key, $val ) {
                $th = Xml::elementClean( 'th', array(), $key );
-               if ( is_array( $val ) ) {
-                       $td = Xml::tags( 'td', array(), self::objectTable( $val ) );
-               } else {
-                       if ( is_string( $val ) ) {
-                               $val = '"' . $val . '"';
-                       } else {
-                               $val = FormatJson::encode( $val );
-                       }
+               $td = self::valueCell( $val );
+               return Html::rawElement( 'tr', array(), $th . $td );
+       }
+
+       /**
+        * Constructs an HTML representation of a JSON array.
+        *
+        * Called recursively via valueCell().
+        *
+        * @param array $mapping
+        * @return string HTML
+        */
+       protected function arrayTable( $mapping ) {
+               $rows = array();
+               $empty = true;
 
-                       $td = Xml::elementClean( 'td', array( 'class' => 'value' ), $val );
+               foreach ( $mapping as $val ) {
+                       $rows[] = $this->arrayRow( $val );
+                       $empty = false;
                }
+               if ( $empty ) {
+                       $rows[] = Html::rawElement( 'tr', array(),
+                               Html::element( 'td', array( 'class' => 'mw-json-empty' ),
+                                       wfMessage( 'content-json-empty-array' )->text()
+                               )
+                       );
+               }
+               return Html::rawElement( 'table', array( 'class' => 'mw-json' ),
+                       Html::rawElement( 'tbody', array(), join( "\n", $rows ) )
+               );
+       }
 
-               return Xml::tags( 'tr', array(), $th . $td );
+       /**
+        * Construct HTML representation of a single array value.
+        * @param mixed $val
+        * @return string HTML.
+        */
+       protected function arrayRow( $val ) {
+               $td = self::valueCell( $val );
+               return Html::rawElement( 'tr', array(), $td );
        }
 
+       /**
+        * Construct HTML representation of a single value.
+        * @param mixed $val
+        * @return string HTML.
+        */
+       protected function valueCell( $val ) {
+               if ( is_object( $val ) ) {
+                       return Html::rawElement( 'td', array(), self::objectTable( $val ) );
+               }
+               if ( is_array( $val ) ) {
+                       return Html::rawElement( 'td', array(), self::arrayTable( $val ) );
+               }
+               if ( is_string( $val ) ) {
+                       $val = '"' . $val . '"';
+               } else {
+                       $val = FormatJson::encode( $val );
+               }
+
+               return Xml::elementClean( 'td', array( 'class' => 'value' ), $val );
+       }
 }
index 6e262e8..b2527f9 100644 (file)
@@ -94,7 +94,7 @@ interface IORMTable {
        public function getSummaryFields();
 
        /**
-        * Selects the the specified fields of the records matching the provided
+        * Selects the specified fields of the records matching the provided
         * conditions and returns them as DBDataObject. Field names get prefixed.
         *
         * @see DatabaseBase::select()
@@ -113,7 +113,7 @@ interface IORMTable {
                array $options = array(), $functionName = null );
 
        /**
-        * Selects the the specified fields of the records matching the provided
+        * Selects the specified fields of the records matching the provided
         * conditions and returns them as DBDataObject. Field names get prefixed.
         *
         * @since 1.20
@@ -145,7 +145,7 @@ interface IORMTable {
                array $options = array(), $functionName = null );
 
        /**
-        * Selects the the specified fields of the records matching the provided
+        * Selects the specified fields of the records matching the provided
         * conditions and returns them as associative arrays.
         * Provided field names get prefixed.
         * Returned field names will not have a prefix.
@@ -170,7 +170,7 @@ interface IORMTable {
                array $options = array(), $collapse = true, $functionName = null );
 
        /**
-        * Selects the the specified fields of the first matching record.
+        * Selects the specified fields of the first matching record.
         * Field names get prefixed.
         *
         * @since 1.20
@@ -186,7 +186,7 @@ interface IORMTable {
                array $options = array(), $functionName = null );
 
        /**
-        * Selects the the specified fields of the records matching the provided
+        * Selects the specified fields of the records matching the provided
         * conditions. Field names do NOT get prefixed.
         *
         * @since 1.20
@@ -202,7 +202,7 @@ interface IORMTable {
                array $options = array(), $functionName = null );
 
        /**
-        * Selects the the specified fields of the first record matching the provided
+        * Selects the specified fields of the first record matching the provided
         * conditions and returns it as an associative array, or false when nothing matches.
         * This method makes use of selectFields and expects the same parameters and
         * returns the same results (if there are any, if there are none, this method returns false).
index b22df39..cada298 100644 (file)
@@ -190,7 +190,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
        }
 
        /**
-        * Selects the the specified fields of the records matching the provided
+        * Selects the specified fields of the records matching the provided
         * conditions and returns them as DBDataObject. Field names get prefixed.
         *
         * @since 1.20
@@ -211,7 +211,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
        }
 
        /**
-        * Selects the the specified fields of the records matching the provided
+        * Selects the specified fields of the records matching the provided
         * conditions and returns them as DBDataObject. Field names get prefixed.
         *
         * @since 1.20
@@ -296,7 +296,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
        }
 
        /**
-        * Selects the the specified fields of the records matching the provided
+        * Selects the specified fields of the records matching the provided
         * conditions and returns them as associative arrays.
         * Provided field names get prefixed.
         * Returned field names will not have a prefix.
@@ -346,7 +346,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
        }
 
        /**
-        * Selects the the specified fields of the first matching record.
+        * Selects the specified fields of the first matching record.
         * Field names get prefixed.
         *
         * @since 1.20
@@ -369,7 +369,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
        }
 
        /**
-        * Selects the the specified fields of the records matching the provided
+        * Selects the specified fields of the records matching the provided
         * conditions. Field names do NOT get prefixed.
         *
         * @since 1.20
@@ -400,7 +400,7 @@ class ORMTable extends DBAccessBase implements IORMTable {
        }
 
        /**
-        * Selects the the specified fields of the first record matching the provided
+        * Selects the specified fields of the first record matching the provided
         * conditions and returns it as an associative array, or false when nothing matches.
         * This method makes use of selectFields and expects the same parameters and
         * returns the same results (if there are any, if there are none, this method returns false).
index 7417c6b..c54d241 100644 (file)
@@ -44,9 +44,8 @@ TXT;
  * change the service provider. If MWLogger::getInstance() is called before
  * any service provider has been registered, it will attempt to use the
  * $wgMWLoggerDefaultSpi global to bootstrap MWLoggerSpi registration.
- * $wgMWLoggerDefaultSpi can either be the name of a class implementing the
- * MWLoggerSpi interface with a zero argument constructor or a callable that
- * will return an MWLoggerSpi instance.
+ * $wgMWLoggerDefaultSpi is expected to be an array usable by
+ * ObjectFactory::getObjectFromSpec() to create a class.
  *
  * @see MWLoggerSpi
  * @since 1.25
index 69c3feb..a682504 100644 (file)
@@ -107,7 +107,7 @@ class MWLoggerLegacyLogger extends \Psr\Log\AbstractLogger {
                        // and no explicit wgDebugLogGroups configuration.
                        $shouldEmit = false;
                } else {
-                       // Default return value is the the same as the historic wfDebug
+                       // Default return value is the same as the historic wfDebug
                        // method: emit if $wgDebugLogFile has been set.
                        $shouldEmit = $wgDebugLogFile != '';
                }
index c9545fa..67acf57 100644 (file)
@@ -21,7 +21,7 @@
 /**
  * Log message formatter that mimics the legacy log message formatting of
  * `wfDebug`, `wfDebugLog`, `wfLogDBError` and `wfErrorLog` global functions by
- * deligating the formatting to MWLoggerLegacyLogger.
+ * delegating the formatting to MWLoggerLegacyLogger.
  *
  * @since 1.25
  * @author Bryan Davis <bd808@wikimedia.org>
index a4c0168..30534f0 100644 (file)
@@ -189,7 +189,7 @@ class DiffOpChange extends DiffOp {
  * More ideas are taken from:
  *     http://www.ics.uci.edu/~eppstein/161/960229.html
  *
- * Some ideas are (and a bit of code) are from from analyze.c, from GNU
+ * Some ideas (and a bit of code) are from analyze.c, from GNU
  * diffutils-2.7, which can be found at:
  *     ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz
  *
index 495ac3c..06fb2c6 100644 (file)
@@ -1372,7 +1372,7 @@ abstract class FileBackendStore extends FileBackend {
 
        /**
         * Check if a container name is valid.
-        * This checks for for length and illegal characters.
+        * This checks for length and illegal characters.
         *
         * @param string $container
         * @return bool
index ea1213c..b676f45 100644 (file)
@@ -612,7 +612,7 @@ abstract class DatabaseUpdater {
         * Append a line to the open filehandle.  The line is assumed to
         * be a complete SQL statement.
         *
-        * This is used as a callback for for sourceLine().
+        * This is used as a callback for sourceLine().
         *
         * @param string $line Text to append to the file
         * @return bool False to skip actually executing the file
index 843fe2f..2cc85ce 100644 (file)
@@ -42,7 +42,7 @@
        "config-ns-other": "Zewbi (keyfiyo)",
        "config-ns-other-default": "MyWiki",
        "config-admin-box": "Hesabê Administratori",
-       "config-admin-name": "Namey  karberdé to:",
+       "config-admin-name": "Nameyê şımayê karberi:",
        "config-admin-password": "Parola:",
        "config-admin-password-confirm": "Fına parola:",
        "config-admin-email": "Adresa e-postey:",
index 056e5a8..5e8399c 100644 (file)
@@ -221,7 +221,7 @@ class JobQueueDB extends JobQueue {
                }
 
                $rowSet = array(); // (sha1 => job) map for jobs that are de-duplicated
-               $rowList = array(); // list of jobs for jobs that are are not de-duplicated
+               $rowList = array(); // list of jobs for jobs that are not de-duplicated
                foreach ( $jobs as $job ) {
                        $row = $this->insertFields( $job );
                        if ( $job->ignoreDuplicates() ) {
index 4d1e72c..b4ddd11 100644 (file)
@@ -26,9 +26,9 @@
  *
  * This job comes in a few variants:
  *   - a) Recursive jobs to purge caches for backlink pages for a given title.
- *        These jobs have have (recursive:true,table:<table>) set.
+ *        These jobs have (recursive:true,table:<table>) set.
  *   - b) Jobs to purge caches for a set of titles (the job title is ignored).
- *           These jobs have have (pages:(<page ID>:(<namespace>,<title>),...) set.
+ *           These jobs have (pages:(<page ID>:(<namespace>,<title>),...) set.
  *
  * @ingroup JobQueue
  */
@@ -67,7 +67,7 @@ class HTMLCacheUpdateJob extends Job {
                                array( 'params' => $this->getRootJobParams() )
                        );
                        JobQueueGroup::singleton()->push( $jobs );
-               // Job to purge pages for for a set of titles
+               // Job to purge pages for a set of titles
                } elseif ( isset( $this->params['pages'] ) ) {
                        $this->invalidateTitles( $this->params['pages'] );
                // B/C for job to purge a range of backlink pages for a given page
index f82af27..5d95792 100644 (file)
@@ -26,9 +26,9 @@
  *
  * This job comes in a few variants:
  *   - a) Recursive jobs to update links for backlink pages for a given title.
- *        These jobs have have (recursive:true,table:<table>) set.
+ *        These jobs have (recursive:true,table:<table>) set.
  *   - b) Jobs to update links for a set of pages (the job title is ignored).
- *           These jobs have have (pages:(<page ID>:(<namespace>,<title>),...) set.
+ *           These jobs have (pages:(<page ID>:(<namespace>,<title>),...) set.
  *   - c) Jobs to update links for a single page (the job title)
  *        These jobs need no extra fields set.
  *
@@ -86,7 +86,7 @@ class RefreshLinksJob extends Job {
                                array( 'params' => $extraParams )
                        );
                        JobQueueGroup::singleton()->push( $jobs );
-               // Job to update link tables for for a set of titles
+               // Job to update link tables for a set of titles
                } elseif ( isset( $this->params['pages'] ) ) {
                        foreach ( $this->params['pages'] as $pageId => $nsAndKey ) {
                                list( $ns, $dbKey ) = $nsAndKey;
@@ -157,7 +157,7 @@ class RefreshLinksJob extends Job {
                        $ellapsed = microtime( true ) - $start;
                        // If it took a long time to render, then save this back to the cache to avoid
                        // wasted CPU by other apaches or job runners. We don't want to always save to
-                       // cache as this cause cause high cache I/O and LRU churn when a template changes.
+                       // cache as this can cause high cache I/O and LRU churn when a template changes.
                        if ( $ellapsed >= self::PARSE_THRESHOLD_SEC
                                && $page->isParserCacheUsed( $parserOptions, $revision->getId() )
                                && $parserOutput->isCacheable()
index f09d101..8bd4656 100644 (file)
@@ -60,10 +60,10 @@ class RunningStat implements Countable {
        /** @var float The second central moment (or variance). **/
        public $m2 = 0.0;
 
-       /** @var float The least value in the the set. **/
+       /** @var float The least value in the set. **/
        public $min = INF;
 
-       /** @var float The most value in the set. **/
+       /** @var float The greatest value in the set. **/
        public $max = NEGATIVE_INF;
 
        /**
@@ -129,7 +129,7 @@ class RunningStat implements Countable {
         * Get the estimated standard deviation.
         *
         * The standard deviation of a statistical population is the square root of
-        * its variance. It shows shows how much variation from the mean exists. In
+        * its variance. It shows how much variation from the mean exists. In
         * addition to expressing the variability of a population, the standard
         * deviation is commonly used to measure confidence in statistical conclusions.
         *
index 629c269..1ec9eaa 100644 (file)
@@ -32,12 +32,12 @@ class ScopedCallback {
        protected $params;
 
        /**
-        * @param callable $callback
+        * @param callable|null $callback
         * @param array $params Callback arguments (since 1.25)
         * @throws Exception
         */
        public function __construct( $callback, array $params = array() ) {
-               if ( !is_callable( $callback ) ) {
+               if ( $callback !== null && !is_callable( $callback ) ) {
                        throw new InvalidArgumentException( "Provided callback is not valid." );
                }
                $this->callback = $callback;
index 0f718d2..fa70c63 100644 (file)
@@ -29,7 +29,7 @@ have been changed or you remove it.
 == Testing ==
 
 'make test' will run the conformance test (UtfNormalTest.php), fetching the
-data from from the net if necessary. If it reports failure, something is
+data from the net if necessary. If it reports failure, something is
 going wrong!
 
 You may have to set up PHPUnit first.
index b9f99c8..b4409c3 100644 (file)
@@ -175,7 +175,7 @@ class ImagePage extends Article {
 
                # Show shared description, if needed
                if ( $this->mExtraDescription ) {
-                       $fol = wfMessage( 'shareddescriptionfollows' );
+                       $fol = $this->getContext()->msg( 'shareddescriptionfollows' );
                        if ( !$fol->isDisabled() ) {
                                $out->addWikiText( $fol->plain() );
                        }
@@ -188,7 +188,7 @@ class ImagePage extends Article {
 
                $out->addHTML( Xml::element( 'h2',
                        array( 'id' => 'filelinks' ),
-                       wfMessage( 'imagelinks' )->text() ) . "\n" );
+                               $this->getContext()->msg( 'imagelinks' )->text() ) . "\n" );
                $this->imageDupes();
                # @todo FIXME: For some freaky reason, we can't redirect to foreign images.
                # Yet we return metadata about the target. Definitely an issue in the FileRepo
@@ -205,7 +205,7 @@ class ImagePage extends Article {
                        $out->addHTML( Xml::element(
                                'h2',
                                array( 'id' => 'metadata' ),
-                               wfMessage( 'metadata' )->text() ) . "\n" );
+                                       $this->getContext()->msg( 'metadata' )->text() ) . "\n" );
                        $out->addWikiText( $this->makeMetadataTable( $formattedMetadata ) );
                        $out->addModules( array( 'mediawiki.action.view.metadata' ) );
                }
@@ -237,12 +237,12 @@ class ImagePage extends Article {
         */
        protected function showTOC( $metadata ) {
                $r = array(
-                       '<li><a href="#file">' . wfMessage( 'file-anchor-link' )->escaped() . '</a></li>',
-                       '<li><a href="#filehistory">' . wfMessage( 'filehist' )->escaped() . '</a></li>',
-                       '<li><a href="#filelinks">' . wfMessage( 'imagelinks' )->escaped() . '</a></li>',
+                       '<li><a href="#file">' . $this->getContext()->msg( 'file-anchor-link' )->escaped() . '</a></li>',
+                       '<li><a href="#filehistory">' . $this->getContext()->msg( 'filehist' )->escaped() . '</a></li>',
+                       '<li><a href="#filelinks">' . $this->getContext()->msg( 'imagelinks' )->escaped() . '</a></li>',
                );
                if ( $metadata ) {
-                       $r[] = '<li><a href="#metadata">' . wfMessage( 'metadata' )->escaped() . '</a></li>';
+                       $r[] = '<li><a href="#metadata">' . $this->getContext()->msg( 'metadata' )->escaped() . '</a></li>';
                }
 
                Hooks::run( 'ImagePageShowTOC', array( $this, &$r ) );
@@ -260,7 +260,7 @@ class ImagePage extends Article {
         */
        protected function makeMetadataTable( $metadata ) {
                $r = "<div class=\"mw-imagepage-section-metadata\">";
-               $r .= wfMessage( 'metadata-help' )->plain();
+               $r .= $this->getContext()->msg( 'metadata-help' )->plain();
                $r .= "<table id=\"mw_metadata\" class=\"mw_metadata\">\n";
                foreach ( $metadata as $type => $stuff ) {
                        foreach ( $stuff as $v ) {
@@ -341,14 +341,14 @@ class ImagePage extends Article {
                        if ( $this->displayImg->allowInlineDisplay() ) {
                                # image
                                # "Download high res version" link below the image
-                               # $msgsize = wfMessage( 'file-info-size', $width_orig, $height_orig,
+                               # $msgsize = $this->getContext()->msg( 'file-info-size', $width_orig, $height_orig,
                                #   Linker::formatSize( $this->displayImg->getSize() ), $mime )->escaped();
                                # We'll show a thumbnail of this image
                                if ( $width > $maxWidth || $height > $maxHeight || $this->displayImg->isVectorized() ) {
                                        list( $width, $height ) = $this->getDisplayWidthHeight(
                                                $maxWidth, $maxHeight, $width, $height
                                        );
-                                       $linktext = wfMessage( 'show-big-image' )->escaped();
+                                       $linktext = $this->getContext()->msg( 'show-big-image' )->escaped();
 
                                        $thumbSizes = $this->getThumbSizes( $width, $height, $width_orig, $height_orig );
                                        # Generate thumbnails or thumbnail links as needed...
@@ -377,14 +377,14 @@ class ImagePage extends Article {
                                        $msgsmall = '';
                                        $sizeLinkBigImagePreview = $this->makeSizeLink( $params, $width, $height );
                                        if ( $sizeLinkBigImagePreview ) {
-                                               $msgsmall .= wfMessage( 'show-big-image-preview' )->
+                                               $msgsmall .= $this->getContext()->msg( 'show-big-image-preview' )->
                                                        rawParams( $sizeLinkBigImagePreview )->
                                                        parse();
                                        }
                                        if ( count( $otherSizes ) ) {
                                                $msgsmall .= ' ' .
                                                Html::rawElement( 'span', array( 'class' => 'mw-filepage-other-resolutions' ),
-                                                       wfMessage( 'show-big-image-other' )->rawParams( $lang->pipeList( $otherSizes ) )->
+                                                       $this->getContext()->msg( 'show-big-image-other' )->rawParams( $lang->pipeList( $otherSizes ) )->
                                                        params( count( $otherSizes ) )->parse()
                                                );
                                        }
@@ -394,7 +394,7 @@ class ImagePage extends Article {
                                        $msgsmall = '';
                                } else {
                                        # Image is small enough to show full size on image page
-                                       $msgsmall = wfMessage( 'file-nohires' )->parse();
+                                       $msgsmall = $this->getContext()->msg( 'file-nohires' )->parse();
                                }
 
                                $params['width'] = $width;
@@ -428,7 +428,7 @@ class ImagePage extends Article {
                                        $count = $this->displayImg->pageCount();
 
                                        if ( $page > 1 ) {
-                                               $label = $out->parse( wfMessage( 'imgmultipageprev' )->text(), false );
+                                               $label = $out->parse( $this->getContext()->msg( 'imgmultipageprev' )->text(), false );
                                                // on the client side, this link is generated in ajaxifyPageNavigation()
                                                // in the mediawiki.page.image.pagination module
                                                $link = Linker::linkKnown(
@@ -450,7 +450,7 @@ class ImagePage extends Article {
                                        }
 
                                        if ( $page < $count ) {
-                                               $label = wfMessage( 'imgmultipagenext' )->text();
+                                               $label = $this->getContext()->msg( 'imgmultipagenext' )->text();
                                                $link = Linker::linkKnown(
                                                        $this->getTitle(),
                                                        $label,
@@ -487,8 +487,8 @@ class ImagePage extends Article {
                                                '</td><td><div class="multipageimagenavbox">' .
                                                Xml::openElement( 'form', $formParams ) .
                                                Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() ) .
-                                                       wfMessage( 'imgmultigoto' )->rawParams( $select )->parse() .
-                                               Xml::submitButton( wfMessage( 'imgmultigo' )->text() ) .
+                                               $this->getContext()->msg( 'imgmultigoto' )->rawParams( $select )->parse() .
+                                               Xml::submitButton( $this->getContext()->msg( 'imgmultigo' )->text() ) .
                                                Xml::closeElement( 'form' ) .
                                                "<hr />$thumb1\n$thumb2<br style=\"clear: both\" /></div></td></tr></table>"
                                        );
@@ -502,12 +502,12 @@ class ImagePage extends Article {
                                        "</div>\n" );
                        }
 
-                       $longDesc = wfMessage( 'parentheses', $this->displayImg->getLongDesc() )->text();
+                       $longDesc = $this->getContext()->msg( 'parentheses', $this->displayImg->getLongDesc() )->text();
 
                        $medialink = "[[Media:$filename|$linktext]]";
 
                        if ( !$this->displayImg->isSafeFile() ) {
-                               $warning = wfMessage( 'mediawarning' )->plain();
+                               $warning = $this->getContext()->msg( 'mediawarning' )->plain();
                                // dirmark is needed here to separate the file name, which
                                // most likely ends in Latin characters, from the description,
                                // which may begin with the file type. In RTL environment
@@ -619,7 +619,7 @@ EOT
                        return Html::rawElement( 'a', array(
                                'href' => $thumbnail->getUrl(),
                                'class' => 'mw-thumbnail-link'
-                               ), wfMessage( 'show-big-image-size' )->numParams(
+                               ), $this->getContext()->msg( 'show-big-image-size' )->numParams(
                                        $thumbnail->getWidth(), $thumbnail->getHeight()
                                )->parse() );
                } else {
@@ -645,9 +645,9 @@ EOT
                $wrap = "<div class=\"sharedUploadNotice\">\n$1\n</div>\n";
                $repo = $this->mPage->getFile()->getRepo()->getDisplayName();
 
-               if ( $descUrl && $descText && wfMessage( 'sharedupload-desc-here' )->plain() !== '-' ) {
+               if ( $descUrl && $descText && $this->getContext()->msg( 'sharedupload-desc-here' )->plain() !== '-' ) {
                        $out->wrapWikiMsg( $wrap, array( 'sharedupload-desc-here', $repo, $descUrl ) );
-               } elseif ( $descUrl && wfMessage( 'sharedupload-desc-there' )->plain() !== '-' ) {
+               } elseif ( $descUrl && $this->getContext()->msg( 'sharedupload-desc-there' )->plain() !== '-' ) {
                        $out->wrapWikiMsg( $wrap, array( 'sharedupload-desc-there', $repo, $descUrl ) );
                } else {
                        $out->wrapWikiMsg( $wrap, array( 'sharedupload', $repo ), ''/*BACKCOMPAT*/ );
@@ -694,7 +694,7 @@ EOT
                ) {
                        $ulink = Linker::makeExternalLink(
                                $this->getUploadUrl(),
-                               wfMessage( 'uploadnewversion-linktext' )->text()
+                               $this->getContext()->msg( 'uploadnewversion-linktext' )->text()
                        );
                        $out->addHTML( "<li id=\"mw-imagepage-reupload-link\">"
                                . "<div class=\"plainlinks\">{$ulink}</div></li>\n" );
@@ -832,7 +832,7 @@ EOT
                                $liContents = $link;
                        } elseif ( count( $redirects[$element->page_title] ) === 0 ) {
                                # Redirect without usages
-                               $liContents = wfMessage( 'linkstoimage-redirect' )->rawParams( $link, '' )->parse();
+                               $liContents = $this->getContext()->msg( 'linkstoimage-redirect' )->rawParams( $link, '' )->parse();
                        } else {
                                # Redirect with usages
                                $li = '';
@@ -855,7 +855,7 @@ EOT
                                        array( 'class' => 'mw-imagepage-redirectstofile' ),
                                        $li
                                        ) . "\n";
-                               $liContents = wfMessage( 'linkstoimage-redirect' )->rawParams(
+                               $liContents = $this->getContext()->msg( 'linkstoimage-redirect' )->rawParams(
                                        $link, $ul )->parse();
                        }
                        $out->addHTML( Html::rawElement(
@@ -901,7 +901,7 @@ EOT
                        } else {
                                $link = Linker::makeExternalLink( $file->getDescriptionUrl(),
                                        $file->getTitle()->getPrefixedText() );
-                               $fromSrc = wfMessage( 'shared-repo-from', $file->getRepo()->getDisplayName() )->text();
+                               $fromSrc = $this->getContext()->msg( 'shared-repo-from', $file->getRepo()->getDisplayName() )->text();
                        }
                        $out->addHTML( "<li>{$link} {$fromSrc}</li>\n" );
                }
@@ -930,7 +930,7 @@ EOT
         */
        function showError( $description ) {
                $out = $this->getContext()->getOutput();
-               $out->setPageTitle( wfMessage( 'internalerror' ) );
+               $out->setPageTitle( $this->getContext()->msg( 'internalerror' ) );
                $out->setRobotPolicy( 'noindex,nofollow' );
                $out->setArticleRelated( false );
                $out->enableClientCache( false );
@@ -1008,7 +1008,7 @@ EOT
                        $code = wfBCP47( $lang );
                        $name = Language::fetchLanguageName( $code, $this->getContext()->getLanguage()->getCode() );
                        if ( $name !== '' ) {
-                               $display = wfMessage( 'img-lang-opt', $code, $name )->text();
+                               $display = $this->getContext()->msg( 'img-lang-opt', $code, $name )->text();
                        } else {
                                $display = $code;
                        }
@@ -1024,7 +1024,7 @@ EOT
                        // Its hard to know if the content is really in the default language, or
                        // if its just unmarked content that could be in any language.
                        $opts = Xml::option(
-                               wfMessage( 'img-lang-default' )->text(),
+                                       $this->getContext()->msg( 'img-lang-default' )->text(),
                                $defaultLang,
                                $defaultLang === $curLang
                        ) . $opts;
@@ -1032,7 +1032,7 @@ EOT
                if ( !$haveCurrentLang && $defaultLang !== $curLang ) {
                        $name = Language::fetchLanguageName( $curLang, $this->getContext()->getLanguage()->getCode() );
                        if ( $name !== '' ) {
-                               $display = wfMessage( 'img-lang-opt', $curLang, $name )->text();
+                               $display = $this->getContext()->msg( 'img-lang-opt', $curLang, $name )->text();
                        } else {
                                $display = $curLang;
                        }
@@ -1044,9 +1044,9 @@ EOT
                        array( 'id' => 'mw-imglangselector', 'name' => 'lang' ),
                        $opts
                );
-               $submit = Xml::submitButton( wfMessage( 'img-lang-go' )->text() );
+               $submit = Xml::submitButton( $this->getContext()->msg( 'img-lang-go' )->text() );
 
-               $formContents = wfMessage( 'img-lang-info' )->rawParams( $select, $submit )->parse()
+               $formContents = $this->getContext()->msg( 'img-lang-info' )->rawParams( $select, $submit )->parse()
                        . Html::hidden( 'title', $this->getTitle()->getPrefixedDBkey() );
 
                $langSelectLine = Html::rawElement( 'div', array( 'id' => 'mw-imglangselector-line' ),
index b9f7eda..41dc802 100644 (file)
@@ -395,7 +395,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @param string|int $from One of the following:
         *        - "fromdb" or WikiPage::READ_NORMAL if the data comes from a slave DB
         *        - "fromdbmaster" or WikiPage::READ_LATEST if the data comes from the master DB
-        *        - "forupdate"  or WikiPage::READ_LOCKING if the data comes from from
+        *        - "forupdate"  or WikiPage::READ_LOCKING if the data comes from
         *          the master DB using SELECT FOR UPDATE
         */
        public function loadFromRow( $data, $from ) {
@@ -975,7 +975,7 @@ class WikiPage implements Page, IDBAccessObject {
                                $source = $this->mTitle->getFullURL( 'redirect=no' );
                                return $rt->getFullURL( array( 'rdfrom' => $source ) );
                        } else {
-                               // External pages pages without "local" bit set are not valid
+                               // External pages without "local" bit set are not valid
                                // redirect targets
                                return false;
                        }
index 6f19a23..e820fe2 100644 (file)
@@ -111,7 +111,7 @@ class CoreParserFunctions {
 
                $pref = $parser->getOptions()->getDateFormat();
 
-               // Specify a different default date format other than the the normal default
+               // Specify a different default date format other than the normal default
                // if the user has 'default' for their setting
                if ( $pref == 'default' && $defaultPref ) {
                        $pref = $defaultPref;
index 428e7b2..1a2be5f 100644 (file)
@@ -861,7 +861,7 @@ class ParserOutput extends CacheTime {
        }
 
        /**
-        * Save space for for serialization by removing useless values
+        * Save space for serialization by removing useless values
         * @return array
         */
        public function __sleep() {
index 9a7ec8c..1d77cc0 100644 (file)
@@ -34,9 +34,7 @@ class ProfilerStub extends Profiler {
        }
 
        public function scopedProfileIn( $section ) {
-               return new ScopedCallback( function () {
-                       // no-op
-               } );
+               return new ScopedCallback( null ); // no-op
        }
 
        public function getFunctionStats() {
index a40c44a..e466657 100644 (file)
@@ -139,8 +139,13 @@ class ProfilerXhprof extends Profiler {
 
                // Merge in all of the custom profile sections
                foreach ( $this->sprofiler->getFunctionStats() as $stats ) {
+                       if ( $stats['name'] === '-total' ) {
+                               // Discard section profiler running totals
+                               continue;
+                       }
+
                        // @note: getFunctionStats() values already in ms
-                       $stats['%real'] = $stats['real'] / $main['real'];
+                       $stats['%real'] = $stats['real'] / $main['real'] * 100;
                        $stats['%cpu'] = $main['cpu'] ? $stats['cpu'] / $main['cpu'] * 100 : 0;
                        $stats['%memory'] = $main['memory'] ? $stats['memory'] / $main['memory'] * 100 : 0;
                        $profile[] = $stats; // assume no section names collide with $metrics
index 2c36b68..d5da928 100644 (file)
@@ -67,8 +67,7 @@ class SectionProfiler {
        public function scopedProfileIn( $section ) {
                $this->profileInInternal( $section );
 
-               $that = $this;
-               return new ScopedCallback( $this->profileOutCallback, array( $that, $section ) );
+               return new SectionProfileCallback( $this, $section );
        }
 
        /**
@@ -502,3 +501,29 @@ class SectionProfiler {
                }
        }
 }
+
+/**
+ * Subclass ScopedCallback to avoid call_user_func_array(), which is slow
+ *
+ * This class should not be used outside of SectionProfiler
+ */
+class SectionProfileCallback extends ScopedCallback {
+       /** @var SectionProfiler */
+       protected $profiler;
+       /** @var string */
+       protected $section;
+
+       /**
+        * @param SectionProfiler $profiler
+        * @param string $section
+        */
+       public function __construct( SectionProfiler $profiler, $section ) {
+               parent::__construct( null );
+               $this->profiler = $profiler;
+               $this->section = $section;
+       }
+
+       function __destruct() {
+               $this->profiler->profileOutInternal( $this->section );
+       }
+}
index a0764de..c79554a 100644 (file)
@@ -293,7 +293,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
        }
 
        /**
-        * Base modules required for the the base environment of ResourceLoader
+        * Base modules required for the base environment of ResourceLoader
         *
         * @return array
         */
@@ -409,8 +409,8 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                // ATTENTION!: Because of the line below, this is not going to cause
                // infinite recursion - think carefully before making changes to this
                // code!
-               // Pre-populate modifiedTime with something because the the loop over
-               // all modules below includes the the startup module (this module).
+               // Pre-populate modifiedTime with something because the loop over
+               // all modules below includes the startup module (this module).
                $this->modifiedTime[$hash] = 1;
 
                foreach ( $loader->getModuleNames() as $name ) {
index d4f8167..b9f2024 100644 (file)
@@ -115,7 +115,7 @@ class RevisionDeleter {
         * "revdelete-restricted", "revdelete-unrestricted" indicating (un)suppression
         * or null to indicate nothing in particular.
         * You can turn the keys in $arr[0] and $arr[1] into message keys by
-        * appending -hid and and -unhid to the keys respectively.
+        * appending -hid and -unhid to the keys respectively.
         *
         * @param int $n The new bitfield.
         * @param int $o The old bitfield.
index 98d8da3..3666964 100644 (file)
@@ -25,7 +25,7 @@
  */
 
 /**
- * A special page page that list most used images
+ * A special page that lists most used images
  *
  * @ingroup SpecialPage
  */
index 5c65dcf..108a997 100644 (file)
        "history-feed-empty": "Запатрабаванай старонкі не існуе.\nМагчыма, яна была выдаленая альбо яе перанесьлі.\nПаспрабуйце [[Special:Search|пашукаць]] падобныя старонкі.",
        "rev-deleted-comment": "(апісаньне зьменаў выдаленае)",
        "rev-deleted-user": "(імя ўдзельніка выдаленае)",
-       "rev-deleted-event": "(запÑ\96Ñ\81 Ð· Ð¶Ñ\83Ñ\80нала Ð¿Ð°Ð´Ð·ÐµÑ\8fÑ\9e Ð²Ñ\8bдаленÑ\8b)",
+       "rev-deleted-event": "(падÑ\80абÑ\8fзнаÑ\81Ñ\8cÑ\86Ñ\96 Ð²Ñ\8bдаленÑ\8bÑ\8f Ð· Ð¶Ñ\83Ñ\80нала Ð¿Ð°Ð´Ð·ÐµÑ\8fÑ\9e)",
        "rev-deleted-user-contribs": "[імя ўдзельніка альбо IP-адрас выдалены — рэдагаваньне схаванае з унёску]",
        "rev-deleted-text-permission": "Гэтая вэрсія старонкі была '''выдаленая'''.\nМагчыма, падрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} журнале выдаленьняў].",
        "rev-suppressed-text-permission": "Гэтая вэрсія старонкі была <strong>схаваная</strong>.\nПадрабязнасьці могуць быць знойдзеныя ў [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} журнале хаваньняў].",
        "revdelete-legend": "Усталяваць абмежаваньні бачнасьці",
        "revdelete-hide-text": "Тэкст вэрсіі",
        "revdelete-hide-image": "Схаваць зьмест файла",
-       "revdelete-hide-name": "СÑ\85аваÑ\86Ñ\8c Ð´Ð·ÐµÑ\8fнÑ\8cне Ñ\96 Ð¼Ñ\8dÑ\82Ñ\83",
+       "revdelete-hide-name": "СÑ\85аваÑ\86Ñ\8c Ð¼Ñ\8dÑ\82Ñ\83 Ñ\96 Ð¿Ð°Ñ\80амÑ\8dÑ\82Ñ\80Ñ\8b",
        "revdelete-hide-comment": "Апісаньне зьменаў",
        "revdelete-hide-user": "Імя ўдзельніка/IP-адрас",
        "revdelete-hide-restricted": "Ужываць гэтыя абмежаваньні таксама і для адміністратараў",
index e647fae..5e137af 100644 (file)
        "protect-locked-blocked": "Ne možete promijeniti nivo zaštite dok ste blokirani.\nOvo su trenutne postavke za stranicu '''$1''':",
        "protect-locked-dblock": "Nivoi zaštite se ne mogu mijenjati jer je aktivna baza podataka zaključana.\nTrenutna postavka za stranicu '''$1''' je:",
        "protect-locked-access": "Nemate ovlasti za mijenjanje stepena zaštite.\nSlijede trenutne postavke stranice '''$1''':",
-       "protect-cascadeon": "Ova stranica je tenutno zaštićena jer je uključena u {{PLURAL:$1|stranicu, koja ima|stranice, koje imaju|stranice, koje imaju}} uključenu prenosnu zaštitu.\nMožete promijeniti stepen zaštite ove stranice, ali to neće uticati na prenosnu zaštitu.",
+       "protect-cascadeon": "Ova stranica je trenutno zaštićena jer je uključena u {{PLURAL:$1|stranicu, koja ima|stranice, koje imaju|stranice, koje imaju}} uključenu prenosnu zaštitu.\nPromijene stepena zaštite ove stranice neće uticati na prenosnu zaštitu.",
        "protect-default": "Dopusti svim korisnicima",
        "protect-fallback": "Dozvolite samo korisnicima sa \"$1\" ovlastima/privilegijama",
        "protect-level-autoconfirmed": "Dopustite samo automatski potvrđenim korisnicima",
        "ipb-unblock-addr": "Deblokiraj $1",
        "ipb-unblock": "Deblokiraj korisničko ime ili IP adresu",
        "ipb-blocklist": "Vidi postojeće blokade",
-       "ipb-blocklist-contribs": "Doprinosi za $1",
+       "ipb-blocklist-contribs": "Doprinosi za {{GENDER:$1|$1}}",
        "unblockip": "Odblokiraj korisnika",
        "unblockiptext": "Upotrebite donji upitnik da bi ste vratili\npravo pisanja ranije blokiranoj IP adresi\nili korisničkom imenu.",
        "ipusubmit": "Ukloni ovu blokadu",
        "range_block_disabled": "Administratorska mogućnost da blokira grupe je isključena.",
        "ipb_expiry_invalid": "Pogrešno vrijeme trajanja.",
        "ipb_expiry_temp": "Sakrivene blokade korisničkih imena moraju biti stalne.",
-       "ipb_hide_invalid": "Ne može se onemogućiti ovaj račun; možda ima isuviše izmjena.",
+       "ipb_hide_invalid": "Ne može se onemogućiti ovaj račun; on ima više od {{PLURAL:$1|jedne izmjene|$1 izmjena}}.",
        "ipb_already_blocked": "\"$1\" je već blokiran",
        "ipb-needreblock": "$1 je već blokiran. Da li želite promijeniti postavke?",
        "ipb-otherblocks-header": "Ostale {{PLURAL:$1|blokada|blokade}}",
        "importuploaderrortemp": "Postavljanje uvozne datoteke nije uspjelo.\nNedostaje privremeni folder.",
        "import-parse-failure": "Greška pri parsiranju XML uvoza",
        "import-noarticle": "Nema stranica za uvoz!",
-       "import-nonewrevisions": "Sve revizije su prethodno uvežene.",
+       "import-nonewrevisions": "Nijedna revizija nije uvezena (ili su sve već prisutne ili su preskočene zbog greške).",
        "xml-error-string": "$1 na liniji $2, kolona $3 (bajt $4): $5",
        "import-upload": "Postavljanje XML podataka",
        "import-token-mismatch": "Izgubljeni podaci sesije. Molimo pokušajte ponovno.",
        "import-error-create": "Stranica \"$1\" nije uvezena jer vam nije dozvoljeno da je napravite.",
        "import-error-interwiki": "Stranica \"$1\" nije uvezena jer je njen naziv rezerviran za vanjsko povezivanje (interwiki).",
        "import-error-special": "Stranica \"$1\" nije uvezena jer pripada posebnom imenskom prostoru koje ne prihvata stranice.",
-       "import-error-invalid": "Stranica \"$1\" nije uvezena jer je njen naziv neispravan.",
+       "import-error-invalid": "Stranica \"$1\" nije uvezena jer je naziv pod kojim treba biti uvezena nije valjan na ovoj wiki.",
        "import-options-wrong": "{{PLURAL:$2|Pogrešna opcija|Pogrešne opcije}}: <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "Navedena osnovna stranica ima neispravan naslov.",
        "import-rootpage-nosubpage": "Imenski prostor \"$1\" osnovne stranice ne dozvoljava podstranice.",
        "importlogpage": "Zapisnik uvoza",
        "importlogpagetext": "Administrativni uvozi stranica sa historijom izmjena sa drugih wikija.",
        "import-logentry-upload": "uvezena stranica [[$1]] putem postavljanja datoteke",
-       "import-logentry-upload-detail": "$1 {{PLURAL:$1|revizija|revizije|revizija}}",
+       "import-logentry-upload-detail": "{{PLURAL:$1|Uvezena jedna revizija|Uvezene $1 revizije|Uvezeno $1 revizija}}",
        "import-logentry-interwiki": "uveženo (''transwikied'') $1",
-       "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|revizija|revizije|revizija}} od $2",
+       "import-logentry-interwiki-detail": "{{PLURAL:$1|Uvezena $1 revizija|Uvezene $1 revizije|Uvezeno $1 revizija}} od $2",
        "javascripttest": "Testiranje JavaScript-e",
        "javascripttest-title": "Pokretanje $1 testova",
        "javascripttest-pagetext-noframework": "Ova stranica je određena za pokretanje JavaScript testova.",
        "spam_reverting": "Vraćanje na posljednju verziju koja ne sadrži linkove ka $1",
        "spam_blanking": "Sve revizije koje sadrže linkove ka $1, očisti",
        "spam_deleting": "Sve revizije koje sadrže linkove na $1, brišem",
-       "simpleantispam-label": "Provjera protiv spama.\n'''NE''' popunjavaj ovo!",
+       "simpleantispam-label": "Provjera protiv spama.\n<strong>NE</strong> popunjavajte ovo!",
        "pageinfo-title": "Informacije za \"$1\"",
        "pageinfo-not-current": "Nažalost, nemoguće je dati ove informacije za starije revizije.",
        "pageinfo-header-basic": "Osnovne informacije",
        "duplicate-defaultsort": "Upozorenje: Postavljeni ključ sortiranja \"$2\" zamjenjuje raniji ključ \"$1\".",
        "version": "Verzija",
        "version-extensions": "Instalirana proširenja (ekstenzije)",
-       "version-skins": "Kože",
+       "version-skins": "Instalirane kože",
        "version-specialpages": "Posebne stranice",
        "version-parserhooks": "Kuke parsera",
        "version-variables": "Promjenjive",
        "limitreport-walltime": "Korištenje u realnom vremenu",
        "limitreport-walltime-value": "$1 {{PLURAL:$1|sekunda|sekunde|sekundi}}",
        "expandtemplates": "Proširi šablone",
-       "expand_templates_intro": "Ova posebna stranica uzima neki tekst i proširuje sve šablone u njemu rekurzivno.\nOna također proširuje parserske funkcije poput\n<nowiki>{{</nowiki>#language:…}} i varijable poput\n<nowiki>{{</nowiki>CURRENTDAY}}&mdash;u principu gotovo sve između dvostrukih zagrada.\nOvo se uradi putem poziva relevantnog parserskog nivoa iz same MediaWiki.",
+       "expand_templates_intro": "Ova posebna stranica uzima neki tekst i proširuje sve šablone u njemu rekurzivno.\nOna također proširuje parserske funkcije poput\n<code><nowiki>{{</nowiki>#language:…}}</code> i varijable poput\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>. U principu proširuje gotovo sve između dvostrukih zagrada.",
        "expand_templates_title": "Naslov konteksta, za {{FULLPAGENAME}} itd.:",
        "expand_templates_input": "Tekst unosa:",
        "expand_templates_output": "Rezultat",
index c455a76..1f2056c 100644 (file)
        "welcomecreation-msg": "Hesabê şıma abiyo.\n[[Special:Preferences|{{SITENAME}} vurnayişê tercihanê xo]], xo vir ra mekere.",
        "yourname": "Nameyê karberi:",
        "userlogin-yourname": "Nameyê karberi",
-       "userlogin-yourname-ph": "Namey ğoyé karberi cı kewe",
-       "createacct-another-username-ph": "Namey karberi de fi",
+       "userlogin-yourname-ph": "Nameyê xoyê karberi cı kewe",
+       "createacct-another-username-ph": "Nameyê karberi cı kewe",
        "yourpassword": "Parola",
        "userlogin-yourpassword": "Parola",
        "userlogin-yourpassword-ph": "Parolaya xo cıkewe",
        "passwordreset-emailtitle": "Hesab timarê {{SITENAME}}",
        "passwordreset-emailtext-ip": "Jeweri, {{SITENAME}} ra (ma heta şımayê, $1 IP adresi ra) ($4) teferuatê hesabdê şıma  va wa biyaro xo viri. Karbero ke cêrdeyo {{PLURAL:$3|hesaba|eno hesaba}} ena e-posta adresiya aleqey cı esto:\n\n$2\n\n{{PLURAL:$3|ena parola idaretena|ena parola idareten}} {{PLURAL:$5|jew roc|$5  roca}}rêya.\nEna parolaya deqewe de u xorê ju parolaya newi bıweçine. Parolaya şıma emaya şıma viri se  yana  ena e-posta şıma nê weştase u şıma qayıl niye parolaya xo bıvurnese, ena mesacer peygoş bıkerê.",
        "passwordreset-emailtext-user": "$1 enê karberi, {{SITENAME}}  ra ($4) teferuatê hesab dê şıma  va wa biyaro xo viri. Karbero ke cêrdeyo {{PLURAL:$3|hesaba|eno hesaba}} ena e-posta adresiya aleqey cı esto:\n\n$2\n\n{{PLURAL:$3|ena parola idaretena|ena parola idareten}} {{PLURAL:$5|jew roc|$5  roca}}rêya.\nEna parolaya deqewe de u xorê ju parolaya newi bıweçine. Parolaya şıma emaya şıma viri se  yana  ena e-posta şıma nê weştase u şıma qayıl niye parolaya xo bıvurnese, ena mesacer peygoş bıkerê.",
-       "passwordreset-emailelement": "Namey karberi: $1\nParola vêrdiye: $2",
+       "passwordreset-emailelement": "Nameyê karberi: $1\nParolaya vêrdiye: $2",
        "passwordreset-emailsent": "Yew e-posteyê esterıtışê parola rışiya.",
        "passwordreset-emailsent-capture": "Yew e-posteyê esterıtışê parolayo ke rışiya, no cêr mocniyayo.",
        "passwordreset-emailerror-capture": "Yew e-posteyê esterıtışê parolayo ke rışiya, no cêr mocniyayo, ema {{GENDER:$2|karber}}i rê rıştış de mıwefeq nêbi: $1",
        "history-feed-item-nocomment": "$1 miyanê $2i de",
        "history-feed-empty": "Pela cıgeyrayiye çıniya.\nBeno ke ena esteriya, ya zi namê cı vuriyo.\nSeba pelanê muhimanê newan [[Special:Search|cıgeyrayışê wiki de]] bıcerebne.",
        "rev-deleted-comment": "(Timarkerdışe enay hewadeyayo)",
-       "rev-deleted-user": "(namey karberi esteriyo)",
+       "rev-deleted-user": "(nameyê karberi esteriyo)",
        "rev-deleted-event": "(fealiyetê cıkewtışi esteriyo)",
        "rev-deleted-user-contribs": "[namey karberi ya zi adresa IPy esteriya - vurnayış iştırakan ra nımniyo]",
        "rev-deleted-text-permission": "Çımraviyarnayışê ena pele '''esteriyo'''.\nBeno ke [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log] de teferruat esto.",
        "prefs-help-email": "Dayışê adresa e-postey keyfiyo, labelê seba eyarê parola lazıma, wexto ke şıma naye xo vira kerê.",
        "prefs-help-email-others": "Pera ğoya kerderi de zew link vırazése karberé bini şımaré şenê mesac bırşé. Lakin e-posta adresa şıma héç cayé de niasena.",
        "prefs-help-email-required": "E-mail adrese mecburiya.",
-       "prefs-info": "Melumata şıma",
+       "prefs-info": "Melumato bıngehên",
        "prefs-i18n": "Şar şélıg kerdış",
        "prefs-signature": "İmza",
        "prefs-dateformat": "Formatê tarixi",
        "right-writeapi": "İstıfadey APIyê nuştey",
        "right-delete": "Pele bestere",
        "right-bigdelete": "Pelanê be tarixanê dergan bestere",
-       "right-deletelogentry": "besternayış u mebesternayışa re qeyde definayışê xısusi",
-       "right-deleterevision": "Vurnayışê xısusiyê ke ê pelanê, inan bestere ya zi peyser bia",
+       "right-deletelogentry": "Qeydanê cıkewtışanê xısusiyan bestere û peyser biya",
+       "right-deleterevision": "Vurnayışanê xısusiyanê pele bestere ya zi peyser biya",
        "right-deletedhistory": "Qeydanê tarixanê esterıteyan de qayt ke, bê nuştey inan",
        "right-deletedtext": "Mabênê newede vurnayışanê esterıtiyan de qaytê nuştey esterıtey u vurnayışan ke",
        "right-browsearchive": "Pelanê esterıteyan bıgeyre",
        "right-undelete": "Jû pela esterıtiye peyser bia",
-       "right-suppressrevision": "İdarekeran ra dızdeni/miyanki, newede vurnayışan de qayt ke u newede vıraze",
+       "right-suppressrevision": "İdarekeran ra miyanki, newede vurnayışan de qayt ke u newede vıraze",
+       "right-viewsuppressed": "İdarekeran ra miyanki newede vurnayışan de qayt ke",
        "right-suppressionlog": "Rocekanê xasan bıvêne",
        "right-block": "Karberanê binan karê vurnayışi ra bloke bıke",
        "right-blockemail": "Yew karberê erşawıtışê/rıştena e-maili ra bloke bıke",
-       "right-hideuser": "Yew namey karberi  şari ra dızdeni/miyanki bloke bıke",
+       "right-hideuser": "Yew nameyê karberi şari ra miyanki bloke bıke",
        "right-ipblock-exempt": "Blokanê IPi, oto-blokan u blokanê menzıli ra ravêre",
        "right-proxyunbannable": "Blokanê otomatikiê proksiyan ra ravêre",
        "right-unblockself": "Blokeyınan ake",
        "noemailtext": "no/na karber yew e-postayo meqbul nêdawa/o",
        "nowikiemailtext": "no/na karber/e, karberanê binani ra gırewtışê e-postayi tercih nêkerd.",
        "emailnotarget": "Qandê Gêreninamey karberiyo wuna çınyo yana xırabo.",
-       "emailtarget": "Namey Karberi defiyê de.",
+       "emailtarget": "Nameyê karberiyê gırewtoği cıkewên.",
        "emailusername": "Nameyê karberi:",
        "emailusernamesubmit": "İtaet",
        "email-legend": "karberê {{SITENAME}} binan re e-posta bıerşaw",
        "emailblock": "e-mail blok biyo",
        "blocklist-nousertalk": "ti nieşken pele minaqaşe xo bivurne",
        "ipblocklist-empty": "Lista kılitkerdışi venga.",
-       "ipblocklist-no-results": "Adresa IPya waştiye ya zi namey karberi kılit nêbiyo.",
+       "ipblocklist-no-results": "Adresa IPya waştiye ya zi nameyê karberi kılit nêbiyo.",
        "blocklink": "kılit ke",
        "unblocklink": "bloki wedare",
        "change-blocklink": "kılitkerdışi bıvurne",
index 82e3fdf..b064b40 100644 (file)
        "history-feed-empty": "La pàgina serchêda l'an gh'é mìa; la pré èser stēda scanşlêda dal sît o gh'é stê cambiê nòm. Verifichêr cun [[Special:Search|pàgina 'd sèirca]] se gh'é dal pàgini nōvi.",
        "rev-deleted-comment": "(argumèint ed la mudéfica armôs)",
        "rev-deleted-user": "(nòm utèint armôs)",
-       "rev-deleted-event": "(asiòun dal log armôsa)",
+       "rev-deleted-event": "(particulêr dal log armôs)",
        "rev-deleted-user-contribs": "(nòm utèint o indirés IP armôs - mudéfica lughêda da la stòria)",
        "rev-deleted-text-permission": "Cla versiòun ché 'd la pàgina l'é stêda <strong> scanşlêda </strong>. \nConsultêr al [{{fullurl:{{#Special:Log}}/delete|page={{PAGENAMEE}}}} log dal canşladûri] per nōv particulêr.",
        "rev-suppressed-text-permission": "Cla versiòun ché 'd la pàgina l'é stêda <strong> scanşlêda </strong>. Consultêr al [{{fullurl:{{#Special:Log}}/ suppress |page={{ FULLPAGENAMEE }}}} log dal canşladûri] per nōv particulêr.",
        "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-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",
+       "right-unwatchedpages": "Fa vèder un elèinch ed pàgini mìa guardêdi",
+       "right-mergehistory": "Al mèt insèm la stôria dal pàgini",
+       "right-userrights": "Mudéfica i dirét ed l'utèint",
+       "right-userrights-interwiki": "Mudéfica i dirét ed j êter utèint 'd êtri wiki",
+       "right-siteadmin": "Blōca e şblōca al databêş",
+       "right-override-export-depth": "Pôrta fōra al pàgini cun insèm al pàgini coleghêdi per 'na larghèsa ed 5",
+       "right-sendemail": "Spidés pôsta eletrônica a êter utèint",
        "newuserlogpage": "Utèint nōv",
        "action-read": "lēzer cla pàgina ché",
        "action-edit": "Mudifichêr cla pàgina ché",
index 2ee3df2..da49fe9 100644 (file)
        "content-model-text": "plain text",
        "content-model-javascript": "JavaScript",
        "content-model-css": "CSS",
+       "content-model-json": "JSON",
+       "content-json-empty-object": "Empty object",
+       "content-json-empty-array": "Empty array",
        "duplicate-args-category": "Pages using duplicate arguments in template calls",
        "duplicate-args-category-desc": "The page contains template calls that use duplicates of arguments, such as <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> or <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "<strong>Warning:</strong> This page contains too many expensive parser function calls.\n\nIt should have less than $2 {{PLURAL:$2|call|calls}}, there {{PLURAL:$1|is now $1 call|are now $1 calls}}.",
index eaea3f6..24d209e 100644 (file)
        "revdel-restore": "تغییر پیدایی",
        "pagehist": "تاریخچهٔ صفحه",
        "deletedhist": "تاریخچهٔ حذف‌شده",
-       "revdelete-hide-current": "خطا در پنهان‌کردن مورد مورخ $2 ساعت $1: این نسخه، نسخهٔ اخیر است و قابل پنهان‌کردن نیست.",
-       "revdelete-show-no-access": "خطا در پنهانکردن مورد مورخ $2 ساعت $1: این نسخه علامت «محدودیت» دارد و شما به آن دسترسی ندارید.",
-       "revdelete-modify-no-access": "خطا در پنهانکردن مورد مورخ $2 ساعت $1: این نسخه علامت «محدودیت» دارد و شما به آن دسترسی ندارید.",
-       "revdelete-modify-missing": "خطا در پنهانکردن مورد شمارهٔ $1: این نسخه در پایگاه داده وجود ندارد!",
+       "revdelete-hide-current": "خطا در پنهان کردن مورد مورخ $2 ساعت $1: این نسخه، نسخهٔ اخیر است و قابل پنهان کردن نیست.",
+       "revdelete-show-no-access": "خطا در پنهان کردن مورد مورخ $2 ساعت $1: این نسخه علامت «محدودیت» دارد و شما به آن دسترسی ندارید.",
+       "revdelete-modify-no-access": "خطا در پنهان کردن مورد مورخ $2 ساعت $1: این نسخه علامت «محدودیت» دارد و شما به آن دسترسی ندارید.",
+       "revdelete-modify-missing": "خطا در پنهان کردن مورد شمارهٔ $1: این نسخه در پایگاه داده وجود ندارد!",
        "revdelete-no-change": "'''هشدار:''' مورد مورخ $2 ساعت $1 از قبل تنظیمات پیدایی درخواست شده را دارا بود.",
-       "revdelete-concurrent-change": "خطا در پنهانکردن مورد مورخ $2 ساعت $1: به نظر می‌رسد که در مدتی که شما برای تغییر وضعیت آن تلاش می‌کردید وضعیت آن توسط فرد دیگری تغییر یافته است.\nلطفاً سیاهه‌ها را بررسی کنید.",
+       "revdelete-concurrent-change": "خطا در پنهان کردن مورد مورخ $2 ساعت $1: به نظر می‌رسد که در مدتی که شما برای تغییر وضعیت آن تلاش می‌کردید وضعیت آن توسط فرد دیگری تغییر یافته است.\nلطفاً سیاهه‌ها را بررسی کنید.",
        "revdelete-only-restricted": "خطا در پنهان کردن مورد مورخ $2 ساعت $1: شما نمی‌توانید موارد را از دید مدیران پنهان کنید مگر آن که یکی دیگر از گزینه‌های پنهان‌سازی را نیز انتخاب کنید.",
        "revdelete-reason-dropdown": "*دلایل متداول حذف\n** نقض حق تکثیر\n** اظهار نظر یا اطلاعات فردی نامناسب\n** نام کاربری نامناسب\n** اطلاعات به طور بالقوه افتراآمیز",
        "revdelete-otherreason": "دلیل دیگر/اضافی:",
        "right-suppressionlog": "مشاهدهٔ سیاهه‌های خصوصی",
        "right-block": "قطع دسترسی ویرایشی دیگر کاربران",
        "right-blockemail": "قطع دسترسی دیگر کاربران برای ارسال رایانامه",
-       "right-hideuser": "قطع دسترسی کاربر و پنهانکردن آن از دید عموم",
+       "right-hideuser": "قطع دسترسی کاربر و پنهان کردن آن از دید عموم",
        "right-ipblock-exempt": "تاثیر نپذیرفتن از قطع دسترسی‌های آی‌پی، خودکار یا فاصله‌ای",
        "right-proxyunbannable": "تاثیر نپذیرفتن از قطع دسترسی خودکار پروکسی‌ها",
        "right-unblockself": "بازکردن دسترسی خود",
        "rclistfrom": "نمایش تغییرات تازه با شروع از $3 $2",
        "rcshowhideminor": "$1 ویرایش‌های جزئی",
        "rcshowhideminor-show": "نمایش",
-       "rcshowhideminor-hide": "پنهانکردن",
+       "rcshowhideminor-hide": "پنهان کردن",
        "rcshowhidebots": "$1 ربات‌ها",
        "rcshowhidebots-show": "نمایش",
-       "rcshowhidebots-hide": "پنهانکردن",
+       "rcshowhidebots-hide": "پنهان کردن",
        "rcshowhideliu": "$1 کاربران ثبت‌نام‌کردە",
        "rcshowhideliu-show": "نمایش",
-       "rcshowhideliu-hide": "پنهانکردن",
+       "rcshowhideliu-hide": "پنهان کردن",
        "rcshowhideanons": "$1 کاربران ناشناس",
        "rcshowhideanons-show": "نمایش",
-       "rcshowhideanons-hide": "پنهانکردن",
+       "rcshowhideanons-hide": "پنهان کردن",
        "rcshowhidepatr": "$1 ویرایش‌های گشت‌خورده",
        "rcshowhidepatr-show": "نمایش",
-       "rcshowhidepatr-hide": "پنهانکردن",
+       "rcshowhidepatr-hide": "پنهان کردن",
        "rcshowhidemine": "$1 ویرایش‌های من",
        "rcshowhidemine-show": "نمایش",
-       "rcshowhidemine-hide": "پنهانکردن",
+       "rcshowhidemine-hide": "پنهان کردن",
        "rclinks": "نمایش آخرین $1 تغییر در $2 روز اخیر<br />$3",
        "diff": "تفاوت",
        "hist": "تاریخچه",
        "protectedpages-indef": "فقط محافظت‌های بی‌پایان",
        "protectedpages-summary": "در این صفحه فهرست صفحات موجود است که در حال حاضر محافظت شده اند. برای فهرست عنوان‌هایی که از ایجاد محافظت شده‌اند، به [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]] مراجعه کنید.",
        "protectedpages-cascade": "فقط محافظت‌های آبشاری",
-       "protectedpages-noredirect": "پنهانکردن تغییر مسیرها",
+       "protectedpages-noredirect": "پنهان کردن تغییر مسیرها",
        "protectedpagesempty": "در حال حاضر هیچ‌صفحه‌ای محافظت نشده‌است.",
        "protectedpages-timestamp": "برچسب زمان",
        "protectedpages-page": "صفحه",
        "blocklist": "کاربران بسته‌شده",
        "ipblocklist": "کاربران بسته‌شده",
        "ipblocklist-legend": "جستجوی کاربر بسته شده",
-       "blocklist-userblocks": "پنهانکردن بسته‌شدن‌های حساب",
-       "blocklist-tempblocks": "پنهانکردن بستن‌های موقت",
-       "blocklist-addressblocks": "پنهانکردن تک آی‌پی‌های بسته شده",
+       "blocklist-userblocks": "پنهان کردن بسته‌شدن‌های حساب",
+       "blocklist-tempblocks": "پنهان کردن بستن‌های موقت",
+       "blocklist-addressblocks": "پنهان کردن تک آی‌پی‌های بسته شده",
        "blocklist-rangeblocks": "پنهان کردنی قطع دسترسی بازه‌ها",
        "blocklist-timestamp": "برچسب زمان",
        "blocklist-target": "هدف",
        "sorbsreason": "نشانی آی‌پی شما توسط DNSBL مورد استفاده {{SITENAME}} به عنوان یک پروکسی باز گزارش شده‌است.",
        "sorbs_create_account_reason": "نشانی آی‌پی شما توسط DNSBL مورد استفاده {{SITENAME}} به عنوان یک پروکسی باز گزارش شده‌است.\nشما اجازهٔ ساختن حساب کاربری ندارید.",
        "xffblockreason": "نشانی آی‌پی در X-Forwarded-For header موجود است و پروکسی شما یا سروری که از آن استفاده می‌کنید بسته‌شده‌است. دلیل بسته‌شدن: $1",
-       "cant-see-hidden-user": "کاربری که می‌خواهید ببندید قبلاً بسته شده و پنهان گردیده‌است. چون شما دسترسی پنهان‌کردن کاربران را ندارید، نمی‌توانید قطع دسترسی کاربر را ببینید یا ویرایش کنید.",
+       "cant-see-hidden-user": "کاربری که می‌خواهید ببندید قبلاً بسته شده و پنهان گردیده است. چون شما دسترسی پنهان کردن کاربران را ندارید، نمی‌توانید قطع دسترسی کاربر را ببینید یا ویرایش کنید.",
        "ipbblocked": "شما نمی‌توانید دسترسی دیگر کاربران را ببندید یا باز کنید زیرا دسترسی خودتان بسته است.",
        "ipbnounblockself": "شما مجاز به باز کردن دسترسی خود نیستید.",
        "lockdb": "قفل کردن پایگاه داده",
index 00faf9d..6e3f367 100644 (file)
@@ -77,7 +77,8 @@
                        "C.R.",
                        "Elitre",
                        "Laurentius",
-                       "Macofe"
+                       "Macofe",
+                       "Ricordisamoa"
                ]
        },
        "tog-underline": "Sottolinea i collegamenti:",
        "history-feed-empty": "La pagina richiesta non esiste; potrebbe essere stata cancellata dal sito o rinominata. Verificare con la [[Special:Search|pagina di ricerca]] se vi sono nuove pagine.",
        "rev-deleted-comment": "(Oggetto della modifica rimosso)",
        "rev-deleted-user": "(nome utente rimosso)",
-       "rev-deleted-event": "(azione del log rimossa)",
+       "rev-deleted-event": "(dettagli del log rimossi)",
        "rev-deleted-user-contribs": "[nome utente o indirizzo IP rimosso - edit nascosto dalla cronologia]",
        "rev-deleted-text-permission": "Questa versione della pagina è stata '''cancellata'''.\nConsultare il [{{fullurl:{{#Special:Log}}/delete|page={{PAGENAMEE}}}} log delle cancellazioni] per ulteriori dettagli.",
        "rev-suppressed-text-permission": "Questa versione della pagina è stata '''soppressa'''.\nConsultare il [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} log delle soppressioni] per ulteriori dettagli.",
index f6184c0..46796ac 100644 (file)
@@ -61,7 +61,8 @@
                        "Rxy",
                        "Mfuji",
                        "Takot",
-                       "SkyDaisy9"
+                       "SkyDaisy9",
+                       "Los688"
                ]
        },
        "tog-underline": "リンクの下線:",
@@ -89,7 +90,7 @@
        "tog-shownumberswatching": "ページをウォッチしている利用者数を表示",
        "tog-oldsig": "既存の署名:",
        "tog-fancysig": "署名をウィキ文として扱う (自動リンクなし)",
-       "tog-uselivepreview": "ライブプレビューを使用 (開発中)",
+       "tog-uselivepreview": "ライブプレビューを使用",
        "tog-forceeditsummary": "要約欄が空欄の場合に確認を促す",
        "tog-watchlisthideown": "自分の編集をウォッチリストに表示しない",
        "tog-watchlisthidebots": "ボットによる編集をウォッチリストに表示しない",
        "history-feed-empty": "要求されたページは存在しません。\nこのウィキから既に削除されたか、名前が変更された可能性があります。\n[[Special:Search|このウィキの検索]]で関連する新しいページを探してみてください。",
        "rev-deleted-comment": "(要約は除去されています)",
        "rev-deleted-user": "(利用者名は除去されています)",
-       "rev-deleted-event": "(記録は除去されています)",
+       "rev-deleted-event": "(è¨\98é\8c²ã\81®è©³ç´°ã\81¯é\99¤å\8e»ã\81\95ã\82\8cã\81¦ã\81\84ã\81¾ã\81\99)",
        "rev-deleted-user-contribs": "[利用者名またはIPアドレスは除去されました - その編集は投稿記録で非表示にされています]",
        "rev-deleted-text-permission": "この版は<strong>削除されています</strong>。\n[{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 削除記録]に詳細情報があるかもしれません。",
        "rev-suppressed-text-permission": "この版は<strong>秘匿されています</strong>。[{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} 秘匿記録]に詳細情報があるかもしれません。",
index d3c9690..08e42c5 100644 (file)
        "blankarticle": "<strong>Ескерту:</strong> Сіз бастамақшы болған бет бос.\nЕгер сіз «{{int:savearticle}}» дегенші қайта шертсеңіз бет қандайда бір мағлұматсыз басталады.",
        "anoneditwarning": "<strong> Ескерту:</strong>  Сіз жүйеге кірмегенсіз.\nIP мекенжайыңыз бұл беттің өңделу тарихында жазылып алынады.",
        "anonpreviewwarning": "<em>Сіз жүйеге кірмегенсіз. IP мекенжайыңыз бұл беттің өңделу тарихында жазылып алынады.</em>",
-       "missingsummary": "<strong>Ð\95Ñ\81кеÑ\80Ñ\82Ñ\83:</strong> Ó¨Ò£Ð´ÐµÐ¼ÐµÐ½Ñ\96Ò£ Ò\9bÑ\8bÑ\81Ò\9bаÑ\88а Ñ\82үйÑ\96ндемеÑ\81Ñ\96н ÐµÐ½Ð³Ñ\96збепÑ\81Ñ\96з.\n«{{int:savearticle}}» Ð±Ð°Ñ\82Ñ\8bÑ\80маÑ\81Ñ\8bн Ò\9bайÑ\82а Ð±Ð°Ñ\81Ñ\81аңÑ\8bз Ó©Ò£Ð´ÐµÐ½Ð¼ÐµÒ£Ñ\96з Ñ\82үйÑ\96ндемеÑ\81Ñ\96з Ñ\81аÒ\9bÑ\82аладÑ\8b.",
+       "missingsummary": "<strong>Ескерту:</strong> Өңдеменің қысқаша түйіндемесін енгізбепсіз.\n«{{int:savearticle}}» батырмасын қайта бассаңыз өңдемеңіз түйіндемесіз сақталады.",
        "missingcommenttext": "Пікіріңізді төменге енгізіңіз.",
        "missingcommentheader": "<strong>Ескерту:</strong> Бұл пікірге тақырыпы/бас жолы жазбапсыз.\n«{{int:savearticle}}» түймесін тағы бассаңыз өңдемеңіз түйіндемесіз сақталады.",
        "summary-preview": "Қысқаша түйіндемесін қарап шығу:",
index cbfd8d1..ac04924 100644 (file)
        "revdelete-legend": "Ustaw ograniczenia widoczności",
        "revdelete-hide-text": "Tekst wersji",
        "revdelete-hide-image": "Ukryj zawartość pliku",
-       "revdelete-hide-name": "Ukryj akcję i cel",
+       "revdelete-hide-name": "Ukryj cel i parametry",
        "revdelete-hide-comment": "Opis zmian",
        "revdelete-hide-user": "Nazwa użytkownika/adres IP",
        "revdelete-hide-restricted": "Ukryj informacje przed administratorami tak samo jak przed innymi",
index 21a976a..ef2564f 100644 (file)
        "anoneditwarning": "<strong>Aviso</strong>: Não iniciou sessão. O seu endereço IP será registado no histórico de edições desta página. Se <strong>[$1 iniciar sessão]</strong> ou <strong>[$2 criar uma conta]</strong>, as suas edições serão registadas com o seu nome de utilizador(a), bem como usufruir de outros benefícios.",
        "anonpreviewwarning": "''Não iniciou sessão. Ao gravar, registará o seu endereço IP no histórico de edições da página.''",
        "missingsummary": "'''Atenção:''' Não introduziu um resumo da edição.\nSe clicar novamente \"Gravar página\" a sua edição será gravada sem resumo.",
+       "selfredirect": "<strong>Aviso:</strong> Está a redirecionar esta página para si mesma.\nPode ter especificado o destino errado para a página ou até a editar a página errada.\nSe clicar em \"{{int:savearticle}}\" novamente, o redirecionamento será criado na mesma.",
        "missingcommenttext": "Introduza um comentário abaixo, por favor.",
        "missingcommentheader": "'''Atenção:''' Não introduziu um assunto ou cabeçalho para este comentário.\nSe clicar novamente \"{{int:savearticle}}\", a sua edição será gravada sem assunto ou cabeçalho.",
        "summary-preview": "Antevisão do resumo:",
        "history-feed-empty": "A página solicitada não existe.\nPode ter sido eliminada da wiki ou o nome sido alterado.\nTente [[Special:Search|pesquisar na wiki]] novas páginas relevantes.",
        "rev-deleted-comment": "(resumo da edição suprimido)",
        "rev-deleted-user": "(nome de utilizador removido)",
-       "rev-deleted-event": "(entrada removida)",
+       "rev-deleted-event": "(registos de detalhes eliminados)",
        "rev-deleted-user-contribs": "[nome de utilizador ou IP removido - edição ocultada das contribuições]",
        "rev-deleted-text-permission": "Esta revisão de página foi <strong>eliminada</strong>.\nEncontrará detalhes no [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} registo de eliminações].",
        "rev-suppressed-text-permission": "Esta revisão de página foi <strong>suprimida</strong>.\nPode consultar os detalhes no [{{fullurl:{{#Special:Log}}/suppress|page={{FULLPAGENAMEE}}}} registo de supressões].",
        "revdelete-legend": "Definir restrições de visibilidade",
        "revdelete-hide-text": "Revisão do texto",
        "revdelete-hide-image": "Ocultar conteúdo do ficheiro",
-       "revdelete-hide-name": "Ocultar operação e destino",
+       "revdelete-hide-name": "Ocultar destino e parâmetros",
        "revdelete-hide-comment": "Resumo da edição",
        "revdelete-hide-user": "Nome de utilizador/endereço de IP",
        "revdelete-hide-restricted": "Ocultar dados dos administradores e de todos os outros",
index 813064d..42ae44c 100644 (file)
        "content-model-text": "Name for the plain text content model, used when decribing what type of content a page contains.\n\nThis message is substituted in:\n*{{msg-mw|Bad-target-model}}\n*{{msg-mw|Content-not-allowed-here}}\n{{Identical|Plain text}}",
        "content-model-javascript": "Name for the JavaScript content model, used when decribing what type of content a page contains.\n\nThis message is substituted in:\n*{{msg-mw|Bad-target-model}}\n*{{msg-mw|Content-not-allowed-here}}",
        "content-model-css": "Name for the CSS content model, used when decribing what type of content a page contains.\n\nThis message is substituted in:\n*{{msg-mw|Bad-target-model}}\n*{{msg-mw|Content-not-allowed-here}}",
+       "content-model-json": "Name for the JSON content model, used when decribing what type of content a page contains.\n\nThis message is substituted in:\n*{{msg-mw|Bad-target-model}}\n*{{msg-mw|Content-not-allowed-here}}",
+       "content-json-empty-object": "Used to represent an object with no properties on a JSON content model page.",
+       "content-json-empty-array": "Used to represent an array with no values on a JSON content model page.",
        "duplicate-args-category": "This message is used as a category name for a [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages are placed automatically if they contain template calls that use duplicates of arguments, such as <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> or <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "duplicate-args-category-desc": "Duplicate arguments category description. Shown on [[Special:TrackingCategories]].\n\nSee also:\n* {{msg-mw|Duplicate-args-category}}",
        "expensive-parserfunction-warning": "On some (expensive) [[MetaWikipedia:Help:ParserFunctions|parser functions]] (e.g. <code><nowiki>{{#ifexist:}}</nowiki></code>) there is a limit of how many times it may be used. This is an error message shown when the limit is exceeded.\n\nParameters:\n* $1 - the current number of parser function calls\n* $2 - the allowed number of parser function calls\nSee also [[:mw:Manual:$wgExpensiveParserFunctionLimit|$wgExpensiveParserFunctionLimit in the MediaWiki manual]].\n\nSee also:\n* {{msg-mw|Expensive-parserfunction-category}}",
index 108fe9f..2f8b7d2 100644 (file)
@@ -1321,7 +1321,7 @@ abstract class LoggedUpdateMaintenance extends Maintenance {
        }
 
        /**
-        * Message to show the the update log was unable to log the completion of this update
+        * Message to show that the update log was unable to log the completion of this update
         * @return string
         */
        protected function updatelogFailedMessage() {
index 3e2c6c9..dd4f760 100644 (file)
@@ -44,7 +44,7 @@ class FetchText extends Maintenance {
         *   \n
         *   text  (may be empty)
         *
-        * note that that the text string itself is *not* followed by newline
+        * note that the text string itself is *not* followed by newline
         */
        public function execute() {
                $db = wfGetDB( DB_SLAVE );
index f77978f..686d9f2 100644 (file)
@@ -84,7 +84,7 @@ class PopulateParentId extends LoggedUpdateMaintenance {
                                                "rev_id < " . intval( $row->rev_id ) ),
                                        __METHOD__,
                                        array( 'ORDER BY' => 'rev_id DESC' ) );
-                               # If there are none, check the the highest ID with a lower timestamp
+                               # If there are none, check the highest ID with a lower timestamp
                                if ( !$previousID ) {
                                        # Get the highest older timestamp
                                        $lastTimestamp = $db->selectField(
index 136530a..19a775a 100644 (file)
@@ -1,4 +1,4 @@
-The icons used here are derived from the crystalsvg icons in the the
+The icons used here are derived from the crystalsvg icons in the
 pics/crystalsvg/ directory of kdelibs-3.4.0 they were modified on 2005-05-15
 by Ævar Arnfjörð Bjarmason for use in MediaWiki.
 
index 6c7b4d4..f7c4217 100644 (file)
                                                                .prop( 'tabIndex', 0 );
                                                }
                                        } else {
-                                               // The toggle-link will be in one the the cells (td or th) of the first row
+                                               // The toggle-link will be in one of the cells (td or th) of the first row
                                                $firstItem = $collapsible.find( 'tr:first th, tr:first td' );
                                                $toggle = $firstItem.find( '> .mw-collapsible-toggle' );
 
index 0d3341b..3918be7 100644 (file)
                                                buildCollationTable();
 
                                                // Legacy fix of .sortbottoms
-                                               // Wrap them inside inside a tfoot (because that's what they actually want to be) &
+                                               // Wrap them inside a tfoot (because that's what they actually want to be)
                                                // and put the <tfoot> at the end of the <table>
                                                var $tfoot,
                                                        $sortbottoms = $table.find( '> tbody > tr.sortbottom' );
index f9944b4..70d54ce 100644 (file)
                // This causes further calls to addButton to go to insertion directly
                // instead of to the queue.
                // It is important that this is after the one and only loop through
-               // the the queue
+               // the queue
                isReady = true;
 
                // Apply to dynamically created textboxes as well as normal ones
index d93e291..4afccda 100644 (file)
        padding: 0.5em 1em;
 }
 
-.mw-json td {
-       background-color: #eee;
-       font-style: italic;
-}
-
 .mw-json .value {
        background-color: #dcfae3;
        font-family: monospace, monospace;
        white-space: pre-wrap;
 }
 
+.mw-json-empty {
+       background-color: #fff;
+       font-style: italic;
+}
+
 .mw-json tr {
        margin-bottom: 0.5em;
+       background-color: #eee;
 }
 
 .mw-json th {
index 9235d69..40f8ef9 100644 (file)
                                if ( 'documentMode' in document && document.documentMode <= 9 ) {
 
                                        $style = getMarker().prev();
-                                       // Verify that the the element before Marker actually is a
+                                       // Verify that the element before Marker actually is a
                                        // <style> tag and one that came from ResourceLoader
                                        // (not some other style tag or even a `<meta>` or `<script>`).
                                        if ( $style.data( 'ResourceLoaderDynamicStyleTag' ) === true ) {
index 89d1de7..4d63ea6 100644 (file)
@@ -177,13 +177,13 @@ mw.loader.implement("test.quux",function($,jQuery){mw.test.baz({token:123});},{"
 }</script>
 '
                        ),
-                       // Load module script with with ESI
+                       // Load module script with ESI
                        array(
                                array( 'test.foo', ResourceLoaderModule::TYPE_SCRIPTS, true ),
                                '<script><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=scripts&amp;skin=fallback&amp;*" /></script>
 '
                        ),
-                       // Load module styles with with ESI
+                       // Load module styles with ESI
                        array(
                                array( 'test.foo', ResourceLoaderModule::TYPE_STYLES, true ),
                                '<style><esi:include src="http://127.0.0.1:8080/w/load.php?debug=false&amp;lang=en&amp;modules=test.foo&amp;only=styles&amp;skin=fallback&amp;*" /></style>
index d4151a5..0ad8ecc 100644 (file)
@@ -6,48 +6,76 @@
  */
 class JsonContentTest extends MediaWikiLangTestCase {
 
+       protected function setUp() {
+               parent::setUp();
+
+               $this->setMwGlobals( 'wgWellFormedXml', true );
+       }
+
        public static function provideValidConstruction() {
                return array(
-                       array( 'foo', CONTENT_MODEL_JSON, false, null ),
-                       array( FormatJson::encode( array() ), CONTENT_MODEL_JSON, true, array() ),
-                       array( FormatJson::encode( array( 'foo' ) ), CONTENT_MODEL_JSON, true, array( 'foo' ) ),
+                       array( 'foo', false, null ),
+                       array( '{}', true, (object)array() ),
+                       array( '{ "0": "bar" }', true, (object)array( 'bar' ) ),
                );
        }
 
        /**
         * @dataProvider provideValidConstruction
         */
-       public function testValidConstruct( $text, $modelId, $isValid, $expected ) {
-               $obj = new JsonContent( $text, $modelId );
+       public function testIsValid( $text, $isValid, $expected ) {
+               $obj = new JsonContent( $text, CONTENT_MODEL_JSON );
                $this->assertEquals( $isValid, $obj->isValid() );
-               $this->assertEquals( $expected, $obj->getJsonData() );
+               $this->assertEquals( $expected, $obj->getData()->getValue() );
        }
 
        public static function provideDataToEncode() {
                return array(
-                       array( array() ),
-                       array( array( 'foo' ) ),
-                       array( array( 'foo', 'bar' ) ),
-                       array( array( 'baz' => 'foo', 'bar' ) ),
-                       array( array( 'baz' => 1000, 'bar' ) ),
+                       array(
+                               // Round-trip empty array
+                               '[]',
+                               '[]',
+                       ),
+                       array(
+                               // Round-trip empty object
+                               '{}',
+                               '{}',
+                       ),
+                       array(
+                               // Round-trip empty array/object (nested)
+                               '{ "foo": {}, "bar": [] }',
+                               "{\n    \"foo\": {},\n    \"bar\": []\n}",
+                       ),
+                       array(
+                               '{ "foo": "bar" }',
+                               "{\n    \"foo\": \"bar\"\n}",
+                       ),
+                       array(
+                               '{ "foo": 1000 }',
+                               "{\n    \"foo\": 1000\n}",
+                       ),
+                       array(
+                               '{ "foo": 1000, "0": "bar" }',
+                               "{\n    \"foo\": 1000,\n    \"0\": \"bar\"\n}",
+                       ),
                );
        }
 
        /**
         * @dataProvider provideDataToEncode
         */
-       public function testBeautifyUsesFormatJson( $data ) {
-               $obj = new JsonContent( FormatJson::encode( $data ) );
-               $this->assertEquals( FormatJson::encode( $data, true ), $obj->beautifyJSON() );
+       public function testBeautifyJson( $input, $beautified ) {
+               $obj = new JsonContent( $input );
+               $this->assertEquals( $beautified, $obj->beautifyJSON() );
        }
 
        /**
         * @dataProvider provideDataToEncode
         */
-       public function testPreSaveTransform( $data ) {
-               $obj = new JsonContent( FormatJson::encode( $data ) );
+       public function testPreSaveTransform( $input, $transformed ) {
+               $obj = new JsonContent( $input );
                $newObj = $obj->preSaveTransform( $this->getMockTitle(), $this->getMockUser(), $this->getMockParserOptions() );
-               $this->assertTrue( $newObj->equals( new JsonContent( FormatJson::encode( $data, true ) ) ) );
+               $this->assertTrue( $newObj->equals( new JsonContent( $transformed ) ) );
        }
 
        private function getMockTitle() {
@@ -70,33 +98,33 @@ class JsonContentTest extends MediaWikiLangTestCase {
        public static function provideDataAndParserText() {
                return array(
                        array(
-                               array(),
-                               '<table class="mw-json"><tbody></tbody></table>'
+                               (object)array(),
+                               '<table class="mw-json"><tbody><tr><td class="mw-json-empty">Empty object</td></tr></tbody></table>'
                        ),
                        array(
-                               array( 'foo' ),
+                               (object)array( 'foo' ),
                                '<table class="mw-json"><tbody><tr><th>0</th><td class="value">&quot;foo&quot;</td></tr></tbody></table>'
                        ),
                        array(
-                               array( 'foo', 'bar' ),
+                               (object)array( 'foo', 'bar' ),
                                '<table class="mw-json"><tbody><tr><th>0</th><td class="value">&quot;foo&quot;</td></tr>' .
                                "\n" .
                                '<tr><th>1</th><td class="value">&quot;bar&quot;</td></tr></tbody></table>'
                        ),
                        array(
-                               array( 'baz' => 'foo', 'bar' ),
+                               (object)array( 'baz' => 'foo', 'bar' ),
                                '<table class="mw-json"><tbody><tr><th>baz</th><td class="value">&quot;foo&quot;</td></tr>' .
                                "\n" .
                                '<tr><th>0</th><td class="value">&quot;bar&quot;</td></tr></tbody></table>'
                        ),
                        array(
-                               array( 'baz' => 1000, 'bar' ),
+                               (object)array( 'baz' => 1000, 'bar' ),
                                '<table class="mw-json"><tbody><tr><th>baz</th><td class="value">1000</td></tr>' .
                                "\n" .
                                '<tr><th>0</th><td class="value">&quot;bar&quot;</td></tr></tbody></table>'
                        ),
                        array(
-                               array( '<script>alert("evil!")</script>'),
+                               (object)array( '<script>alert("evil!")</script>'),
                                '<table class="mw-json"><tbody><tr><th>0</th><td class="value">&quot;&lt;script&gt;alert(&quot;evil!&quot;)&lt;/script&gt;&quot;</td></tr></tbody></table>',
                        ),
                );
index 3d8612d..a972b21 100644 (file)
--- a/thumb.php
+++ b/thumb.php
@@ -135,12 +135,12 @@ function wfStreamThumb( array $params ) {
                // Format is <timestamp>!<name>
                $bits = explode( '!', $fileName, 2 );
                if ( count( $bits ) != 2 ) {
-                       wfThumbError( 404, wfMessage( 'badtitletext' )->text() );
+                       wfThumbError( 404, wfMessage( 'badtitletext' )->parse() );
                        return;
                }
                $title = Title::makeTitleSafe( NS_FILE, $bits[1] );
                if ( !$title ) {
-                       wfThumbError( 404, wfMessage( 'badtitletext' )->text() );
+                       wfThumbError( 404, wfMessage( 'badtitletext' )->parse() );
                        return;
                }
                $img = RepoGroup::singleton()->getLocalRepo()->newFromArchiveName( $title, $fileName );
@@ -150,7 +150,7 @@ function wfStreamThumb( array $params ) {
 
        // Check the source file title
        if ( !$img ) {
-               wfThumbError( 404, wfMessage( 'badtitletext' )->text() );
+               wfThumbError( 404, wfMessage( 'badtitletext' )->parse() );
                return;
        }
 
@@ -262,7 +262,7 @@ function wfStreamThumb( array $params ) {
                return;
        }
 
-       // For 404 handled thumbnails, we only use the the base name of the URI
+       // For 404 handled thumbnails, we only use the base name of the URI
        // for the thumb params and the parent directory for the source file name.
        // Check that the zone relative path matches up so squid caches won't pick
        // up thumbs that would not be purged on source file deletion (bug 34231).
@@ -310,10 +310,10 @@ function wfStreamThumb( array $params ) {
 
        $user = RequestContext::getMain()->getUser();
        if ( !wfThumbIsStandard( $img, $params ) && $user->pingLimiter( 'renderfile-nonstandard' ) ) {
-               wfThumbError( 500, wfMessage( 'actionthrottledtext' ) );
+               wfThumbError( 500, wfMessage( 'actionthrottledtext' )->parse() );
                return;
        } elseif ( $user->pingLimiter( 'renderfile' ) ) {
-               wfThumbError( 500, wfMessage( 'actionthrottledtext' ) );
+               wfThumbError( 500, wfMessage( 'actionthrottledtext' )->parse() );
                return;
        }
 
@@ -598,7 +598,7 @@ function wfExtractThumbParams( $file, $params ) {
  * Output a thumbnail generation error message
  *
  * @param int $status
- * @param string $msg
+ * @param string $msg HTML
  * @return void
  */
 function wfThumbError( $status, $msg ) {