enhance size tooltip on changelist
[lhc/web/wiklou.git] / languages / Language.php
index a712246..56367db 100644 (file)
@@ -61,6 +61,7 @@ class Language {
 
        var $mVariants, $mCode, $mLoaded = false;
        var $mMagicExtensions = array(), $mMagicHookDone = false;
+       private $mHtmlCode = null;
 
        var $mNamespaceIds, $namespaceNames, $namespaceAliases;
        var $dateFormatStrings = array();
@@ -637,7 +638,8 @@ class Language {
        }
 
        /**
-        * Get language names, indexed by code.
+        * Get native language names, indexed by code.
+        * Only those defined in MediaWiki, no other data like CLDR.
         * If $customisedOnly is true, only returns codes with a messages file
         *
         * @param $customisedOnly bool
@@ -657,7 +659,6 @@ class Language {
                        return $allNames;
                }
 
-               global $IP;
                $names = array();
                // We do this using a foreach over the codes instead of a directory
                // loop so that messages files in extensions will work correctly.
@@ -699,6 +700,8 @@ class Language {
        }
 
        /**
+        * Get the native language name of $code.
+        * Only if defined in MediaWiki, no other data like CLDR.
         * @param $code string
         * @return string
         */
@@ -823,6 +826,7 @@ class Language {
         *    xij  j (day number) in Iranian calendar
         *    xiF  F (month name) in Iranian calendar
         *    xin  n (month number) in Iranian calendar
+        *    xiy  y (two digit year) in Iranian calendar
         *    xiY  Y (full year) in Iranian calendar
         *
         *    xjj  j (day number) in Hebrew calendar
@@ -1041,7 +1045,7 @@ class Language {
                                        if ( !$unix ) {
                                                $unix = wfTimestamp( TS_UNIX, $ts );
                                        }
-                                       $num = date( 'o', $unix );
+                                       $num = gmdate( 'o', $unix );
                                        break;
                                case 'Y':
                                        $num = substr( $ts, 0, 4 );
@@ -1085,6 +1089,12 @@ class Language {
                                case 'y':
                                        $num = substr( $ts, 2, 2 );
                                        break;
+                               case 'xiy':
+                                       if ( !$iranian ) {
+                                               $iranian = self::tsToIranian( $ts );
+                                       }
+                                       $num = substr( $iranian[0], -2 );
+                                       break;
                                case 'a':
                                        $s .= intval( substr( $ts, 8, 2 ) ) < 12 ? 'am' : 'pm';
                                        break;
@@ -1650,7 +1660,7 @@ class Language {
         *            get user timecorrection setting)
         * @return int
         */
-       function userAdjust( $ts, $tz = false ) {
+       function userAdjust( $ts, $tz = false ) {
                global $wgUser, $wgLocalTZoffset;
 
                if ( $tz === false ) {
@@ -1854,6 +1864,7 @@ class Language {
         *             - true: use user's preference
         *             - false: use default preference
         *             - string: format to use
+        * @since 1.19
         * @return String
         */
        private function internalUserTimeAndDate( $type, $ts, User $user, array $options ) {
@@ -1892,6 +1903,7 @@ class Language {
         *             - true: use user's preference
         *             - false: use default preference
         *             - string: format to use
+        * @since 1.19
         * @return String
         */
        public function userDate( $ts, User $user, array $options = array() ) {
@@ -1914,6 +1926,7 @@ class Language {
         *             - true: use user's preference
         *             - false: use default preference
         *             - string: format to use
+        * @since 1.19
         * @return String
         */
        public function userTime( $ts, User $user, array $options = array() ) {
@@ -1936,6 +1949,7 @@ class Language {
         *             - true: use user's preference
         *             - false: use default preference
         *             - string: format to use
+        * @since 1.19
         * @return String
         */
        public function userTimeAndDate( $ts, User $user, array $options = array() ) {
@@ -2668,7 +2682,7 @@ class Language {
          * @param $nocommafy Bool: set to true for special numbers like dates
          * @return string
          */
-       function formatNum( $number, $nocommafy = false ) {
+       public function formatNum( $number, $nocommafy = false ) {
                global $wgTranslateNumerals;
                if ( !$nocommafy ) {
                        $number = $this->commafy( $number );
@@ -2715,6 +2729,9 @@ class Language {
         */
        function commafy( $_ ) {
                $digitGroupingPattern = $this->digitGroupingPattern();
+               if ( $_ === null ) {
+                       return '';
+               }
 
                if ( !$digitGroupingPattern || $digitGroupingPattern === "###,###,###" ) {
                        // default grouping is at thousands,  use the same for ###,###,### pattern too.
@@ -2725,7 +2742,7 @@ class Language {
                        if ( intval( $_ ) < 0 ) {
                                // For negative numbers apply the algorithm like positive number and add sign.
                                $sign =  "-";
-                               $_ = substr( $_,1 );
+                               $_ = substr( $_, 1 );
                        }
                        $numberpart = array();
                        $decimalpart = array();
@@ -2813,7 +2830,7 @@ class Language {
         * @return string
         */
        function commaList( array $list ) {
-               return implode(                 
+               return implode(
                        wfMsgExt(
                                'comma-separator',
                                array( 'parsemag', 'escapenoentities', 'language' => $this )
@@ -2829,7 +2846,7 @@ class Language {
         * @return string
         */
        function semicolonList( array $list ) {
-               return implode(                 
+               return implode(
                        wfMsgExt(
                                'semicolon-separator',
                                array( 'parsemag', 'escapenoentities', 'language' => $this )
@@ -2844,7 +2861,7 @@ class Language {
         * @return string
         */
        function pipeList( array $list ) {
-               return implode(                 
+               return implode(
                        wfMsgExt(
                                'pipe-separator',
                                array( 'escapenoentities', 'language' => $this )
@@ -3244,7 +3261,7 @@ class Language {
         * @param $text String
         * @return String
         */
-       function segmentForDiff( $text ) {
+       public function segmentForDiff( $text ) {
                return $text;
        }
 
@@ -3254,7 +3271,7 @@ class Language {
         * @param $text String
         * @return String
         */
-       function unsegmentForDiff( $text ) {
+       public function unsegmentForDiff( $text ) {
                return $text;
        }
 
@@ -3262,7 +3279,7 @@ class Language {
         * Return the LanguageConverter used in the Language
         * @return LanguageConverter
         */
-       function getConverter() {
+       public function getConverter() {
                return $this->mConverter;
        }
 
@@ -3272,7 +3289,7 @@ class Language {
         * @param $text string
         * @return array
         */
-       function autoConvertToAllVariants( $text ) {
+       public function autoConvertToAllVariants( $text ) {
                return $this->mConverter->autoConvertToAllVariants( $text );
        }
 
@@ -3282,18 +3299,17 @@ class Language {
         * @param $text string
         * @return string
         */
-       function convert( $text ) {
+       public function convert( $text ) {
                return $this->mConverter->convert( $text );
        }
 
-
        /**
         * Convert a Title object to a string in the preferred variant
         *
         * @param $title Title
         * @return string
         */
-       function convertTitle( $title ) {
+       public function convertTitle( $title ) {
                return $this->mConverter->convertTitle( $title );
        }
 
@@ -3302,15 +3318,16 @@ class Language {
         *
         * @return bool
         */
-       function hasVariants() {
+       public function hasVariants() {
                return sizeof( $this->getVariants() ) > 1;
        }
 
        /**
         * Check if the language has the specific variant
+        * @param $variant string
         * @return bool
         */
-       function hasVariant( $variant ) {
+       public function hasVariant( $variant ) {
                return (bool)$this->mConverter->validateVariant( $variant );
        }
 
@@ -3320,7 +3337,7 @@ class Language {
         * @param $text string
         * @return string
         */
-       function armourMath( $text ) {
+       public function armourMath( $text ) {
                return $this->mConverter->armourMath( $text );
        }
 
@@ -3331,7 +3348,7 @@ class Language {
         * @return string
         * @todo this should get integrated somewhere sane
         */
-       function convertHtml( $text, $isTitle = false ) {
+       public function convertHtml( $text, $isTitle = false ) {
                return htmlspecialchars( $this->convert( $text, $isTitle ) );
        }
 
@@ -3339,7 +3356,7 @@ class Language {
         * @param $key string
         * @return string
         */
-       function convertCategoryKey( $key ) {
+       public function convertCategoryKey( $key ) {
                return $this->mConverter->convertCategoryKey( $key );
        }
 
@@ -3349,28 +3366,28 @@ class Language {
         *
         * @return array an array of language codes
         */
-       function getVariants() {
+       public function getVariants() {
                return $this->mConverter->getVariants();
        }
 
        /**
         * @return string
         */
-       function getPreferredVariant() {
+       public function getPreferredVariant() {
                return $this->mConverter->getPreferredVariant();
        }
 
        /**
         * @return string
         */
-       function getDefaultVariant() {
+       public function getDefaultVariant() {
                return $this->mConverter->getDefaultVariant();
        }
 
        /**
         * @return string
         */
-       function getURLVariant() {
+       public function getURLVariant() {
                return $this->mConverter->getURLVariant();
        }
 
@@ -3386,7 +3403,7 @@ class Language {
         *      we need to transclude a template or update a category's link
         * @return null the input parameters may be modified upon return
         */
-       function findVariantLink( &$link, &$nt, $ignoreOtherCond = false ) {
+       public function findVariantLink( &$link, &$nt, $ignoreOtherCond = false ) {
                $this->mConverter->findVariantLink( $link, $nt, $ignoreOtherCond );
        }
 
@@ -3401,7 +3418,7 @@ class Language {
         *
         * @return string
         */
-       function convertLinkToAllVariants( $text ) {
+       public function convertLinkToAllVariants( $text ) {
                return $this->mConverter->convertLinkToAllVariants( $text );
        }
 
@@ -3422,7 +3439,7 @@ class Language {
         *
         * @return string
         */
-       function getParsedTitle() {
+       public function getParsedTitle() {
                return $this->mConverter->getParsedTitle();
        }
 
@@ -3434,7 +3451,7 @@ class Language {
         * @param $noParse bool
         * @return string the tagged text
         */
-       function markNoConversion( $text, $noParse = false ) {
+       public function markNoConversion( $text, $noParse = false ) {
                return $this->mConverter->markNoConversion( $text, $noParse );
        }
 
@@ -3444,7 +3461,7 @@ class Language {
         *
         * @return string
         */
-       function linkTrail() {
+       public function linkTrail() {
                return self::$dataCache->getItem( $this->mCode, 'linkTrail' );
        }
 
@@ -3460,23 +3477,30 @@ class Language {
         *
         * @return string
         */
-       function getCode() {
+       public function getCode() {
                return $this->mCode;
        }
 
        /**
         * Get the code in Bcp47 format which we can use
         * inside of html lang="" tags.
+        * @since 1.19
+        * @return string
         */
-       function getHtmlCode() {
-               return wfBcp47( $this->getCode() );
+       public function getHtmlCode() {
+               if ( is_null( $this->mHtmlCode ) ) {
+                       $this->mHtmlCode = wfBCP47( $this->getCode() );
+               }
+               return $this->mHtmlCode;
        }
 
        /**
         * @param $code string
         */
-       function setCode( $code ) {
+       public function setCode( $code ) {
                $this->mCode = $code;
+               // Ensure we don't leave an incorrect html code lying around
+               $this->mHtmlCode = null;
        }
 
        /**
@@ -3486,7 +3510,7 @@ class Language {
         * @param $suffix string Append this to the filename
         * @return string $prefix . $mangledCode . $suffix
         */
-       static function getFileName( $prefix = 'Language', $code, $suffix = '.php' ) {
+       public static function getFileName( $prefix = 'Language', $code, $suffix = '.php' ) {
                // Protect against path traversal
                if ( !Language::isValidCode( $code )
                        || strcspn( $code, ":/\\\000" ) !== strlen( $code ) )
@@ -3504,7 +3528,7 @@ class Language {
         * @param $suffix string Suffix after the language code
         * @return string Language code, or false if $prefix or $suffix isn't found
         */
-       static function getCodeFromFileName( $filename, $prefix = 'Language', $suffix = '.php' ) {
+       public static function getCodeFromFileName( $filename, $prefix = 'Language', $suffix = '.php' ) {
                $m = null;
                preg_match( '/' . preg_quote( $prefix, '/' ) . '([A-Z][a-z_]+)' .
                        preg_quote( $suffix, '/' ) . '/', $filename, $m );
@@ -3518,7 +3542,7 @@ class Language {
         * @param $code string
         * @return string
         */
-       static function getMessagesFileName( $code ) {
+       public static function getMessagesFileName( $code ) {
                global $IP;
                $file = self::getFileName( "$IP/languages/messages/Messages", $code, '.php' );
                wfRunHooks( 'Language::getMessagesFileName', array( $code, &$file ) );
@@ -3529,7 +3553,7 @@ class Language {
         * @param $code string
         * @return string
         */
-       static function getClassFileName( $code ) {
+       public static function getClassFileName( $code ) {
                global $IP;
                return self::getFileName( "$IP/languages/classes/Language", $code, '.php' );
        }
@@ -3541,7 +3565,7 @@ class Language {
         *
         * @return false|string
         */
-       static function getFallbackFor( $code ) {
+       public static function getFallbackFor( $code ) {
                if ( $code === 'en' || !Language::isValidBuiltInCode( $code ) ) {
                        return false;
                } else {
@@ -3558,7 +3582,7 @@ class Language {
         * @param $code string Language code
         * @return array
         */
-       static function getFallbacksFor( $code ) {
+       public static function getFallbacksFor( $code ) {
                if ( $code === 'en' || !Language::isValidBuiltInCode( $code ) ) {
                        return array();
                } else {
@@ -3580,7 +3604,7 @@ class Language {
         *
         * @return array
         */
-       static function getMessagesFor( $code ) {
+       public static function getMessagesFor( $code ) {
                return self::getLocalisationCache()->getItem( $code, 'messages' );
        }
 
@@ -3592,7 +3616,7 @@ class Language {
         *
         * @return string
         */
-       static function getMessageFor( $key, $code ) {
+       public static function getMessageFor( $key, $code ) {
                return self::getLocalisationCache()->getSubitem( $code, 'messages', $key );
        }
 
@@ -3604,7 +3628,7 @@ class Language {
         * @param $code string Language code
         * @return array of message keys (strings)
         */
-       static function getMessageKeysFor( $code ) {
+       public static function getMessageKeysFor( $code ) {
                return self::getLocalisationCache()->getSubItemList( $code, 'messages' );
        }
 
@@ -3785,52 +3809,62 @@ class Language {
        }
 
        /**
+        * Format a bitrate for output, using an appropriate
+        * unit (bps, kbps, Mbps, Gbps, Tbps, Pbps, Ebps, Zbps or Ybps) according to the magnitude in question
+        *
         * @param $bps int
         * @return string
         */
        function formatBitrate( $bps ) {
-               $units = array( 'bps', 'kbps', 'Mbps', 'Gbps' );
+               $units = array( '', 'kilo', 'mega', 'giga', 'tera', 'peta', 'exa', 'zeta', 'yotta' );
                if ( $bps <= 0 ) {
-                       return $this->formatNum( $bps ) . $units[0];
+                       return str_replace( '$1', $this->formatNum( $bps ), $this->getMessageFromDB( 'bitrate-bits' ) );
                }
                $unitIndex = (int)floor( log10( $bps ) / 3 );
                $mantissa = $bps / pow( 1000, $unitIndex );
+
+               $maxIndex = count( $units ) - 1;
+
+               if ( $unitIndex  > $maxIndex ) {
+                       // Prevent code falling off end of $units array
+                       $mantissa *= ( $unitIndex - $maxIndex ) * 1000;
+                       $unitIndex = $maxIndex;
+               }
                if ( $mantissa < 10 ) {
                        $mantissa = round( $mantissa, 1 );
                } else {
                        $mantissa = round( $mantissa );
                }
-               return $this->formatNum( $mantissa ) . $units[$unitIndex];
+               $msg = "bitrate-{$units[$unitIndex]}bits";
+               $text = $this->getMessageFromDB( $msg );
+               return str_replace( '$1', $this->formatNum( $mantissa ), $text );
        }
 
        /**
         * Format a size in bytes for output, using an appropriate
-        * unit (B, KB, MB or GB) according to the magnitude in question
+        * unit (B, KB, MB, GB, TB, PB, EB, ZB or YB) according to the magnitude in question
         *
         * @param $size int Size to format
         * @return string Plain text (not HTML)
         */
        function formatSize( $size ) {
+               $sizes = array( '', 'kilo', 'mega', 'giga', 'tera', 'peta', 'exa', 'zeta', 'yotta' );
+               $index = 0;
+
+               $maxIndex = count( $sizes ) - 1;
+               while ( $size >= 1024 && $index < $maxIndex ) {
+                       $index++;
+                       $size /= 1024;
+               }
+
                // For small sizes no decimal places necessary
                $round = 0;
-               if ( $size > 1024 ) {
-                       $size = $size / 1024;
-                       if ( $size > 1024 ) {
-                               $size = $size / 1024;
-                               // For MB and bigger two decimal places are smarter
-                               $round = 2;
-                               if ( $size > 1024 ) {
-                                       $size = $size / 1024;
-                                       $msg = 'size-gigabytes';
-                               } else {
-                                       $msg = 'size-megabytes';
-                               }
-                       } else {
-                               $msg = 'size-kilobytes';
-                       }
-               } else {
-                       $msg = 'size-bytes';
+               if ( $index > 1 ) {
+                       // For MB and bigger two decimal places are smarter
+                       $round = 2;
                }
+               $msg = "size-{$sizes[$index]}bytes";
+
                $size = round( $size, $round );
                $text = $this->getMessageFromDB( $msg );
                return str_replace( '$1', $this->formatNum( $size ), $text );
@@ -3868,7 +3902,7 @@ class Language {
 
                # Make 'previous' link
                $prev = wfMessage( 'prevn' )->inLanguage( $this )->title( $title )->numParams( $limit )->text();
-               if( $offset > 0 ) {
+               if ( $offset > 0 ) {
                        $plink = $this->numLink( $title, max( $offset - $limit, 0 ), $limit,
                                $query, $prev, 'prevn-title', 'mw-prevlink' );
                } else {
@@ -3877,7 +3911,7 @@ class Language {
 
                # Make 'next' link
                $next = wfMessage( 'nextn' )->inLanguage( $this )->title( $title )->numParams( $limit )->text();
-               if( $atend ) {
+               if ( $atend ) {
                        $nlink = htmlspecialchars( $next );
                } else {
                        $nlink = $this->numLink( $title, $offset + $limit, $limit,
@@ -3886,7 +3920,7 @@ class Language {
 
                # Make links to set number of items per page
                $numLinks = array();
-               foreach( array( 20, 50, 100, 250, 500 ) as $num ) {
+               foreach ( array( 20, 50, 100, 250, 500 ) as $num ) {
                        $numLinks[] = $this->numLink( $title, $offset, $num,
                                $query, $this->formatNum( $num ), 'shown-title', 'mw-numlink' );
                }
@@ -3919,7 +3953,7 @@ class Language {
         *
         * @return string
         */
-       function getConvRuleTitle() {
+       public function getConvRuleTitle() {
                return $this->mConverter->getConvRuleTitle();
        }
 }