Bug 38450 Reimplement MediaWiki's info action
authormadman <madman.enwiki@gmail.com>
Fri, 3 Aug 2012 23:19:01 +0000 (23:19 +0000)
committerPlatonides <platonides@gmail.com>
Sun, 19 Aug 2012 20:25:10 +0000 (22:25 +0200)
Currently addresses: bug 38526, bug 38527, bug 38528, bug 38529, bug
38530, bug 38531, bug 38532, bug 38533, bug 38536, bug 38558, bug 38560,
bug 38561, bug 38562, bug 38563, bug 38564.

Change-Id: Ia1878588f718e99756caf23ae9c5a131eb70bf12

includes/actions/InfoAction.php
languages/messages/MessagesEn.php
languages/messages/MessagesQqq.php
maintenance/language/messages.inc

index f4813a4..db7b61d 100644 (file)
@@ -1,7 +1,6 @@
 <?php
 /**
- * Display informations about a page.
- * Very inefficient for the moment.
+ * Displays information about a page.
  *
  * Copyright © 2011 Alexandre Emsenhuber
  *
  */
 
 class InfoAction extends FormlessAction {
-
+       /**
+        * Returns the name of the action this object responds to.
+        *
+        * @return string lowercase
+        */
        public function getName() {
                return 'info';
        }
 
-       protected function getDescription() {
-               return '';
-       }
-
-       public function requiresWrite() {
-               return false;
-       }
-
+       /**
+        * Whether this action can still be executed by a blocked user.
+        *
+        * @return bool
+        */
        public function requiresUnblock() {
                return false;
        }
 
-       protected function getPageTitle() {
-               return $this->msg( 'pageinfo-title', $this->getTitle()->getSubjectPage()->getPrefixedText() )->text();
+       /**
+        * Whether this action requires the wiki not to be locked.
+        *
+        * @return bool
+        */
+       public function requiresWrite() {
+               return false;
        }
 
+       /**
+        * Shows page information on GET request.
+        *
+        * @return string Page information that will be added to the output
+        */
        public function onView() {
-               global $wgDisableCounters;
+               global $wgDisableCounters, $wgRCMaxAge, $wgRestrictionTypes;
 
-               $title = $this->getTitle()->getSubjectPage();
+               $lang = $this->getLanguage();
+               $title = $this->getTitle();
 
-               $userCanViewUnwatchedPages = $this->getUser()->isAllowed( 'unwatchedpages' );
+               $article = new Article( $title );
+               $id = $title->getArticleID();
 
+               // Get page information that would be too "expensive" to retrieve by normal means
+               $userCanViewUnwatchedPages = $this->getUser()->isAllowed( 'unwatchedpages' );
                $pageInfo = self::pageCountInfo( $title, $userCanViewUnwatchedPages, $wgDisableCounters );
-               $talkInfo = self::pageCountInfo( $title->getTalkPage(), $userCanViewUnwatchedPages, $wgDisableCounters );
 
-               $lang = $this->getLanguage();
+               // Get page properties
+               $dbr = wfGetDB( DB_SLAVE );
+               $result = $dbr->select(
+                       'page_props',
+                       array( 'pp_propname', 'pp_value' ),
+                       array( 'pp_page' => $id ),
+                       __METHOD__
+               );
+
+               $pageProperties = array();
+               foreach ( $result as $row ) {
+                       $pageProperties[$row->pp_propname] = $row->pp_value;
+               }
+
+               $content = '';
+               $table = '';
+
+               // Basic information
+               $content = $this->addHeader( $content, $this->msg( 'pageinfo-header-basic' ) );
+
+               // Display title
+               $displayTitle = $title->getPrefixedText();
+               if ( !empty( $pageProperties['displaytitle'] ) ) {
+                       $displayTitle = $pageProperties['displaytitle'];
+               }
+
+               $table = $this->addRow( $table,
+                       $this->msg( 'pageinfo-display-title' ), $displayTitle );
+
+               // Default sort key
+               $sortKey = $title->getCategorySortKey();
+               if ( !empty( $pageProperties['defaultsort'] ) ) {
+                       $sortKey = $pageProperties['defaultsort'];
+               }
+
+               $table = $this->addRow( $table,
+                       $this->msg( 'pageinfo-default-sort' ), $sortKey );
 
-               $content =
-                       Html::rawElement( 'tr', array(),
-                               Html::element( 'th', array(), '' ) .
-                                       Html::element( 'th', array(), $this->msg( 'pageinfo-subjectpage' )->text() ) .
-                                       Html::element( 'th', array(), $this->msg( 'pageinfo-talkpage' )->text() )
-                       ) .
-                       Html::rawElement( 'tr', array(),
-                               Html::element( 'th', array( 'colspan' => 3 ), $this->msg( 'pageinfo-header-edits' )->text() )
-                       ) .
-                       Html::rawElement( 'tr', array(),
-                               Html::element( 'td', array(), $this->msg( 'pageinfo-edits' )->text() ) .
-                                       Html::element( 'td', array(), $lang->formatNum( $pageInfo['edits'] ) ) .
-                                       Html::element( 'td', array(), $lang->formatNum( $talkInfo['edits'] ) )
-                       ) .
-                       Html::rawElement( 'tr', array(),
-                               Html::element( 'td', array(), $this->msg( 'pageinfo-authors' )->text() ) .
-                                       Html::element( 'td', array(), $lang->formatNum( $pageInfo['authors'] ) ) .
-                                       Html::element( 'td', array(), $lang->formatNum( $talkInfo['authors'] ) )
+               // Page length (in bytes)
+               $table = $this->addRow( $table,
+                       $this->msg( 'pageinfo-length' ), $lang->formatNum( $title->getLength() ) );
+
+               // Page ID
+               $table = $this->addRow( $table,
+                       $this->msg( 'pageinfo-article-id' ), $lang->formatNum( $id ) );
+
+               // Search engine status
+               $pOutput = new ParserOutput();
+               if ( isset( $pageProperties['noindex'] ) ) {
+                       $pOutput->setIndexPolicy( 'noindex' );
+               }
+
+               // Use robot policy logic
+               $policy = $article->getRobotPolicy( 'view', $pOutput );
+               $table = $this->addRow( $table,
+                       'Search engine status', "Marked as '" . $policy['index'] . "'"
+               );
+
+               if ( !$wgDisableCounters ) {
+                       // Number of views
+                       $table = $this->addRow( $table,
+                               $this->msg( 'pageinfo-views' ), $lang->formatNum( $pageInfo['views'] )
                        );
+               }
 
                if ( $userCanViewUnwatchedPages ) {
-                       $content .= Html::rawElement( 'tr', array(),
-                               Html::element( 'th', array( 'colspan' => 3 ), $this->msg( 'pageinfo-header-watchlist' )->text() )
-                       ) .
-                               Html::rawElement( 'tr', array(),
-                                       Html::element( 'td', array(), $this->msg( 'pageinfo-watchers' )->text() ) .
-                                               Html::element( 'td', array( 'colspan' => 2 ), $lang->formatNum( $pageInfo['watchers'] ) )
-                               );
+                       // Number of page watchers
+                       $table = $this->addRow( $table,
+                               $this->msg( 'pageinfo-watchers' ), $lang->formatNum( $pageInfo['watchers'] ) );
                }
 
-               if ( !$wgDisableCounters ) {
-                       $content .= Html::rawElement( 'tr', array(),
-                               Html::element( 'th', array( 'colspan' => 3 ), $this->msg( 'pageinfo-header-views' )->text() )
-                       ) .
-                               Html::rawElement( 'tr', array(),
-                                       Html::element( 'td', array(), $this->msg( 'pageinfo-views' )->text() ) .
-                                               Html::element( 'td', array(), $lang->formatNum( $pageInfo['views'] ) ) .
-                                               Html::element( 'td', array(), $lang->formatNum( $talkInfo['views'] ) )
-                               ) .
-                               Html::rawElement( 'tr', array(),
-                                       Html::element( 'td', array(), $this->msg( 'pageinfo-viewsperedit' )->text() ) .
-                                               Html::element( 'td', array(), $lang->formatNum( sprintf( '%.2f', $pageInfo['edits'] ? $pageInfo['views'] / $pageInfo['edits'] : 0 ) ) ) .
-                                               Html::element( 'td', array(), $lang->formatNum( sprintf( '%.2f', $talkInfo['edits'] ? $talkInfo['views'] / $talkInfo['edits'] : 0 ) ) )
+               // Redirects to this page
+               $whatLinksHere = SpecialPage::getTitleFor( 'WhatLinksHere', $title->getPrefixedText() );
+               $table = $this->addRow( $table,
+                       Linker::link(
+                               $whatLinksHere,
+                               $this->msg( 'pageinfo-redirects-name' ),
+                               array(),
+                               array( 'hidelinks' => 1, 'hidetrans' => 1 )
+                       ),
+                       $this->msg( 'pageinfo-redirects-value',
+                               $lang->formatNum( count( $title->getRedirectsHere() ) )
+                       )
+               );
+
+               // Subpages of this page
+               $prefixIndex = SpecialPage::getTitleFor( 'PrefixIndex', $title->getPrefixedText() . '/' );
+               $table = $this->addRow( $table,
+                       Linker::link( $prefixIndex, $this->msg( 'pageinfo-subpages-name' ) ),
+                       $this->msg( 'pageinfo-subpages-value',
+                               $lang->formatNum( $pageInfo['subpages']['total'] ),
+                               $pageInfo['subpages']['redirects'],
+                               $pageInfo['subpages']['nonredirects']
+                       )
+               );
+
+               // Page protection
+               $content = $this->addTable( $content, $table );
+               $content = $this->addHeader( $content, $this->msg( 'pageinfo-header-restrictions' ) );
+               $table = '';
+
+               // Page protection
+               foreach ( $wgRestrictionTypes as $restrictionType ) {
+                       $protectionLevel = implode( ', ', $title->getRestrictions( $restrictionType ) );
+                       if ( $protectionLevel == '' ) {
+                               // Allow all users
+                               $message = $this->msg( "protect-default" );
+                       } else {
+                               // Administrators only
+                               $message = $this->msg( "protect-level-$protectionLevel" );
+                               if ( !$message->exists() ) {
+                                       // Require "$1" permission
+                                       $message = $this->msg( "protect-fallback", $protectionLevel );
+                               }
+                       }
+
+                       $table = $this->addRow( $table,
+                               $this->msg( 'pageinfo-restriction', $restrictionType ), $message
+                       );
+               }
+
+               // Edit history
+               $content = $this->addTable( $content, $table );
+               $content = $this->addHeader( $content, $this->msg( 'pageinfo-header-edits' ) );
+               $table = '';
+
+               // Page creator
+               $table = $this->addRow( $table,
+                       $this->msg( 'pageinfo-firstuser' ), $pageInfo['firstuser']
+               );
+
+               // Date of page creation
+               $table = $this->addRow( $table,
+                       $this->msg( 'pageinfo-firsttime' ), $lang->timeanddate( $pageInfo['firsttime'] )
+               );
+
+               // Latest editor
+               $table = $this->addRow( $table,
+                       $this->msg( 'pageinfo-lastuser' ), $pageInfo['lastuser']
+               );
+
+               // Date of latest edit
+               $table = $this->addRow( $table,
+                       $this->msg( 'pageinfo-lasttime' ), $lang->timeanddate( $pageInfo['lasttime'] )
+               );
+
+               // Total number of edits
+               $table = $this->addRow( $table,
+                       $this->msg( 'pageinfo-edits' ), $lang->formatNum( $pageInfo['edits'] )
+               );
+
+               // Total number of distinct authors
+               $table = $this->addRow( $table,
+                       $this->msg( 'pageinfo-authors' ), $lang->formatNum( $pageInfo['authors'] )
+               );
+
+               // Recent number of edits (within past 30 days)
+               $table = $this->addRow( $table,
+                       $this->msg( 'pageinfo-recent-edits', $lang->formatDuration( $wgRCMaxAge ) ),
+                       $lang->formatNum( $pageInfo['recent_edits'] )
+               );
+
+               // Recent number of distinct authors
+               $table = $this->addRow( $table,
+                       $this->msg( 'pageinfo-recent-authors' ), $lang->formatNum( $pageInfo['recent_authors'] )
+               );
+
+               $content = $this->addTable( $content, $table );
+
+               // Array of MagicWord objects
+               $magicWords = MagicWord::getDoubleUnderscoreArray();
+
+               // Array of magic word IDs
+               $wordIDs = $magicWords->names;
+
+               // Array of IDs => localized magic words
+               $localizedWords = $lang->getMagicWords();
+
+               $listItems = array();
+               foreach ( $pageProperties as $property => $value ) {
+                       if ( in_array( $property, $wordIDs ) ) {
+                               $listItems[] = Html::element( 'li', array(), $localizedWords[$property][1] );
+                       }
+               }
+
+               $localizedList = Html::rawElement( 'ul', array(), implode( '', $listItems ) );
+               $hiddenCategories = $article->getHiddenCategories();
+               $transcludedTemplates = $title->getTemplateLinksFrom();
+
+               if ( count( $listItems ) > 0
+                       || count( $hiddenCategories ) > 0
+                       || count( $transcludedTemplates ) > 0 ) {
+                       // Page properties
+                       $content = $this->addHeader( $content, $this->msg( 'pageinfo-header-properties' ) );
+                       $table = '';
+
+                       // Magic words
+                       if ( count( $listItems ) > 0 ) {
+                               $table = $this->addRow( $table,
+                                       $this->msg( 'pageinfo-magic-words', count( $listItems ) ), $localizedList
+                               );
+                       }
+
+                       // Hide "This page is a member of # hidden categories explanation
+                       $content .= Html::element( 'style', array(),
+                               '.mw-hiddenCategoriesExplanation { display: none; }' );
+
+                       // Hidden categories
+                       if ( count( $hiddenCategories ) > 0 ) {
+                               $table = $this->addRow( $table,
+                                       $this->msg( 'pageinfo-hidden-categories', count( $hiddenCategories ) ),
+                                       Linker::formatHiddenCategories( $hiddenCategories )
                                );
+                       }
+
+                       // Hide "Templates used on this page:" explanation
+                       $content .= Html::element( 'style', array(),
+                               '.mw-templatesUsedExplanation { display: none; }' );
+
+                       // Transcluded templates
+                       if ( count( $transcludedTemplates ) > 0 ) {
+                               $table = $this->addRow( $table,
+                                       $this->msg( 'pageinfo-templates', count( $transcludedTemplates ) ),
+                                       Linker::formatTemplates( $transcludedTemplates )
+                               );
+                       }
+
+                       $content = $this->addTable( $content, $table );
                }
-               return Html::rawElement( 'table', array( 'class' => 'wikitable mw-page-info' ), $content );
+
+               return $content;
        }
 
        /**
-        * Return the total number of edits and number of unique editors
-        * on a given page. If page does not exist, returns false.
+        * Returns page information that would be too "expensive" to retrieve by normal means.
         *
         * @param $title Title object
         * @param $canViewUnwatched bool
@@ -115,13 +310,28 @@ class InfoAction extends FormlessAction {
         * @return array
         */
        public static function pageCountInfo( $title, $canViewUnwatched, $disableCounter ) {
+               global $wgRCMaxAge;
+
                wfProfileIn( __METHOD__ );
                $id = $title->getArticleID();
-               $dbr = wfGetDB( DB_SLAVE );
 
+               $dbr = wfGetDB( DB_SLAVE );
                $result = array();
+
+               if ( !$disableCounter ) {
+                       // Number of views
+                       $views = (int) $dbr->selectField(
+                               'page',
+                               'page_counter',
+                               array( 'page_id' => $id ),
+                               __METHOD__
+                       );
+                       $result['views'] = $views;
+               }
+
                if ( $canViewUnwatched ) {
-                       $watchers = (int)$dbr->selectField(
+                       // Number of page watchers
+                       $watchers = (int) $dbr->selectField(
                                'watchlist',
                                'COUNT(*)',
                                array(
@@ -133,7 +343,8 @@ class InfoAction extends FormlessAction {
                        $result['watchers'] = $watchers;
                }
 
-               $edits = (int)$dbr->selectField(
+               // Total number of edits
+               $edits = (int) $dbr->selectField(
                        'revision',
                        'COUNT(rev_page)',
                        array( 'rev_page' => $id ),
@@ -141,7 +352,8 @@ class InfoAction extends FormlessAction {
                );
                $result['edits'] = $edits;
 
-               $authors = (int)$dbr->selectField(
+               // Total number of distinct authors
+               $authors = (int) $dbr->selectField(
                        'revision',
                        'COUNT(DISTINCT rev_user_text)',
                        array( 'rev_page' => $id ),
@@ -149,17 +361,139 @@ class InfoAction extends FormlessAction {
                );
                $result['authors'] = $authors;
 
-               if ( !$disableCounter ) {
-                       $views = (int)$dbr->selectField(
-                               'page',
-                               'page_counter',
-                               array( 'page_id' => $id ),
-                               __METHOD__
-                       );
-                       $result['views'] = $views;
-               }
+               // "Recent" threshold defined by $wgRCMaxAge
+               $threshold = $dbr->timestamp( time() - $wgRCMaxAge );
+
+               // Recent number of edits
+               $edits = (int) $dbr->selectField(
+                       'revision',
+                       'COUNT(rev_page)',
+                       array(
+                               'rev_page' => $id ,
+                               "rev_timestamp >= $threshold"
+                       ),
+                       __METHOD__
+               );
+               $result['recent_edits'] = $edits;
+
+               // Recent number of distinct authors
+               $authors = (int) $dbr->selectField(
+                       'revision',
+                       'COUNT(DISTINCT rev_user_text)',
+                       array(
+                               'rev_page' => $id,
+                               "rev_timestamp >= $threshold"
+                       ),
+                       __METHOD__
+               );
+               $result['recent_authors'] = $authors;
+
+               $conds = array( 'page_namespace' => $title->getNamespace(), 'page_is_redirect' => 1 );
+               $conds[] = 'page_title ' . $dbr->buildLike( $title->getDBkey() . '/', $dbr->anyString() );
+
+               // Subpages of this page (redirects)
+               $result['subpages']['redirects'] = (int) $dbr->selectField(
+                       'page',
+                       'COUNT(page_id)',
+                       $conds,
+                       __METHOD__ );
+
+               // Subpages of this page (non-redirects)
+               $conds['page_is_redirect'] = 0;
+               $result['subpages']['nonredirects'] = (int) $dbr->selectField(
+                       'page',
+                       'COUNT(page_id)',
+                       $conds,
+                       __METHOD__
+               );
+
+               // Subpages of this page (total)
+               $result['subpages']['total'] = $result['subpages']['redirects']
+                       + $result['subpages']['nonredirects'];
+
+               // Latest editor + date of latest edit
+               $options = array( 'ORDER BY' => 'rev_timestamp ASC', 'LIMIT' => 1 );
+               $row = $dbr->fetchRow( $dbr->select(
+                       'revision',
+                       array( 'rev_user_text', 'rev_timestamp' ),
+                       array( 'rev_page' => $id ),
+                       __METHOD__,
+                       $options
+               ) );
+
+               $result['firstuser'] = $row['rev_user_text'];
+               $result['firsttime'] = $row['rev_timestamp'];
+
+               // Latest editor + date of latest edit
+               $options['ORDER BY'] = 'rev_timestamp DESC';
+               $row = $dbr->fetchRow( $dbr->select(
+                       'revision',
+                       array( 'rev_user_text', 'rev_timestamp' ),
+                       array( 'rev_page' => $id ),
+                       __METHOD__,
+                       $options
+               ) );
+
+               $result['lastuser'] = $row['rev_user_text'];
+               $result['lasttime'] = $row['rev_timestamp'];
 
                wfProfileOut( __METHOD__ );
                return $result;
        }
+
+       /**
+        * Adds a header to the content that will be added to the output.
+        *
+        * @param $content string The content that will be added to the output
+        * @param $header string The value of the header
+        * @return string The content with the header added
+        */
+       protected function addHeader( $content, $header ) {
+               return $content . Html::element( 'h2', array(), $header );
+       }
+
+       /**
+        * Adds a row to a table that will be added to the content.
+        *
+        * @param $table string The table that will be added to the content
+        * @param $name string The name of the row
+        * @param $value string The value of the row
+        * @return string The table with the row added
+        */
+       protected function addRow( $table, $name, $value ) {
+               return $table . Html::rawElement( 'tr', array(),
+                       Html::rawElement( 'td', array(), $name ) .
+                       Html::rawElement( 'td', array(), $value )
+               );
+       }
+
+       /**
+        * Adds a table to the content that will be added to the output.
+        *
+        * @param $content string The content that will be added to the output
+        * @param $table string The table
+        * @return string The content with the table added
+        */
+       protected function addTable( $content, $table ) {
+               return $content . Html::rawElement( 'table', array( 'class' => 'wikitable mw-page-info' ),
+                       $table );
+       }
+
+       /**
+        * Returns the description that goes below the <h1> tag.
+        *
+        * @return string
+        */
+       protected function getDescription() {
+               return '';
+       }
+
+       /**
+        * Returns the name that goes in the <h1> page title.
+        *
+        * @return string
+        */
+       protected function getPageTitle() {
+               return $this->msg( 'pageinfo-title', $this->getTitle()->getPrefixedText() )->text();
+       }
 }
index 41312c5..56a96bf 100644 (file)
@@ -3730,17 +3730,34 @@ This is probably caused by a link to a blacklisted external site.',
 'spam_deleting'       => 'All revisions contained links to $1, deleting',
 
 # Info page
-'pageinfo-title'            => 'Information for "$1"',
-'pageinfo-header-edits'     => 'Edits',
-'pageinfo-header-watchlist' => 'Watchlist',
-'pageinfo-header-views'     => 'Views',
-'pageinfo-subjectpage'      => 'Page',
-'pageinfo-talkpage'         => 'Talk page',
-'pageinfo-watchers'         => 'Number of watchers',
-'pageinfo-edits'            => 'Number of edits',
-'pageinfo-authors'          => 'Number of distinct authors',
-'pageinfo-views'            => 'Number of views',
-'pageinfo-viewsperedit'     => 'Views per edit',
+'pageinfo-title'               => 'Information for "$1"',
+'pageinfo-header-basic'        => 'Basic information',
+'pageinfo-header-edits'        => 'Edit history',
+'pageinfo-header-restrictions' => 'Page protection',
+'pageinfo-header-properties'   => 'Page properties',
+'pageinfo-display-title'       => 'Display title',
+'pageinfo-default-sort'        => 'Default sort key',
+'pageinfo-length'              => 'Page length (in bytes)',
+'pageinfo-article-id'          => 'Page ID',
+'pageinfo-robot-policy'        => 'Search engine status',
+'pageinfo-views'               => 'Number of views',
+'pageinfo-watchers'            => 'Number of page watchers',
+'pageinfo-redirects-name'      => 'Redirects to this page',
+'pageinfo-redirects-value'     => '$1',
+'pageinfo-subpages-name'       => 'Subpages of this page',
+'pageinfo-subpages-value'      => '$1 ($2 {{PLURAL:$2|redirect|redirects}}; $3 {{PLURAL:$3|non-redirect|non-redirects}})',
+'pageinfo-firstuser'           => 'Page creator',
+'pageinfo-firsttime'           => 'Date of page creation',
+'pageinfo-lastuser'            => 'Latest editor',
+'pageinfo-lasttime'            => 'Date of latest edit',
+'pageinfo-edits'               => 'Total number of edits',
+'pageinfo-authors'             => 'Total number of distinct authors',
+'pageinfo-recent-edits'        => 'Recent number of edits (within past $1)',
+'pageinfo-recent-authors'      => 'Recent number of distinct authors',
+'pageinfo-restriction'         => 'Page protection ($1)',
+'pageinfo-magic-words'         => 'Magic words ($1)',
+'pageinfo-hidden-categories'   => 'Hidden categories ($1)',
+'pageinfo-templates'           => 'Transcluded {{PLURAL:$1|template|templates}} ($1)',
 
 # Skin names
 'skinname-standard'    => 'Classic', # only translate this message to other languages if you have to change it
index 3a03e53..3bde772 100644 (file)
@@ -3447,17 +3447,43 @@ See also {{msg-mw|Anonuser}} and {{msg-mw|Siteusers}}.',
 * $1 is a spammed domain name.',
 
 # Info page
-'pageinfo-title' => 'Page title for action=info.
-
+'pageinfo-title' => 'Page title for action=info. Parameters:
 * $1 is the page name',
-'pageinfo-header-edits' => 'Table section header in action=info.
-{{Identical|Edit}}',
-'pageinfo-header-watchlist' => 'Table section header in action=info.',
-'pageinfo-header-views' => 'Table section header in action=info.
-{{Identical|View}}',
-'pageinfo-subjectpage' => 'Table header in action=info.
-{{Identical|Page}}',
-'pageinfo-talkpage' => 'Table header in action=info.',
+'pageinfo-header-basic' => 'Table section header in action=info.',
+'pageinfo-header-edits' => 'Table section header in action=info.',
+'pageinfo-header-restrictions' => 'Table section header in action=info.',
+'pageinfo-header-properties' => 'Table section header in action=info.',
+'pageinfo-display-title' => 'The title that is displayed when the page is viewed.',
+'pageinfo-default-sort' => 'The key by which the page is sorted in categories by default.',
+'pageinfo-length' => 'The length of the page, in bytes.',
+'pageinfo-article-id' => 'The numeric identifier of the page.',
+'pageinfo-robot-policy' => 'The search engine status of the page.',
+'pageinfo-views' => 'The number of times the page has been viewed.',
+'pageinfo-watchers' => 'The number of users watching the page.',
+'pageinfo-redirects-name' => 'The number of redirects to the page.',
+'pageinfo-redirects-value' => 'Parameters:
+* $1 is the number of redirects to the page.',
+'pageinfo-subpages-name' => 'The number of subpages of the page.',
+'pageinfo-subpages-value' => 'Parameters:
+* $1 is the number of subpages of the page.
+* $2 is the number of subpages of the page that are redirects.
+* $3 is the number of subpages of the page that are not redirects.',
+'pageinfo-firstuser' => 'The user who created the page.',
+'pageinfo-firsttime' => 'The date and time the page was created.',
+'pageinfo-lastuser' => 'The last user who edited the page.',
+'pageinfo-lasttime' => 'The date and time the page was last edited.',
+'pageinfo-edits' => 'The total number of times the page has been edited.',
+'pageinfo-authors' => 'The total number of users who have edited the page.',
+'pageinfo-recent-edits' => 'The number of times the page has been edited recently.',
+'pageinfo-recent-authors' => 'The number of users who have edited the page recently.',
+'pageinfo-restriction' => 'Parameters:
+* $1 is the type of page protection.',
+'pageinfo-magic-words' => 'The list of magic words on the page. Parameters:
+* $1 is the number of magic words on the page.',
+'pageinfo-hidden-categories' => 'The list of hidden categories on the page. Parameters:
+* $1 is the number of hidden categories on the page.',
+'pageinfo-templates' => 'The list of templates transcluded within the page. Parameters:
+* $1 is the number of templates transcluded within the page.',
 
 # Skin names
 'skinname-standard' => '{{optional}}
index bed7e5a..57941a2 100644 (file)
@@ -2661,16 +2661,33 @@ $wgMessageStructure = array(
        ),
        'info' => array(
                'pageinfo-title',
+               'pageinfo-header-basic',
                'pageinfo-header-edits',
-               'pageinfo-header-watchlist',
-               'pageinfo-header-views',
-               'pageinfo-subjectpage',
-               'pageinfo-talkpage',
+               'pageinfo-header-restrictions',
+               'pageinfo-header-properties',
+               'pageinfo-display-title',
+               'pageinfo-default-sort',
+               'pageinfo-length',
+               'pageinfo-article-id',
+               'pageinfo-robot-policy',
+               'pageinfo-views',
                'pageinfo-watchers',
+               'pageinfo-redirects-name',
+               'pageinfo-redirects-value',
+               'pageinfo-subpages-name',
+               'pageinfo-subpages-value',
+               'pageinfo-firstuser',
+               'pageinfo-firsttime',
+               'pageinfo-lastuser',
+               'pageinfo-lasttime',
                'pageinfo-edits',
                'pageinfo-authors',
-               'pageinfo-views',
-               'pageinfo-viewsperedit',
+               'pageinfo-recent-edits',
+               'pageinfo-recent-authors',
+               'pageinfo-restriction',
+               'pageinfo-magic-words',
+               'pageinfo-hidden-categories',
+               'pageinfo-templates',
        ),
        'skin' => array(
                'skinname-standard',