* Completely rewriting and reformatting the code of the localisation statistics utili...
authorRotem Liss <rotem@users.mediawiki.org>
Sun, 6 Aug 2006 14:06:57 +0000 (14:06 +0000)
committerRotem Liss <rotem@users.mediawiki.org>
Sun, 6 Aug 2006 14:06:57 +0000 (14:06 +0000)
* Introducing the concept of translatable messages to the languages object, and using it instead of the English messages.
* Adding ignored messages to the obsolete messages list.
* Removing the message "metadata-fields" from the ignored messages list, as it contains help in the local language.
* Fixing a whitespace in zh-yue messages file.

languages/MessagesZh_yue.php
maintenance/checkLanguage.php
maintenance/languages.inc
maintenance/transstat.php

index 5ccf0b6..663550d 100644 (file)
@@ -18,13 +18,13 @@ function checkLanguage( $code ) {
        global $wgLanguages, $wgHideMessages;
 
        # Get messages number
-       $englishMessagesNumber = count( $wgLanguages->getMessagesFor( 'en' ) );
+       $translatableMessagesNumber = count( $wgLanguages->getTranslatableMessages() );
        $localMessagesNumber = count( $wgLanguages->getMessagesFor( $code ) );
 
        # Untranslated messages
        $untranslatedMessages = $wgLanguages->getUntranslatedMessages( $code );
        $untranslatedMessagesNumber = count( $untranslatedMessages );
-       $wgLanguages->outputMessagesList( $untranslatedMessages, "\n$untranslatedMessagesNumber messages of $englishMessagesNumber are not translated to $code, but exist in en:", $wgHideMessages );
+       $wgLanguages->outputMessagesList( $untranslatedMessages, "\n$untranslatedMessagesNumber messages of $translatableMessagesNumber are not translated to $code, but exist in en:", $wgHideMessages );
 
        # Duplicate messages
        $duplicateMessages = $wgLanguages->getDuplicateMessages( $code );
@@ -34,7 +34,7 @@ function checkLanguage( $code ) {
        # Obsolete messages
        $obsoleteMessages = $wgLanguages->getObsoleteMessages( $code );
        $obsoleteMessagesNumber = count( $obsoleteMessages );
-       $wgLanguages->outputMessagesList( $obsoleteMessages, "\n$obsoleteMessagesNumber messages of $localMessagesNumber are not exist in en, but still exist in $code:", $wgHideMessages );
+       $wgLanguages->outputMessagesList( $obsoleteMessages, "\n$obsoleteMessagesNumber messages of $localMessagesNumber are not exist in en (or are in the ignored list), but still exist in $code:", $wgHideMessages );
 
        # Messages without variables
        $messagesWithoutVariables = $wgLanguages->getMessagesWithoutVariables( $code );
index f6767da..4f2031c 100644 (file)
@@ -9,6 +9,7 @@
 class languages {
        private $mList = array();
        private $mMessages = array();
+       private $mTranslatableMessages = array();
        private $mIgnoredMessages = array(
                'sidebar',
                'addsection',
@@ -24,7 +25,6 @@ class languages {
                'loginend',
                'loginlanguagelinks',
                'markaspatrolledlink',
-               'metadata-fields', // Objection, contains help
                'newarticletextanon',
                'noarticletextanon',
                'number_of_watching_users_RCview',
@@ -80,6 +80,14 @@ class languages {
                                require( $filename );
                                if ( isset( $messages ) ) {
                                        $this->mMessages[$code] = $messages;
+                                       if ( $code == 'en' ) {
+                                               $this->mTranslatableMessages = $this->mMessages['en'];
+                                               foreach ( array_keys( $this->mTranslatableMessages ) as $key ) {
+                                                       if ( in_array( $key, $this->mIgnoredMessages ) ) {
+                                                               unset( $this->mTranslatableMessages[$key] );
+                                                       }
+                                               }
+                                       }
                                } else {
                                        $this->mMessages[$code] = array();
                                }
@@ -103,12 +111,34 @@ class languages {
        }
 
        /**
-        * Get all the messages of all the languages.
+        * Get all the messages which are translatable - not ignored messages.
+        *
+        * @param $code The langauge code.
+        *
+        * @return The messages in this language.
+        */
+       public function getTranslatableMessages() {
+               $this->loadMessages( 'en' );
+               return $this->mTranslatableMessages;
+       }
+
+       /**
+        * Get the translated messages for a specific language.
+        *
+        * @param $code The langauge code.
+        *
+        * @return The translated messages for this language.
         */
-       public function getAllMessages() {
-               foreach ( $this->mList as $code ) {
-                       $this->getMessages( $code );
+       public function getTranslatedMessages( $code ) {
+               $this->loadMessages( 'en' );
+               $this->loadMessages( $code );
+               $translatedMessages = array();
+               foreach ( $this->mTranslatableMessages as $key => $value ) {
+                       if ( isset( $this->mMessages[$code][$key] ) ) {
+                               $translatedMessages[$key] = $value;
+                       }
                }
+               return $translatedMessages;
        }
 
        /**
@@ -122,8 +152,8 @@ class languages {
                $this->loadMessages( 'en' );
                $this->loadMessages( $code );
                $untranslatedMessages = array();
-               foreach ( $this->mMessages['en'] as $key => $value ) {
-                       if ( !isset( $this->mMessages[$code][$key] ) && !in_array( $key, $this->mIgnoredMessages ) ) {
+               foreach ( $this->mTranslatableMessages as $key => $value ) {
+                       if ( !isset( $this->mMessages[$code][$key] ) ) {
                                $untranslatedMessages[$key] = $value;
                        }
                }
@@ -142,7 +172,7 @@ class languages {
                $this->loadMessages( $code );
                $duplicateMessages = array();
                foreach ( $this->mMessages[$code] as $key => $value ) {
-                       if ( @$this->mMessages['en'][$key] == $value ) {
+                       if ( @$this->mTranslatableMessages[$key] == $value ) {
                                $duplicateMessages[$key] = $value;
                        }
                }
@@ -161,7 +191,7 @@ class languages {
                $this->loadMessages( $code );
                $obsoleteMessages = array();
                foreach ( $this->mMessages[$code] as $key => $value ) {
-                       if ( !isset( $this->mMessages['en'][$key] ) ) {
+                       if ( !isset( $this->mTranslatableMessages[$key] ) ) {
                                $obsoleteMessages[$key] = $value;
                        }
                }
@@ -181,10 +211,10 @@ class languages {
                $variables = array( '\$1', '\$2', '\$3', '\$4', '\$5', '\$6', '\$7', '\$8', '\$9' );
                $messagesWithoutVariables = array();
                foreach ( $this->mMessages[$code] as $key => $value ) {
-                       if ( isset( $this->mMessages['en'][$key] ) ) {
+                       if ( isset( $this->mTranslatableMessages[$key] ) ) {
                                $missing = array();
                                foreach ( $variables as $var ) {
-                                       if ( preg_match( "/$var/sU", $this->mMessages['en'][$key] ) &&
+                                       if ( preg_match( "/$var/sU", $this->mTranslatableMessages[$key] ) &&
                                                !preg_match( "/$var/sU", $value ) ) {
                                                $missing[] = str_replace( '\$', '$', $var );
                                        }
@@ -209,7 +239,7 @@ class languages {
                $this->loadMessages( $code );
                $emptyMessages = array();
                foreach ( $this->mMessages[$code] as $key => $value ) {
-                       if ( isset( $this->mMessages['en'][$key] ) &&
+                       if ( isset( $this->mTranslatableMessages[$key] ) &&
                                ( $this->mMessages[$code][$key] === '' || $this->mMessages[$code][$key] === '-' ) ) {
                                $emptyMessages[$key] = $value;
                        }
@@ -229,7 +259,7 @@ class languages {
                $this->loadMessages( $code );
                $messagesWithWhitespace = array();
                foreach ( $this->mMessages[$code] as $key => $value ) {
-                       if ( isset( $this->mMessages['en'][$key] ) && $this->mMessages['en'][$key] !== '' &&
+                       if ( isset( $this->mTranslatableMessages[$key] ) && $this->mTranslatableMessages[$key] !== '' &&
                                $value !== rtrim( $value ) ) {
                                $messagesWithWhitespace[$key] = $value;
                        }
@@ -256,7 +286,7 @@ class languages {
                $wrongPhrases = '~(' . implode( '|', $wrongPhrases ) . ')~sDu';
                $nonXHTMLMessages = array();
                foreach ( $this->mMessages[$code] as $key => $value ) {
-                       if ( isset( $this->mMessages['en'][$key] ) && preg_match( $wrongPhrases, $value ) ) {
+                       if ( isset( $this->mTranslatableMessages[$key] ) && preg_match( $wrongPhrases, $value ) ) {
                                $nonXHTMLMessages[$key] = $value;
                        }
                }
@@ -290,7 +320,7 @@ class languages {
                $wrongRegExp = '/(' . implode( '|', array_values( $wrongChars ) ) . ')/sDu';
                $nonXHTMLMessages = array();
                foreach ( $this->mMessages[$code] as $key => $value ) {
-                       if ( isset( $this->mMessages['en'][$key] ) && preg_match( $wrongRegExp, $value ) ) {
+                       if ( isset( $this->mTranslatableMessages[$key] ) && preg_match( $wrongRegExp, $value ) ) {
                                foreach ( $wrongChars as $viewableChar => $hiddenChar ) {
                                        $value = str_replace( $hiddenChar, $viewableChar, $value );
                                }
index ddcb840..0af80b2 100644 (file)
 <?php
 /**
+ * Statistics about the localisation.
+ *
  * @package MediaWiki
  * @subpackage Maintenance
  *
  * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
  * @author Ashar Voultoiz <thoane@altern.org>
- * @bug 2499
  *
  * Output is posted from time to time on:
  * http://meta.wikimedia.org/wiki/Localization_statistics
  */
 
-/** */
-require_once('commandLine.inc');
-require_once('languages.inc');
-
-if( isset($options['help']) ) { usage(); wfDie(); }
-// default output is WikiText
-if( !isset($options['output']) ) { $options['output']='wiki'; }
+require_once( 'commandLine.inc' );
+require_once( 'languages.inc' );
 
+if ( isset( $options['help'] ) ) {
+       showUsage();
+}
+# Default output is WikiText
+if ( !isset( $options['output'] ) ) {
+       $options['output'] = 'wiki';
+}
 
 /** Print a usage message*/
-function usage() {
-print <<<END
-Usage: php transstat.php [--help] [--output:csv|text|wiki] [--showdupes]
-         --help : this helpful message
-      --showold : show old messages that are not in Messages.php
-       --output : select an output engine one of:
-                    * 'csv'  : Comma Separated Values.
-                    * 'none' : Nothing, usefull with --showdupes
-                    * 'wiki' : MediaWiki syntax (default).
-                    * 'text' : Text with tabs.
-Example: php transstat.php --showdupes --output=none
-
+function showUsage() {
+       print <<<END
+Usage: php transstat.php [--help] [--output=csv|text|wiki]
+       --help : this helpful message
+       --output : select an output engine one of:
+               * 'csv'  : Comma Separated Values.
+               * 'wiki' : MediaWiki syntax (default).
+               * 'text' : Text with tabs.
+Example: php maintenance/transstat.php --output=text
 
 END;
+       exit();
 }
 
-
 /** A general output object. Need to be overriden */
 class statsOutput {
-       var $output; // buffer that contain the text
-       function statsOutput() { $this->output='';}
-       function getContent() { return $this->output;}
-
-       function formatPercent($subset, $total, $revert=false, $accuracy=2) {
+       function formatPercent( $subset, $total, $revert = false, $accuracy = 2 ) {
                return @sprintf( '%.' . $accuracy . 'f%%', 100 * $subset / $total );
        }
 
-       // Override the next methods
-       function heading() {}
-       function footer() {}
-       function blockstart() {}
-       function blockend() {}
-       function element($in, $heading=false) {}
-}
-
-/** Outputs nothing ! */
-class noneStatsOutput extends statsOutput {
-       function getContent() { return NULL;}
+       # Override the following methods
+       function heading() {
+       }
+       function footer() {
+       }
+       function blockstart() {
+       }
+       function blockend() {
+       }
+       function element( $in, $heading = false ) {
+       }
 }
 
 /** Outputs WikiText */
 class wikiStatsOutput extends statsOutput {
        function heading() {
-               $this->output .= "{| border=2 cellpadding=4 cellspacing=0 style=\"background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse;\" width=100%\n";
+               echo "'''Note:''' These statistics can be generated by running <code>php maintenance/transstat.php</code>.\n\n";
+               echo "{| border=2 cellpadding=4 cellspacing=0 style=\"background: #f9f9f9; border: 1px #aaa solid; border-collapse: collapse;\" width=100%\n";
+       }
+       function footer() {
+               echo "|}\n";
        }
-       function footer()     { $this->output .= "|}\n"; }
-       function blockstart() { $this->output .= "|-\n"; }
-       function blockend()   { $this->output .= ''; }
-       function element($in, $heading = false) {
-               $this->output .= ($heading ? '!' : '|') . " $in\n";
+       function blockstart() {
+               echo "|-\n";
        }
-       function formatPercent($subset, $total, $revert=false, $accuracy=2) {
+       function blockend() {
+               echo '';
+       }
+       function element( $in, $heading = false ) {
+               echo ($heading ? '!' : '|') . " $in\n";
+       }
+       function formatPercent( $subset, $total, $revert = false, $accuracy = 2 ) {
                $v = @round(255 * $subset / $total);
-               if($revert) $v = 255 - $v;
-               if($v < 128) {
-                       // red to yellow
+               if ( $revert ) {
+                       $v = 255 - $v;
+               }
+               if ( $v < 128 ) {
+                       # Red to Yellow
                        $red = 'FF';
-                       $green = sprintf('%02X', 2*$v);
+                       $green = sprintf( '%02X', 2 * $v );
                } else {
-                       // yellow to green
-                       $red   = sprintf('%02X', 2*(255 -$v) );
+                       # Yellow to Green
+                       $red = sprintf('%02X', 2 * ( 255 - $v ) );
                        $green = 'FF';
                }
-               $blue  = '00';
-               $color = $red.$green.$blue;
+               $blue = '00';
+               $color = $red . $green . $blue;
 
-               $percent = statsOutput::formatPercent($subset, $total, $revert, $accuracy);
-               return 'bgcolor="#'.$color.'" | '.$percent;
+               $percent = statsOutput::formatPercent( $subset, $total, $revert, $accuracy );
+               return 'bgcolor="#'. $color .'" | '. $percent;
        }
 }
 
 /** Output text. To be used on a terminal for example. */
 class textStatsOutput extends statsOutput {
-       function element($in, $heading = false) {
-               $this->output .= $in."\t";
+       function element( $in, $heading = false ) {
+               echo $in."\t";
+       }
+       function blockend() {
+               echo "\n";
        }
-       function blockend(){ $this->output .="\n";}
 }
 
 /** csv output. Some people love excel */
 class csvStatsOutput extends statsOutput {
-       function element($in, $heading = false) {
-               $this->output .= $in.";";
+       function element( $in, $heading = false ) {
+               echo $in . ";";
        }
-       function blockend(){ $this->output .="\n";}
-}
-
-
-function redundant(&$arr, $langcode) {
-       $redundant = 0;
-       $englishMessages = Language::getMessagesFor( 'en' );
-       foreach(array_keys($arr) as $key) {
-               if ( !isset( $englishMessages[$key] ) ) {
-                       global $options;
-                       if( isset( $options['showold'] ) ) {
-                               print "Deprecated [$langcode]: $key\n";
-                       }
-                       ++$redundant;
-               }
+       function blockend() {
+               echo "\n";
        }
-       return $redundant;
 }
 
-// Select an output engine
-switch ($options['output']) {
-       case 'csv':
-               $out = new csvStatsOutput(); break;
-       case 'none':
-               $out = new noneStatsOutput(); break;
-       case 'text':
-               $out = new textStatsOutput(); break;
+# Select an output engine
+switch ( $options['output'] ) {
        case 'wiki':
-               $out = new wikiStatsOutput(); break;
+               $wgOut = new wikiStatsOutput();
+               break;
+       case 'text':
+               $wgOut = new textStatsOutput();
+               break;
+       case 'csv':
+               $wgOut = new csvStatsOutput();
+               break;
        default:
-               usage(); wfDie();
-       break;
+               showUsage();
 }
 
-$langTool = new languages();
-
-//  Load message and compute stuff
-$msgs = array();
-foreach ( $langTool->getList() as $langcode ) {
-       // Since they aren't loaded by default..
-       require( Language::getFileName( "$IP/languages/Messages", $langcode, ".php" ) );
-       if( isset( $messages ) ) {
-               $msgs[$wgContLang->lcfirst($langcode)] = array(
-                       'total' => count( $messages ),
-                       'redundant' => redundant( $messages, $langcode ),
-               );
-       } else {
-               $msgs[$wgContLang->lcfirst($langcode)] = array(
-                       'total' => 0,
-                       'redundant' => 0,
-               );
-       }
-       unset( $messages );
-}
+# Languages
+$wgLanguages = new languages();
+
+# Header
+$wgOut->heading();
+$wgOut->blockstart();
+$wgOut->element( 'Language', true );
+$wgOut->element( 'Translated', true );
+$wgOut->element( '%', true );
+$wgOut->element( 'Possibly untranslated', true );
+$wgOut->element( '%', true );
+$wgOut->element( 'Obsolete', true );
+$wgOut->element( '%', true );
+$wgOut->blockend();
+
+foreach ( $wgLanguages->getList() as $code ) {
+       # Don't check English
+       if ( $code == 'en' ) {
+               continue;
+       }
+       
+       # FIXME - temporary hack for this non-language won't appear
+       if ( $code == 'enRTL' ) {
+               continue;
+       }
 
-// Top entry
-$out->heading();
-$out->blockstart();
-$out->element('Language', true);
-$out->element('Translated', true);
-$out->element('%', true);
-$out->element('Untranslated', true);
-$out->element('%', true);
-$out->element('Redundant', true);
-$out->element('%', true);
-$out->blockend();
-
-// Generate rows
-foreach($msgs as $lang => $stats) {
-       $out->blockstart();
-       // Language
-       $out->element($wgContLang->getLanguageName(strtr($lang, '_', '-')) . " ($lang)");
-       // Translated
-       $out->element($stats['total'] . '/' . $msgs['en']['total']);
-       // % Translated
-       $out->element($out->formatPercent($stats['total'], $msgs['en']['total']));
-       // Untranslated
-       $out->element($msgs['en']['total'] - $stats['total']);
-       // % Untranslated
-       $out->element($out->formatPercent($msgs['en']['total'] - $stats['total'], $msgs['en']['total'], true));
-       // Redundant & % Redundant
-       if($stats['redundant'] =='NC') {
-               $out->element('NC');
-               $out->element('NC');
-       } else {
-               $out->element($stats['redundant'] . '/' . $stats['total']);
-               $out->element($out->formatPercent($stats['redundant'],  $stats['total'],true));
-       }
-       $out->blockend();
+       # Calculate the numbers
+       $name = $wgLang->getLanguageName( $code );
+       $translatableMessagesNumber = count( $wgLanguages->getTranslatableMessages() );
+       $localMessagesNumber = count( $wgLanguages->getMessagesFor( $code ) );
+       $translatedMessagesNumber = count( $wgLanguages->getTranslatedMessages( $code ) );
+       $translatedMessagesPercent = $wgOut->formatPercent( $translatedMessagesNumber, $translatableMessagesNumber );
+       $duplicateMessagesNumber = count( $wgLanguages->getDuplicateMessages( $code ) );
+       $duplicateMessagesPercent = $wgOut->formatPercent( $duplicateMessagesNumber, $translatedMessagesNumber, true );
+       $obsoleteMessagesNumber = count( $wgLanguages->getObsoleteMessages( $code ) );
+       $obsoleteMessagesPercent = $wgOut->formatPercent( $obsoleteMessagesNumber, $translatedMessagesNumber, true );
+
+       # Output them
+       $wgOut->blockstart();
+       $wgOut->element( "$name ($code)" );
+       $wgOut->element( "$translatedMessagesNumber/$translatableMessagesNumber" );
+       $wgOut->element( $translatedMessagesPercent );
+       $wgOut->element( "$duplicateMessagesNumber/$translatedMessagesNumber" );
+       $wgOut->element( $duplicateMessagesPercent );
+       $wgOut->element( "$obsoleteMessagesNumber/$translatedMessagesNumber" );
+       $wgOut->element( $obsoleteMessagesPercent );
+       $wgOut->blockend();
 }
-$out->footer();
 
-// Final output
-echo $out->getContent();
+# Footer
+$wgOut->footer();
+
 ?>