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