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 
70  public const CONSTRUCTOR_OPTIONS = [
71  'DummyLanguageCodes',
72  'LangObjCacheSize',
73  ];
74 
83  public function __construct(
90  ) {
91  $options->assertRequiredOptions( self::CONSTRUCTOR_OPTIONS );
92 
93  $this->options = $options;
94  $this->localisationCache = $localisationCache;
95  $this->langNameUtils = $langNameUtils;
96  $this->langFallback = $langFallback;
97  $this->langConverterFactory = $langConverterFactory;
98  $this->hookContainer = $hookContainer;
99  }
100 
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  ) {
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,
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 }
MediaWiki\Languages
MediaWiki\MediaWikiServices
MediaWikiServices is the service locator for the application scope of MediaWiki.
Definition: MediaWikiServices.php:165
$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:83
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:197
MediaWiki\Languages\LanguageFactory\newFromCode
newFromCode( $code, $fallback=false)
Create a language object for a given language code.
Definition: LanguageFactory.php:147
MWException
MediaWiki exception.
Definition: MWException.php:29
MediaWiki\Config\ServiceOptions
A class for passing options to services.
Definition: ServiceOptions.php:27
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:108
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:179
Language\$mLangObjCache
static array $mLangObjCache
Definition: Language.php:145
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:208
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:45
LanguageConverter
Base class for multi-variant language conversion.
Definition: LanguageConverter.php:35
MediaWiki\Languages\LanguageFactory\classFromCode
classFromCode( $code, $fallback=true)
Definition: LanguageFactory.php:192
MediaWiki\Languages\LanguageFactory\CONSTRUCTOR_OPTIONS
const CONSTRUCTOR_OPTIONS
Definition: LanguageFactory.php:70
Language
Internationalisation code See https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation for more...
Definition: Language.php:42
MediaWiki\Config\ServiceOptions\assertRequiredOptions
assertRequiredOptions(array $expectedKeys)
Assert that the list of options provided in this instance exactly match $expectedKeys,...
Definition: ServiceOptions.php:66