MediaWiki REL1_35
LanguageFactory.php
Go to the documentation of this file.
1<?php
25namespace MediaWiki\Languages;
26
27use Language;
33use MWException;
34
44 private $options;
45
48
51
54
57
60
62 private $langObjCache = [];
63
65 private $parentLangCache = [];
66
71 public const CONSTRUCTOR_OPTIONS = [
72 'DummyLanguageCodes',
73 'LangObjCacheSize',
74 ];
75
84 public function __construct(
91 ) {
92 $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
93
94 $this->options = $options;
95 $this->localisationCache = $localisationCache;
96 $this->langNameUtils = $langNameUtils;
97 $this->langFallback = $langFallback;
98 $this->langConverterFactory = $langConverterFactory;
99 $this->hookContainer = $hookContainer;
100 }
101
108 public function getLanguage( $code ) : Language {
109 $code = $this->options->get( 'DummyLanguageCodes' )[$code] ?? $code;
110
111 // This is horrible, horrible code, but is necessary to support Language::$mLangObjCache
112 // per the deprecation policy. Kill with fire in 1.36!
113 if (
115 $this === MediaWikiServices::getInstance()->getLanguageFactory()
116 ) {
117 $this->langObjCache = Language::$mLangObjCache;
118 }
119
120 // Get the language object to process
121 $langObj = $this->langObjCache[$code] ?? $this->newFromCode( $code );
122
123 // Merge the language object in to get it up front in the cache
124 $this->langObjCache = array_merge( [ $code => $langObj ], $this->langObjCache );
125 // Get rid of the oldest ones in case we have an overflow
126 $this->langObjCache =
127 array_slice( $this->langObjCache, 0, $this->options->get( 'LangObjCacheSize' ), true );
128
129 // As above, remove this in 1.36
130 if (
132 $this === MediaWikiServices::getInstance()->getLanguageFactory()
133 ) {
134 Language::$mLangObjCache = $this->langObjCache;
135 }
136
137 return $langObj;
138 }
139
147 private function newFromCode( $code, $fallback = false ) : Language {
148 if ( !$this->langNameUtils->isValidCode( $code ) ) {
149 throw new MWException( "Invalid language code \"$code\"" );
150 }
151
152 $constructorArgs = [
153 $code,
154 $this->localisationCache,
155 $this->langNameUtils,
156 $this->langFallback,
157 $this->langConverterFactory,
158 $this->hookContainer
159 ];
160
161 if ( !$this->langNameUtils->isValidBuiltInCode( $code ) ) {
162 // It's not possible to customise this code with class files, so
163 // just return a Language object. This is to support uselang= hacks.
164 return new Language( ...$constructorArgs );
165 }
166
167 // Check if there is a language class for the code
168 $class = $this->classFromCode( $code, $fallback );
169 // LanguageCode does not inherit Language
170 if ( class_exists( $class ) && is_a( $class, 'Language', true ) ) {
171 return new $class( ...$constructorArgs );
172 }
173
174 // Keep trying the fallback list until we find an existing class
175 $fallbacks = $this->langFallback->getAll( $code );
176 foreach ( $fallbacks as $fallbackCode ) {
177 $class = $this->classFromCode( $fallbackCode );
178 if ( class_exists( $class ) ) {
179 // TODO allow additional dependencies to be injected for subclasses somehow
180 return new $class( ...$constructorArgs );
181 }
182 }
183
184 throw new MWException( "Invalid fallback sequence for language '$code'" );
185 }
186
192 private function classFromCode( $code, $fallback = true ) {
193 if ( $fallback && $code == 'en' ) {
194 return 'Language';
195 } else {
196 return 'Language' . str_replace( '-', '_', ucfirst( $code ) );
197 }
198 }
199
208 public function getParentLanguage( $code ) {
209 // We deliberately use array_key_exists() instead of isset() because we cache null.
210 if ( !array_key_exists( $code, $this->parentLangCache ) ) {
211 $codeBase = explode( '-', $code )[0];
212 if ( !in_array( $codeBase, LanguageConverter::$languagesWithVariants ) ) {
213 $this->parentLangCache[$code] = null;
214 return null;
215 }
216
217 $lang = $this->getLanguage( $codeBase );
218 $converter = $this->langConverterFactory->getLanguageConverter( $lang );
219 if ( !$converter->hasVariant( $code ) ) {
220 $this->parentLangCache[$code] = null;
221 return null;
222 }
223
224 $this->parentLangCache[$code] = $lang;
225 }
226
227 return $this->parentLangCache[$code];
228 }
229}
$fallback
if(ini_get('mbstring.func_overload')) if(!defined('MW_ENTRY_POINT'))
Pre-config setup: Before loading LocalSettings.php.
Definition Setup.php:85
Base class for multi-variant language conversion.
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition Language.php:41
Class for caching the contents of localisation files, Messages*.php and *.i18n.php.
MediaWiki exception.
A class for passing options to services.
assertRequiredOptions(array $expectedKeys)
Assert that the list of options provided in this instance exactly match $expectedKeys,...
An interface for creating language converters.
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
newFromCode( $code, $fallback=false)
Create a language object for a given language code.
LanguageConverterFactory $langConverterFactory
__construct(ServiceOptions $options, LocalisationCache $localisationCache, LanguageNameUtils $langNameUtils, LanguageFallback $langFallback, LanguageConverterFactory $langConverterFactory, HookContainer $hookContainer)
getLanguage( $code)
Get a cached or new language object for a given language code.
classFromCode( $code, $fallback=true)
getParentLanguage( $code)
Get the "parent" language which has a converter to convert a "compatible" language (in another varian...
A service that provides utilities to do with language names and codes.
MediaWikiServices is the service locator for the application scope of MediaWiki.
static hasInstance()
Returns true if an instance has already been initialized.
static getInstance()
Returns the global default instance of the top level service locator.
if(!isset( $args[0])) $lang