Bump and prep 1.34.1
[lhc/web/wiklou.git] / languages / Language.php
index 16a6e1a..39b5f73 100644 (file)
@@ -27,8 +27,8 @@
  */
 
 use CLDRPluralRuleParser\Evaluator;
+use MediaWiki\Languages\LanguageNameUtils;
 use MediaWiki\MediaWikiServices;
-use Wikimedia\Assert\Assert;
 
 /**
  * Internationalisation code
@@ -38,21 +38,24 @@ class Language {
        /**
         * Return autonyms in fetchLanguageName(s).
         * @since 1.32
+        * @deprecated since 1.34, LanguageNameUtils::AUTONYMS
         */
-       const AS_AUTONYMS = null;
+       const AS_AUTONYMS = LanguageNameUtils::AUTONYMS;
 
        /**
         * Return all known languages in fetchLanguageName(s).
         * @since 1.32
+        * @deprecated since 1.34, use LanguageNameUtils::ALL
         */
-       const ALL = 'all';
+       const ALL = LanguageNameUtils::ALL;
 
        /**
         * Return in fetchLanguageName(s) only the languages for which we have at
         * least some localisation.
         * @since 1.32
+        * @deprecated since 1.34, use LanguageNameUtils::SUPPORTED
         */
-       const SUPPORTED = 'mwfile';
+       const SUPPORTED = LanguageNameUtils::SUPPORTED;
 
        /**
         * @var LanguageConverter|FakeConverter
@@ -77,10 +80,11 @@ class Language {
         */
        public $transformData = [];
 
-       /**
-        * @var LocalisationCache
-        */
-       public static $dataCache;
+       /** @var LocalisationCache */
+       private $localisationCache;
+
+       /** @var LanguageNameUtils */
+       private $langNameUtils;
 
        public static $mLangObjCache = [];
 
