Add PLURAL support and "human readable" sizes for mediastatistics messages
[lhc/web/wiklou.git] / languages / Language.php
index 50ed513..69f518b 100644 (file)
@@ -147,7 +147,7 @@ class Language {
 
        /**
         * Cache for language names
-        * @var MapCacheLRU|null
+        * @var HashBagOStuff|null
         */
        static private $languageNameCache;
 
@@ -207,10 +207,7 @@ class Language {
         * @return Language
         */
        protected static function newFromCode( $code ) {
-               // Protect against path traversal below
-               if ( !Language::isValidCode( $code )
-                       || strcspn( $code, ":/\\\000" ) !== strlen( $code )
-               ) {
+               if ( !Language::isValidCode( $code ) ) {
                        throw new MWException( "Invalid language code \"$code\"" );
                }
 
@@ -224,7 +221,6 @@ class Language {
 
                // Check if there is a language class for the code
                $class = self::classFromCode( $code );
-               self::preloadLanguageClass( $class );
                if ( class_exists( $class ) ) {
                        $lang = new $class;
                        return $lang;
@@ -238,9 +234,8 @@ class Language {
                        }
 
                        $class = self::classFromCode( $fallbackCode );
-                       self::preloadLanguageClass( $class );
                        if ( class_exists( $class ) ) {
-                               $lang = Language::newFromCode( $fallbackCode );
+                               $lang = new $class;
                                $lang->setCode( $code );
                                return $lang;
                        }
@@ -341,17 +336,16 @@ class Language {
         */
        public static function isValidCode( $code ) {
                static $cache = array();
-               if ( isset( $cache[$code] ) ) {
-                       return $cache[$code];
+               if ( !isset( $cache[$code] ) ) {
+                       // People think language codes are html safe, so enforce it.
+                       // Ideally we should only allow a-zA-Z0-9-
+                       // but, .+ and other chars are often used for {{int:}} hacks
+                       // see bugs 37564, 37587, 36938
+                       $cache[$code] =
+                               // Protect against path traversal
+                               strcspn( $code, ":/\\\000&<>'\"" ) === strlen( $code )
+                               && !preg_match( MediaWikiTitleCodec::getTitleInvalidRegex(), $code );
                }
-               // People think language codes are html safe, so enforce it.
-               // Ideally we should only allow a-zA-Z0-9-
-               // but, .+ and other chars are often used for {{int:}} hacks
-               // see bugs 37564, 37587, 36938
-               $cache[$code] =
-                       strcspn( $code, ":/\\\000&<>'\"" ) === strlen( $code )
-                       && !preg_match( MediaWikiTitleCodec::getTitleInvalidRegex(), $code );
-
                return $cache[$code];
        }
 
@@ -411,35 +405,6 @@ class Language {
                return false;
        }
 
-       /**
-        * @param string $code
-        * @return string Name of the language class
-        */
-       public static function classFromCode( $code ) {
-               if ( $code == 'en' ) {
-                       return 'Language';
-               } else {
-                       return 'Language' . str_replace( '-', '_', ucfirst( $code ) );
-               }
-       }
-
-       /**
-        * Includes language class files
-        *
-        * @param string $class Name of the language class
-        */
-       public static function preloadLanguageClass( $class ) {
-               global $IP;
-
-               if ( $class === 'Language' ) {
-                       return;
-               }
-
-               if ( file_exists( "$IP/languages/classes/$class.php" ) ) {
-                       include_once "$IP/languages/classes/$class.php";
-               }
-       }
-
        /**
         * Get the LocalisationCache instance
         *
@@ -886,11 +851,11 @@ class Language {
                $cacheKey = $inLanguage === null ? 'null' : $inLanguage;
                $cacheKey .= ":$include";
                if ( self::$languageNameCache === null ) {
-                       self::$languageNameCache = new MapCacheLRU( 20 );
+                       self::$languageNameCache = new HashBagOStuff( array( 'maxKeys' => 20 ) );
                }
-               if ( self::$languageNameCache->has( $cacheKey ) ) {
-                       $ret = self::$languageNameCache->get( $cacheKey );
-               } else {
+
+               $ret = self::$languageNameCache->get( $cacheKey );
+               if ( !$ret ) {
                        $ret = self::fetchLanguageNamesUncached( $inLanguage, $include );
                        self::$languageNameCache->set( $cacheKey, $ret );
                }
@@ -3691,8 +3656,9 @@ class Language {
                                # We got the first byte only of a multibyte char; remove it.
                                $string = substr( $string, 0, -1 );
                        } elseif ( $char >= 0x80 &&
+                               // Use the /s modifier (PCRE_DOTALL) so (.*) also matches newlines
                                preg_match( '/^(.*)(?:[\xe0-\xef][\x80-\xbf]|' .
-                                       '[\xf0-\xf7][\x80-\xbf]{1,2})$/', $string, $m )
+                                       '[\xf0-\xf7][\x80-\xbf]{1,2})$/s', $string, $m )
                        ) {
                                # We chopped in the middle of a character; remove it
                                $string = $m[1];
@@ -4406,22 +4372,6 @@ class Language {
                $this->mParentLanguage = false;
        }
 
-       /**
-        * Get the name of a file for a certain language code
-        * @param string $prefix Prepend this to the filename
-        * @param string $code Language code
-        * @param string $suffix Append this to the filename
-        * @throws MWException
-        * @return string $prefix . $mangledCode . $suffix
-        */
-       public static function getFileName( $prefix = 'Language', $code, $suffix = '.php' ) {
-               if ( !self::isValidBuiltInCode( $code ) ) {
-                       throw new MWException( "Invalid language code \"$code\"" );
-               }
-
-               return $prefix . str_replace( '-', '_', ucfirst( $code ) ) . $suffix;
-       }
-
        /**
         * Get the language code from a file name. Inverse of getFileName()
         * @param string $filename $prefix . $languageCode . $suffix
@@ -4439,6 +4389,34 @@ class Language {
                return str_replace( '_', '-', strtolower( $m[1] ) );
        }
 
+       /**
+        * @param string $code
+        * @return string Name of the language class
+        */
+       public static function classFromCode( $code ) {
+               if ( $code == 'en' ) {
+                       return 'Language';
+               } else {
+                       return 'Language' . str_replace( '-', '_', ucfirst( $code ) );
+               }
+       }
+
+       /**
+        * Get the name of a file for a certain language code
+        * @param string $prefix Prepend this to the filename
+        * @param string $code Language code
+        * @param string $suffix Append this to the filename
+        * @throws MWException
+        * @return string $prefix . $mangledCode . $suffix
+        */
+       public static function getFileName( $prefix = 'Language', $code, $suffix = '.php' ) {
+               if ( !self::isValidBuiltInCode( $code ) ) {
+                       throw new MWException( "Invalid language code \"$code\"" );
+               }
+
+               return $prefix . str_replace( '-', '_', ucfirst( $code ) ) . $suffix;
+       }
+
        /**
         * @param string $code
         * @return string
@@ -4465,15 +4443,6 @@ class Language {
                return "$IP/languages/i18n/$code.json";
        }
 
-       /**
-        * @param string $code
-        * @return string
-        */
-       public static function getClassFileName( $code ) {
-               global $IP;
-               return self::getFileName( "$IP/languages/classes/Language", $code, '.php' );
-       }
-
        /**
         * Get the first fallback for a given language.
         *
@@ -4482,12 +4451,11 @@ class Language {
         * @return bool|string
         */
        public static function getFallbackFor( $code ) {
-               if ( $code === 'en' || !Language::isValidBuiltInCode( $code ) ) {
-                       return false;
-               } else {
-                       $fallbacks = self::getFallbacksFor( $code );
+               $fallbacks = self::getFallbacksFor( $code );
+               if ( $fallbacks ) {
                        return $fallbacks[0];
                }
+               return false;
        }
 
        /**