MediaWiki  master
LanguageFallback.php
Go to the documentation of this file.
1 <?php
2 
3 namespace MediaWiki\Languages;
4 
8 
18  const MESSAGES = 0;
19 
24  const STRICT = 1;
25 
27  private $siteLangCode;
28 
31 
33  private $langNameUtils;
34 
36  private $fallbackCache = [];
37 
46  public function __construct(
50  ) {
51  $this->siteLangCode = $siteLangCode;
52  $this->localisationCache = $localisationCache;
53  $this->langNameUtils = $langNameUtils;
54  }
55 
63  public function getFirst( $code ) {
64  return $this->getAll( $code )[0] ?? null;
65  }
66 
77  public function getAll( $code, $mode = self::MESSAGES ) {
78  // XXX The LanguageNameUtils dependency is just because of this line, is it needed?
79  // Especially because isValidBuiltInCode() is just a one-line regex anyway, maybe it should
80  // actually be static?
81  if ( $code === 'en' || !$this->langNameUtils->isValidBuiltInCode( $code ) ) {
82  return [];
83  }
84  switch ( $mode ) {
85  case self::MESSAGES:
86  // For unknown languages, fallbackSequence returns an empty array. Hardcode fallback
87  // to 'en' in that case, as English messages are always defined.
88  $ret = $this->localisationCache->getItem( $code, 'fallbackSequence' ) ?: [ 'en' ];
89  break;
90 
91  case self::STRICT:
92  // Use this mode when you don't want to fall back to English unless explicitly
93  // defined, for example when you have language-variant icons and an international
94  // language-independent fallback.
95  $ret = $this->localisationCache->getItem( $code, 'originalFallbackSequence' );
96  break;
97 
98  default:
99  throw new InvalidArgumentException( "Invalid fallback mode \"$mode\"" );
100  }
101 
102  foreach ( $ret as $fallbackCode ) {
103  Assert::postcondition( $this->langNameUtils->isValidBuiltInCode( $fallbackCode ),
104  "Invalid fallback code '$fallbackCode' in fallback sequence for '$code'" );
105  }
106 
107  return $ret;
108  }
109 
118  public function getAllIncludingSiteLanguage( $code ) {
119  // Usually, we will only store a tiny number of fallback chains, so we cache in a member.
120  $cacheKey = "{$code}-{$this->siteLangCode}";
121 
122  if ( !array_key_exists( $cacheKey, $this->fallbackCache ) ) {
123  $fallbacks = $this->getAll( $code );
124 
125  if ( $code === $this->siteLangCode ) {
126  // Don't bother hitting the localisation cache a second time
127  $siteFallbacks = [ $code ];
128  } else {
129  // Append the site's fallback chain, including the site language itself
130  $siteFallbacks = $this->getAll( $this->siteLangCode );
131  array_unshift( $siteFallbacks, $this->siteLangCode );
132 
133  // Eliminate any languages already included in the chain
134  $siteFallbacks = array_diff( $siteFallbacks, $fallbacks );
135  }
136 
137  $this->fallbackCache[$cacheKey] = [ $fallbacks, $siteFallbacks ];
138  }
139  return $this->fallbackCache[$cacheKey];
140  }
141 }
const MESSAGES
Return a fallback chain for messages in getAll.
getAll( $code, $mode=self::MESSAGES)
Get the ordered list of fallback languages.
getAllIncludingSiteLanguage( $code)
Get the ordered list of fallback languages, ending with the fallback language chain for the site lang...
getFirst( $code)
Get the first fallback for a given language.
const STRICT
Return a strict fallback chain in getAll.
A service that provides utilities to do with language names and codes.
__construct( $siteLangCode, LocalisationCache $localisationCache, LanguageNameUtils $langNameUtils)
Do not call this directly.