@@ -96,6 +100,7 @@ class Language {
         */
        const STRICT_FALLBACKS = 1;
 
+       // TODO Make these const once we drop HHVM support (T192166)
        public static $mWeekdayMsgs = [
                'sunday', 'monday', 'tuesday', 'wednesday', 'thursday',
                'friday', 'saturday'
@@ -180,12 +185,6 @@ class Language {
         */
        private static $grammarTransformations;
 
-       /**
-        * Cache for language names
-        * @var HashBagOStuff|null
-        */
-       private static $languageNameCache;
-
        /**
         * Unicode directional formatting characters, for embedBidi()
         */
@@ -241,11 +240,12 @@ class Language {
         * @return Language
         */
        protected static function newFromCode( $code, $fallback = false ) {
-               if ( !self::isValidCode( $code ) ) {
+               $langNameUtils = MediaWikiServices::getInstance()->getLanguageNameUtils();
+               if ( !$langNameUtils->isValidCode( $code ) ) {
                        throw new MWException( "Invalid language code \"$code\"" );
                }
 
-               if ( !self::isValidBuiltInCode( $code ) ) {
+               if ( !$langNameUtils->isValidBuiltInCode( $code ) ) {
                        // It's not possible to customise this code with class files, so
                        // just return a Language object. This is to support uselang= hacks.
                        $lang = new Language;
@@ -264,7 +264,7 @@ class Language {
                // Keep trying the fallback list until we find an existing class
                $fallbacks = self::getFallbacksFor( $code );
                foreach ( $fallbacks as $fallbackCode ) {
-                       if ( !self::isValidBuiltInCode( $fallbackCode ) ) {
+                       if ( !$langNameUtils->isValidBuiltInCode( $fallbackCode ) ) {
                                throw new MWException( "Invalid fallback '$fallbackCode' in fallback sequence for '$code'" );
                        }
 
@@ -285,37 +285,30 @@ class Language {
         * @since 1.32
         */
        public static function clearCaches() {
-               if ( !defined( 'MW_PHPUNIT_TEST' ) ) {
-                       throw new MWException( __METHOD__ . ' must not be used outside tests' );
+               if ( !defined( 'MW_PHPUNIT_TEST' ) && !defined( 'MEDIAWIKI_INSTALL' ) ) {
+                       throw new MWException( __METHOD__ . ' must not be used outside tests/installer' );
+               }
+               if ( defined( 'MW_PHPUNIT_TEST' ) ) {
+                       MediaWikiServices::getInstance()->resetServiceForTesting( 'LocalisationCache' );
+                       MediaWikiServices::getInstance()->resetServiceForTesting( 'LanguageNameUtils' );
                }
-               self::$dataCache = null;
-               // Reinitialize $dataCache, since it's expected to always be available
-               self::getLocalisationCache();
                self::$mLangObjCache = [];
                self::$fallbackLanguageCache = [];
                self::$grammarTransformations = null;
-               self::$languageNameCache = null;
        }
 
        /**
         * Checks whether any localisation is available for that language tag
         * in MediaWiki (MessagesXx.php exists).
         *
+        * @deprecated since 1.34, use LanguageNameUtils
         * @param string $code Language tag (in lower case)
         * @return bool Whether language is supported
         * @since 1.21
         */
        public static function isSupportedLanguage( $code ) {
-               if ( !self::isValidBuiltInCode( $code ) ) {
-                       return false;
-               }
-
-               if ( $code === 'qqq' ) {
-                       return false;
-               }
-
-               return is_readable( self::getMessagesFileName( $code ) ) ||
-                       is_readable( self::getJsonMessagesFileName( $code ) );
+               return MediaWikiServices::getInstance()->getLanguageNameUtils()
+                       ->isSupportedLanguage( $code );
        }
 
        /**
@@ -383,77 +376,55 @@ class Language {
         * not it exists. This includes codes which are used solely for
         * customisation via the MediaWiki namespace.
         *
+        * @deprecated since 1.34, use LanguageNameUtils
+        *
         * @param string $code
         *
         * @return bool
         */
        public static function isValidCode( $code ) {
-               static $cache = [];
-               Assert::parameterType( 'string', $code, '$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 T39564, T39587, T38938
-                       $cache[$code] =
-                               // Protect against path traversal
-                               strcspn( $code, ":/\\\000&<>'\"" ) === strlen( $code )
-                               && !preg_match( MediaWikiTitleCodec::getTitleInvalidRegex(), $code );
-               }
-               return $cache[$code];
+               return MediaWikiServices::getInstance()->getLanguageNameUtils()->isValidCode( $code );
        }
 
        /**
         * Returns true if a language code is of a valid form for the purposes of
         * internal customisation of MediaWiki, via Messages*.php or *.json.
         *
+        * @deprecated since 1.34, use LanguageNameUtils
+        *
         * @param string $code
         *
         * @since 1.18
         * @return bool
         */
        public static function isValidBuiltInCode( $code ) {
-               Assert::parameterType( 'string', $code, '$code' );
-
-               return (bool)preg_match( '/^[a-z0-9-]{2,}$/', $code );
+               return MediaWikiServices::getInstance()->getLanguageNameUtils()
+                       ->isValidBuiltInCode( $code );
        }
 
        /**
         * Returns true if a language code is an IETF tag known to MediaWiki.
         *
+        * @deprecated since 1.34, use LanguageNameUtils
+        *
         * @param string $tag
         *
         * @since 1.21
         * @return bool
         */
        public static function isKnownLanguageTag( $tag ) {
-               // Quick escape for invalid input to avoid exceptions down the line
-               // when code tries to process tags which are not valid at all.
-               if ( !self::isValidBuiltInCode( $tag ) ) {
-                       return false;
-               }
-
-               if ( isset( MediaWiki\Languages\Data\Names::$names[$tag] )
-                       || self::fetchLanguageName( $tag, $tag ) !== ''
-               ) {
-                       return true;
-               }
-
-               return false;
+               return MediaWikiServices::getInstance()->getLanguageNameUtils()
+                       ->isKnownLanguageTag( $tag );
        }
 
        /**
         * Get the LocalisationCache instance
         *
+        * @deprecated since 1.34, use MediaWikiServices
         * @return LocalisationCache
         */
        public static function getLocalisationCache() {
-               if ( is_null( self::$dataCache ) ) {
-                       global $wgLocalisationCacheConf;
-                       $class = $wgLocalisationCacheConf['class'];
-                       self::$dataCache = new $class( $wgLocalisationCacheConf );
-               }
-               return self::$dataCache;
+               return MediaWikiServices::getInstance()->getLocalisationCache();
        }
 
        function __construct() {
@@ -464,7 +435,9 @@ class Language {
                } else {
                        $this->mCode = str_replace( '_', '-', strtolower( substr( static::class, 8 ) ) );
                }
-               self::getLocalisationCache();
+               $services = MediaWikiServices::getInstance();
+               $this->localisationCache = $services->getLocalisationCache();
+               $this->langNameUtils = $services->getLanguageNameUtils();
        }
 
        /**
@@ -497,7 +470,7 @@ class Language {
         * @return array
         */
        public function getBookstoreList() {
-               return self::$dataCache->getItem( $this->mCode, 'bookstoreList' );
+               return $this->localisationCache->getItem( $this->mCode, 'bookstoreList' );
        }
 
        /**
@@ -514,7 +487,7 @@ class Language {
                                getCanonicalNamespaces();
 
                        $this->namespaceNames = $wgExtraNamespaces +
-                               self::$dataCache->getItem( $this->mCode, 'namespaceNames' );
+                               $this->localisationCache->getItem( $this->mCode, 'namespaceNames' );
                        $this->namespaceNames += $validNamespaces;
 
                        $this->namespaceNames[NS_PROJECT] = $wgMetaNamespace;
@@ -527,7 +500,6 @@ class Language {
                        }
 
                        # Sometimes a language will be localised but not actually exist on this wiki.
-                       // @phan-suppress-next-line PhanTypeMismatchForeach
                        foreach ( $this->namespaceNames as $key => $text ) {
                                if ( !isset( $validNamespaces[$key] ) ) {
                                        unset( $this->namespaceNames[$key] );
@@ -536,7 +508,6 @@ class Language {
 
                        # The above mixing may leave namespaces out of canonical order.
                        # Re-order by namespace ID number...
-                       // @phan-suppress-next-line PhanTypeMismatchArgumentInternal
                        ksort( $this->namespaceNames );
 
                        Hooks::run( 'LanguageGetNamespaces', [ &$this->namespaceNames ] );
@@ -623,7 +594,7 @@ class Language {
                global $wgExtraGenderNamespaces;
 
                $ns = $wgExtraGenderNamespaces +
-                       (array)self::$dataCache->getItem( $this->mCode, 'namespaceGenderAliases' );
+                       (array)$this->localisationCache->getItem( $this->mCode, 'namespaceGenderAliases' );
 
                return $ns[$index][$gender] ?? $this->getNsText( $index );
        }
@@ -645,7 +616,7 @@ class Language {
                        return false;
                } else {
                        // Check what is in i18n files
-                       $aliases = self::$dataCache->getItem( $this->mCode, 'namespaceGenderAliases' );
+                       $aliases = $this->localisationCache->getItem( $this->mCode, 'namespaceGenderAliases' );
                        return count( $aliases ) > 0;
                }
        }
@@ -669,7 +640,7 @@ class Language {
         */
        public function getNamespaceAliases() {
                if ( is_null( $this->namespaceAliases ) ) {
-                       $aliases = self::$dataCache->getItem( $this->mCode, 'namespaceAliases' );
+                       $aliases = $this->localisationCache->getItem( $this->mCode, 'namespaceAliases' );
                        if ( !$aliases ) {
                                $aliases = [];
                        } else {
@@ -683,8 +654,8 @@ class Language {
                        }
 
                        global $wgExtraGenderNamespaces;
-                       $genders = $wgExtraGenderNamespaces +
-                               (array)self::$dataCache->getItem( $this->mCode, 'namespaceGenderAliases' );
+                       $genders = $wgExtraGenderNamespaces + (array)$this->localisationCache
+                               ->getItem( $this->mCode, 'namespaceGenderAliases' );
                        foreach ( $genders as $index => $forms ) {
                                foreach ( $forms as $alias ) {
                                        $aliases[$alias] = $index;
@@ -772,7 +743,7 @@ class Language {
                if ( $usemsg && wfMessage( $msg )->exists() ) {
                        return $this->getMessageFromDB( $msg );
                }
-               $name = self::fetchLanguageName( $code );
+               $name = $this->langNameUtils->getLanguageName( $code );
                if ( $name ) {
                        return $name; # if it's defined as a language name, show that
                } else {
@@ -785,21 +756,21 @@ class Language {
         * @return string[]|bool List of date format preference keys, or false if disabled.
         */
        public function getDatePreferences() {
-               return self::$dataCache->getItem( $this->mCode, 'datePreferences' );
+               return $this->localisationCache->getItem( $this->mCode, 'datePreferences' );
        }
 
        /**
         * @return array
         */
        function getDateFormats() {
-               return self::$dataCache->getItem( $this->mCode, 'dateFormats' );
+               return $this->localisationCache->getItem( $this->mCode, 'dateFormats' );
        }
 
        /**
         * @return array|string
         */
        public function getDefaultDateFormat() {
-               $df = self::$dataCache->getItem( $this->mCode, 'defaultDateFormat' );
+               $df = $this->localisationCache->getItem( $this->mCode, 'defaultDateFormat' );
                if ( $df === 'dmy or mdy' ) {
                        global $wgAmericanDates;
                        return $wgAmericanDates ? 'mdy' : 'dmy';
@@ -812,7 +783,7 @@ class Language {
         * @return array
         */
        public function getDatePreferenceMigrationMap() {
-               return self::$dataCache->getItem( $this->mCode, 'datePreferenceMigrationMap' );
+               return $this->localisationCache->getItem( $this->mCode, 'datePreferenceMigrationMap' );
        }
 
        /**
@@ -833,6 +804,8 @@ class Language {
 
        /**
         * Get an array of language names, indexed by code.
+        *
+        * @deprecated since 1.34, use LanguageNameUtils::getLanguageNames
         * @param null|string $inLanguage Code of language in which to return the names
         *              Use self::AS_AUTONYMS for autonyms (native names)
         * @param string $include One of:
@@ -843,95 +816,12 @@ class Language {
         * @since 1.20
         */
        public static function fetchLanguageNames( $inLanguage = self::AS_AUTONYMS, $include = 'mw' ) {
-               $cacheKey = $inLanguage === self::AS_AUTONYMS ? 'null' : $inLanguage;
-               $cacheKey .= ":$include";
-               if ( self::$languageNameCache === null ) {
-                       self::$languageNameCache = new HashBagOStuff( [ 'maxKeys' => 20 ] );
-               }
-
-               $ret = self::$languageNameCache->get( $cacheKey );
-               if ( !$ret ) {
-                       $ret = self::fetchLanguageNamesUncached( $inLanguage, $include );
-                       self::$languageNameCache->set( $cacheKey, $ret );
-               }
-               return $ret;
-       }
-
-       /**
-        * Uncached helper for fetchLanguageNames
-        * @param null|string $inLanguage Code of language in which to return the names
-        *              Use self::AS_AUTONYMS for autonyms (native names)
-        * @param string $include One of:
-        *              self::ALL all available languages
-        *              'mw' only if the language is defined in MediaWiki or wgExtraLanguageNames (default)
-        *              self::SUPPORTED only if the language is in 'mw' *and* has a message file
-        * @return array Language code => language name (sorted by key)
-        */
-       private static function fetchLanguageNamesUncached(
-               $inLanguage = self::AS_AUTONYMS,
-               $include = 'mw'
-       ) {
-               global $wgExtraLanguageNames, $wgUsePigLatinVariant;
-
-               // If passed an invalid language code to use, fallback to en
-               if ( $inLanguage !== self::AS_AUTONYMS && !self::isValidCode( $inLanguage ) ) {
-                       $inLanguage = 'en';
-               }
-
-               $names = [];
-
-               if ( $inLanguage ) {
-                       # TODO: also include when $inLanguage is null, when this code is more efficient
-                       Hooks::run( 'LanguageGetTranslatedLanguageNames', [ &$names, $inLanguage ] );
-               }
-
-               $mwNames = $wgExtraLanguageNames + MediaWiki\Languages\Data\Names::$names;
-               if ( $wgUsePigLatinVariant ) {
-                       // Pig Latin (for variant development)
-                       $mwNames['en-x-piglatin'] = 'Igpay Atinlay';
-               }
-
-               foreach ( $mwNames as $mwCode => $mwName ) {
-                       # - Prefer own MediaWiki native name when not using the hook
-                       # - For other names just add if not added through the hook
-                       if ( $mwCode === $inLanguage || !isset( $names[$mwCode] ) ) {
-                               $names[$mwCode] = $mwName;
-                       }
-               }
-
-               if ( $include === self::ALL ) {
-                       ksort( $names );
-                       return $names;
-               }
-
-               $returnMw = [];
-               $coreCodes = array_keys( $mwNames );
-               foreach ( $coreCodes as $coreCode ) {
-                       $returnMw[$coreCode] = $names[$coreCode];
-               }
-
-               if ( $include === self::SUPPORTED ) {
-                       $namesMwFile = [];
-                       # We do this using a foreach over the codes instead of a directory
-                       # loop so that messages files in extensions will work correctly.
-                       foreach ( $returnMw as $code => $value ) {
-                               if ( is_readable( self::getMessagesFileName( $code ) )
-                                       || is_readable( self::getJsonMessagesFileName( $code ) )
-                               ) {
-                                       $namesMwFile[$code] = $names[$code];
-                               }
-                       }
-
-                       ksort( $namesMwFile );
-                       return $namesMwFile;
-               }
-
-               ksort( $returnMw );
-               # 'mw' option; default if it's not one of the other two options (all/mwfile)
-               return $returnMw;
+               return MediaWikiServices::getInstance()->getLanguageNameUtils()
+                       ->getLanguageNames( $inLanguage, $include );
        }
 
        /**
+        * @deprecated since 1.34, use LanguageNameUtils::getLanguageName
         * @param string $code The code of the language for which to get the name
         * @param null|string $inLanguage Code of language in which to return the name
         *   (SELF::AS_AUTONYMS for autonyms)
@@ -944,9 +834,8 @@ class Language {
                $inLanguage = self::AS_AUTONYMS,
                $include = self::ALL
        ) {
-               $code = strtolower( $code );
-               $array = self::fetchLanguageNames( $inLanguage, $include );
-               return !array_key_exists( $code, $array ) ? '' : $array[$code];
+               return MediaWikiServices::getInstance()->getLanguageNameUtils()
+                       ->getLanguageName( $code, $inLanguage, $include );
        }
 
        /**
@@ -2279,7 +2168,8 @@ class Language {
                }
 
                if ( !isset( $this->dateFormatStrings[$type][$pref] ) ) {
-                       $df = self::$dataCache->getSubitem( $this->mCode, 'dateFormats', "$pref $type" );
+                       $df =
+                               $this->localisationCache->getSubitem( $this->mCode, 'dateFormats', "$pref $type" );
 
                        if ( $type === 'pretty' && $df === null ) {
                                $df = $this->getDateFormatString( 'date', $pref );
@@ -2287,7 +2177,8 @@ class Language {
 
                        if ( !$wasDefault && $df === null ) {
                                $pref = $this->getDefaultDateFormat();
-                               $df = self::$dataCache->getSubitem( $this->mCode, 'dateFormats', "$pref $type" );
+                               $df = $this->getLocalisationCache()
+                                       ->getSubitem( $this->mCode, 'dateFormats', "$pref $type" );
                        }
 
                        $this->dateFormatStrings[$type][$pref] = $df;
@@ -2651,14 +2542,14 @@ class Language {
         * @return string|null
         */
        public function getMessage( $key ) {
-               return self::$dataCache->getSubitem( $this->mCode, 'messages', $key );
+               return $this->localisationCache->getSubitem( $this->mCode, 'messages', $key );
        }
 
        /**
         * @return array
         */
        function getAllMessages() {
-               return self::$dataCache->getItem( $this->mCode, 'messages' );
+               return $this->localisationCache->getItem( $this->mCode, 'messages' );
        }
 
        /**
@@ -2900,7 +2791,7 @@ class Language {
         * @return string
         */
        function fallback8bitEncoding() {
-               return self::$dataCache->getItem( $this->mCode, 'fallback8bitEncoding' );
+               return $this->localisationCache->getItem( $this->mCode, 'fallback8bitEncoding' );
        }
 
        /**
@@ -3090,7 +2981,7 @@ class Language {
         * @return bool
         */
        function isRTL() {
-               return self::$dataCache->getItem( $this->mCode, 'rtl' );
+               return $this->localisationCache->getItem( $this->mCode, 'rtl' );
        }
 
        /**
@@ -3166,7 +3057,7 @@ class Language {
         * @return array
         */
        function capitalizeAllNouns() {
-               return self::$dataCache->getItem( $this->mCode, 'capitalizeAllNouns' );
+               return $this->localisationCache->getItem( $this->mCode, 'capitalizeAllNouns' );
        }
 
        /**
@@ -3199,7 +3090,7 @@ class Language {
         * @return bool
         */
        function linkPrefixExtension() {
-               return self::$dataCache->getItem( $this->mCode, 'linkPrefixExtension' );
+               return $this->localisationCache->getItem( $this->mCode, 'linkPrefixExtension' );
        }
 
        /**
@@ -3207,7 +3098,7 @@ class Language {
         * @return array
         */
        function getMagicWords() {
-               return self::$dataCache->getItem( $this->mCode, 'magicWords' );
+               return $this->localisationCache->getItem( $this->mCode, 'magicWords' );
        }
 
        /**
@@ -3217,7 +3108,7 @@ class Language {
         */
        function getMagic( $mw ) {
                $rawEntry = $this->mMagicExtensions[$mw->mId] ??
-                       self::$dataCache->getSubitem( $this->mCode, 'magicWords', $mw->mId );
+                       $this->localisationCache->getSubitem( $this->mCode, 'magicWords', $mw->mId );
 
                if ( !is_array( $rawEntry ) ) {
                        wfWarn( "\"$rawEntry\" is not a valid magic word for \"$mw->mId\"" );
@@ -3237,7 +3128,6 @@ class Language {
                $fallbackChain = array_reverse( $fallbackChain );
                foreach ( $fallbackChain as $code ) {
                        if ( isset( $newWords[$code] ) ) {
-                               // @phan-suppress-next-line PhanTypeMismatchProperty
                                $this->mMagicExtensions = $newWords[$code] + $this->mMagicExtensions;
                        }
                }
@@ -3253,7 +3143,7 @@ class Language {
                if ( is_null( $this->mExtendedSpecialPageAliases ) ) {
                        // Initialise array
                        $this->mExtendedSpecialPageAliases =
-                               self::$dataCache->getItem( $this->mCode, 'specialPageAliases' );
+                               $this->localisationCache->getItem( $this->mCode, 'specialPageAliases' );
                }
 
                return $this->mExtendedSpecialPageAliases;
@@ -3418,28 +3308,28 @@ class Language {
         * @return string
         */
        function digitGroupingPattern() {
-               return self::$dataCache->getItem( $this->mCode, 'digitGroupingPattern' );
+               return $this->localisationCache->getItem( $this->mCode, 'digitGroupingPattern' );
        }
 
        /**
         * @return array
         */
        function digitTransformTable() {
-               return self::$dataCache->getItem( $this->mCode, 'digitTransformTable' );
+               return $this->localisationCache->getItem( $this->mCode, 'digitTransformTable' );
        }
 
        /**
         * @return array
         */
        function separatorTransformTable() {
-               return self::$dataCache->getItem( $this->mCode, 'separatorTransformTable' );
+               return $this->localisationCache->getItem( $this->mCode, 'separatorTransformTable' );
        }
 
        /**
         * @return int|null
         */
        function minimumGroupingDigits() {
-               return self::$dataCache->getItem( $this->mCode, 'minimumGroupingDigits' );
+               return $this->localisationCache->getItem( $this->mCode, 'minimumGroupingDigits' );
        }
 
        /**
@@ -4339,7 +4229,7 @@ class Language {
         * @return string
         */
        public function linkTrail() {
-               return self::$dataCache->getItem( $this->mCode, 'linkTrail' );
+               return $this->localisationCache->getItem( $this->mCode, 'linkTrail' );
        }
 
        /**
@@ -4349,7 +4239,7 @@ class Language {
         * @return string
         */
        public function linkPrefixCharset() {
-               return self::$dataCache->getItem( $this->mCode, 'linkPrefixCharset' );
+               return $this->localisationCache->getItem( $this->mCode, 'linkPrefixCharset' );
        }
 
        /**
@@ -4451,6 +4341,8 @@ class Language {
 
        /**
         * Get the name of a file for a certain language code
+        *
+        * @deprecated since 1.34, use LanguageNameUtils
         * @param string $prefix Prepend this to the filename
         * @param string $code Language code
         * @param string $suffix Append this to the filename
@@ -4458,38 +4350,30 @@ class Language {
         * @return string $prefix . $mangledCode . $suffix
         */
        public static function getFileName( $prefix, $code, $suffix = '.php' ) {
-               if ( !self::isValidBuiltInCode( $code ) ) {
-                       throw new MWException( "Invalid language code \"$code\"" );
-               }
-
-               return $prefix . str_replace( '-', '_', ucfirst( $code ) ) . $suffix;
+               return MediaWikiServices::getInstance()->getLanguageNameUtils()
+                       ->getFileName( $prefix, $code, $suffix );
        }
 
        /**
+        * @deprecated since 1.34, use LanguageNameUtils
         * @param string $code
         * @return string
         */
        public static function getMessagesFileName( $code ) {
-               global $IP;
-               $file = self::getFileName( "$IP/languages/messages/Messages", $code, '.php' );
-               Hooks::run( 'Language::getMessagesFileName', [ $code, &$file ] );
-               return $file;
+               return MediaWikiServices::getInstance()->getLanguageNameUtils()
+                       ->getMessagesFileName( $code );
        }
 
        /**
+        * @deprecated since 1.34, use LanguageNameUtils
         * @param string $code
         * @return string
         * @throws MWException
         * @since 1.23
         */
        public static function getJsonMessagesFileName( $code ) {
-               global $IP;
-
-               if ( !self::isValidBuiltInCode( $code ) ) {
-                       throw new MWException( "Invalid language code \"$code\"" );
-               }
-
-               return "$IP/languages/i18n/$code.json";
+               return MediaWikiServices::getInstance()->getLanguageNameUtils()
+                       ->getJsonMessagesFileName( $code );
        }
 
        /**
@@ -4939,11 +4823,13 @@ class Language {
         * @return array Associative array with plural form, and plural rule as key-value pairs
         */
        public function getCompiledPluralRules() {
-               $pluralRules = self::$dataCache->getItem( strtolower( $this->mCode ), 'compiledPluralRules' );
+               $pluralRules =
+                       $this->localisationCache->getItem( strtolower( $this->mCode ), 'compiledPluralRules' );
                $fallbacks = self::getFallbacksFor( $this->mCode );
                if ( !$pluralRules ) {
                        foreach ( $fallbacks as $fallbackCode ) {
-                               $pluralRules = self::$dataCache->getItem( strtolower( $fallbackCode ), 'compiledPluralRules' );
+                               $pluralRules = $this->localisationCache
+                                       ->getItem( strtolower( $fallbackCode ), 'compiledPluralRules' );
                                if ( $pluralRules ) {
                                        break;
                                }
@@ -4958,11 +4844,13 @@ class Language {
         * @return array Associative array with plural form number and plural rule as key-value pairs
         */
        public function getPluralRules() {
-               $pluralRules = self::$dataCache->getItem( strtolower( $this->mCode ), 'pluralRules' );
+               $pluralRules =
+                       $this->localisationCache->getItem( strtolower( $this->mCode ), 'pluralRules' );
                $fallbacks = self::getFallbacksFor( $this->mCode );
                if ( !$pluralRules ) {
                        foreach ( $fallbacks as $fallbackCode ) {
-                               $pluralRules = self::$dataCache->getItem( strtolower( $fallbackCode ), 'pluralRules' );
+                               $pluralRules = $this->localisationCache
+                                       ->getItem( strtolower( $fallbackCode ), 'pluralRules' );
                                if ( $pluralRules ) {
                                        break;
                                }
@@ -4977,11 +4865,13 @@ class Language {
         * @return array Associative array with plural form number and plural rule type as key-value pairs
         */
        public function getPluralRuleTypes() {
-               $pluralRuleTypes = self::$dataCache->getItem( strtolower( $this->mCode ), 'pluralRuleTypes' );
+               $pluralRuleTypes =
+                       $this->localisationCache->getItem( strtolower( $this->mCode ), 'pluralRuleTypes' );
                $fallbacks = self::getFallbacksFor( $this->mCode );
                if ( !$pluralRuleTypes ) {
                        foreach ( $fallbacks as $fallbackCode ) {
-                               $pluralRuleTypes = self::$dataCache->getItem( strtolower( $fallbackCode ), 'pluralRuleTypes' );
+                               $pluralRuleTypes = $this->localisationCache
+                                       ->getItem( strtolower( $fallbackCode ), 'pluralRuleTypes' );
                                if ( $pluralRuleTypes ) {
                                        break;
                                }