MediaWiki REL1_39
LanguageFallback.php
Go to the documentation of this file.
1<?php
21namespace MediaWiki\Languages;
22
23use InvalidArgumentException;
25use Wikimedia\Assert\Assert;
26
36 public const MESSAGES = 0;
37
42 public const STRICT = 1;
43
45 private $siteLangCode;
46
48 private $localisationCache;
49
51 private $langNameUtils;
52
54 private $fallbackCache = [];
55
64 public function __construct(
65 $siteLangCode,
66 LocalisationCache $localisationCache,
67 LanguageNameUtils $langNameUtils
68 ) {
69 $this->siteLangCode = $siteLangCode;
70 $this->localisationCache = $localisationCache;
71 $this->langNameUtils = $langNameUtils;
72 }
73
81 public function getFirst( $code ) {
82 return $this->getAll( $code )[0] ?? null;
83 }
84
95 public function getAll( $code, $mode = self::MESSAGES ) {
96 // XXX The LanguageNameUtils dependency is just because of this line, is it needed?
97 // Especially because isValidBuiltInCode() is just a one-line regex anyway, maybe it should
98 // actually be static?
99 if ( $code === 'en' || !$this->langNameUtils->isValidBuiltInCode( $code ) ) {
100 return [];
101 }
102 switch ( $mode ) {
103 case self::MESSAGES:
104 // For unknown languages, fallbackSequence returns an empty array. Hardcode fallback
105 // to 'en' in that case, as English messages are always defined.
106 $ret = $this->localisationCache->getItem( $code, 'fallbackSequence' ) ?: [ 'en' ];
107 break;
108
109 case self::STRICT:
110 // Use this mode when you don't want to fall back to English unless explicitly
111 // defined, for example when you have language-variant icons and an international
112 // language-independent fallback.
113 $ret = $this->localisationCache->getItem( $code, 'originalFallbackSequence' );
114 break;
115
116 default:
117 throw new InvalidArgumentException( "Invalid fallback mode \"$mode\"" );
118 }
119
120 foreach ( $ret as $fallbackCode ) {
121 Assert::postcondition( $this->langNameUtils->isValidBuiltInCode( $fallbackCode ),
122 "Invalid fallback code '$fallbackCode' in fallback sequence for '$code'" );
123 }
124
125 return $ret;
126 }
127
136 public function getAllIncludingSiteLanguage( $code ) {
137 // Usually, we will only store a tiny number of fallback chains, so we cache in a member.
138 $cacheKey = "{$code}-{$this->siteLangCode}";
139
140 if ( !array_key_exists( $cacheKey, $this->fallbackCache ) ) {
141 $fallbacks = $this->getAll( $code );
142
143 if ( $code === $this->siteLangCode ) {
144 // Don't bother hitting the localisation cache a second time
145 $siteFallbacks = [ $code ];
146 } else {
147 // Append the site's fallback chain, including the site language itself
148 $siteFallbacks = $this->getAll( $this->siteLangCode );
149 array_unshift( $siteFallbacks, $this->siteLangCode );
150
151 // Eliminate any languages already included in the chain
152 $siteFallbacks = array_diff( $siteFallbacks, $fallbacks );
153 }
154
155 $this->fallbackCache[$cacheKey] = [ $fallbacks, $siteFallbacks ];
156 }
157 return $this->fallbackCache[$cacheKey];
158 }
159}
Caching for the contents of localisation files.
getAllIncludingSiteLanguage( $code)
Get the ordered list of fallback languages, ending with the fallback language chain for the site lang...
const STRICT
Return a strict fallback chain in getAll.
getFirst( $code)
Get the first fallback for a given language.
const MESSAGES
Return a fallback chain for messages in getAll.
__construct( $siteLangCode, LocalisationCache $localisationCache, LanguageNameUtils $langNameUtils)
Do not call this directly.
getAll( $code, $mode=self::MESSAGES)
Get the ordered list of fallback languages.
A service that provides utilities to do with language names and codes.