7f3ddc816bf34cd9a4c940860f2b67dc183641b6
[yaffs-website] / web / core / lib / Drupal / Core / Language / LanguageManager.php
1 <?php
2
3 namespace Drupal\Core\Language;
4
5 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
6 use Drupal\Core\StringTranslation\TranslatableMarkup;
7 use Drupal\Core\Url;
8
9 /**
10  * Class responsible for providing language support on language-unaware sites.
11  */
12 class LanguageManager implements LanguageManagerInterface {
13   use DependencySerializationTrait;
14
15   /**
16    * A static cache of translated language lists.
17    *
18    * Array of arrays to cache the result of self::getLanguages() keyed by the
19    * language the list is translated to (first level) and the flags provided to
20    * the method (second level).
21    *
22    * @var \Drupal\Core\Language\LanguageInterface[]
23    *
24    * @see \Drupal\Core\Language\LanguageManager::getLanguages()
25    */
26   protected $languages = [];
27
28   /**
29    * The default language object.
30    *
31    * @var \Drupal\Core\Language\LanguageDefault
32    */
33   protected $defaultLanguage;
34
35   /**
36    * Constructs the language manager.
37    *
38    * @param \Drupal\Core\Language\LanguageDefault $default_language
39    *   The default language.
40    */
41   public function __construct(LanguageDefault $default_language) {
42     $this->defaultLanguage = $default_language;
43   }
44
45   /**
46    * {@inheritdoc}
47    */
48   public function isMultilingual() {
49     return FALSE;
50   }
51
52   /**
53    * {@inheritdoc}
54    */
55   public function getLanguageTypes() {
56     return [LanguageInterface::TYPE_INTERFACE, LanguageInterface::TYPE_CONTENT, LanguageInterface::TYPE_URL];
57   }
58
59   /**
60    * Returns information about all defined language types.
61    *
62    * Defines the three core language types:
63    * - Interface language is the only configurable language type in core. It is
64    *   used by t() as the default language if none is specified.
65    * - Content language is by default non-configurable and inherits the
66    *   interface language negotiated value. It is used by the Field API to
67    *   determine the display language for fields if no explicit value is
68    *   specified.
69    * - URL language is by default non-configurable and is determined through the
70    *   URL language negotiation method or the URL fallback language negotiation
71    *   method if no language can be detected. It is used by l() as the default
72    *   language if none is specified.
73    *
74    * @return array
75    *   An associative array of language type information arrays keyed by
76    *   language type machine name, in the format of
77    *   hook_language_types_info().
78    */
79   public function getDefinedLanguageTypesInfo() {
80     $this->definedLanguageTypesInfo = [
81       LanguageInterface::TYPE_INTERFACE => [
82         'name' => new TranslatableMarkup('Interface text'),
83         'description' => new TranslatableMarkup('Order of language detection methods for interface text. If a translation of interface text is available in the detected language, it will be displayed.'),
84         'locked' => TRUE,
85       ],
86       LanguageInterface::TYPE_CONTENT => [
87         'name' => new TranslatableMarkup('Content'),
88         'description' => new TranslatableMarkup('Order of language detection methods for content. If a version of content is available in the detected language, it will be displayed.'),
89         'locked' => TRUE,
90       ],
91       LanguageInterface::TYPE_URL => [
92         'locked' => TRUE,
93       ],
94     ];
95
96     return $this->definedLanguageTypesInfo;
97   }
98
99   /**
100    * {@inheritdoc}
101    */
102   public function getCurrentLanguage($type = LanguageInterface::TYPE_INTERFACE) {
103     return $this->getDefaultLanguage();
104   }
105
106   /**
107    * {@inheritdoc}
108    */
109   public function reset($type = NULL) {
110     return $this;
111   }
112
113   /**
114    * {@inheritdoc}
115    */
116   public function getDefaultLanguage() {
117     return $this->defaultLanguage->get();
118   }
119
120   /**
121    * {@inheritdoc}
122    */
123   public function getLanguages($flags = LanguageInterface::STATE_CONFIGURABLE) {
124     $static_cache_id = $this->getCurrentLanguage()->getId();
125     if (!isset($this->languages[$static_cache_id][$flags])) {
126       // If this language manager is used, there are no configured languages.
127       // The default language and locked languages comprise the full language
128       // list.
129       $default = $this->getDefaultLanguage();
130       $languages = [$default->getId() => $default];
131       $languages += $this->getDefaultLockedLanguages($default->getWeight());
132
133       // Filter the full list of languages based on the value of $flags.
134       $this->languages[$static_cache_id][$flags] = $this->filterLanguages($languages, $flags);
135     }
136     return $this->languages[$static_cache_id][$flags];
137   }
138
139   /**
140    * {@inheritdoc}
141    */
142   public function getNativeLanguages() {
143     // In a language unaware site we don't have translated languages.
144     return $this->getLanguages();
145   }
146
147   /**
148    * {@inheritdoc}
149    */
150   public function getLanguage($langcode) {
151     $languages = $this->getLanguages(LanguageInterface::STATE_ALL);
152     return isset($languages[$langcode]) ? $languages[$langcode] : NULL;
153   }
154
155   /**
156    * {@inheritdoc}
157    */
158   public function getLanguageName($langcode) {
159     if ($langcode == LanguageInterface::LANGCODE_NOT_SPECIFIED) {
160       return new TranslatableMarkup('None');
161     }
162     if ($language = $this->getLanguage($langcode)) {
163       return $language->getName();
164     }
165     if (empty($langcode)) {
166       return new TranslatableMarkup('Unknown');
167     }
168     return new TranslatableMarkup('Unknown (@langcode)', ['@langcode' => $langcode]);
169   }
170
171   /**
172    * {@inheritdoc}
173    */
174   public function getDefaultLockedLanguages($weight = 0) {
175     $languages = [];
176
177     $locked_language = [
178       'default' => FALSE,
179       'locked' => TRUE,
180       'direction' => LanguageInterface::DIRECTION_LTR,
181     ];
182     // This is called very early while initializing the language system. Prevent
183     // early t() calls by using the TranslatableMarkup.
184     $languages[LanguageInterface::LANGCODE_NOT_SPECIFIED] = new Language([
185       'id' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
186       'name' => new TranslatableMarkup('Not specified'),
187       'weight' => ++$weight,
188     ] + $locked_language);
189
190     $languages[LanguageInterface::LANGCODE_NOT_APPLICABLE] = new Language([
191       'id' => LanguageInterface::LANGCODE_NOT_APPLICABLE,
192       'name' => new TranslatableMarkup('Not applicable'),
193       'weight' => ++$weight,
194     ] + $locked_language);
195
196     return $languages;
197   }
198
199   /**
200    * {@inheritdoc}
201    */
202   public function isLanguageLocked($langcode) {
203     $language = $this->getLanguage($langcode);
204     return ($language ? $language->isLocked() : FALSE);
205   }
206
207   /**
208    * {@inheritdoc}
209    */
210   public function getFallbackCandidates(array $context = []) {
211     return [LanguageInterface::LANGCODE_DEFAULT];
212   }
213
214   /**
215    * {@inheritdoc}
216    */
217   public function getLanguageSwitchLinks($type, Url $url) {
218     return [];
219   }
220
221   /**
222    * {@inheritdoc}
223    */
224   public static function getStandardLanguageList() {
225     // This list is based on languages available from localize.drupal.org. See
226     // http://localize.drupal.org/issues for information on how to add languages
227     // there.
228     //
229     // The "Left-to-right marker" comments and the enclosed UTF-8 markers are to
230     // make otherwise strange looking PHP syntax natural (to not be displayed in
231     // right to left). See https://www.drupal.org/node/128866#comment-528929.
232     return [
233       'af' => ['Afrikaans', 'Afrikaans'],
234       'am' => ['Amharic', 'አማርኛ'],
235       'ar' => ['Arabic', /* Left-to-right marker "‭" */ 'العربية', LanguageInterface::DIRECTION_RTL],
236       'ast' => ['Asturian', 'Asturianu'],
237       'az' => ['Azerbaijani', 'Azərbaycanca'],
238       'be' => ['Belarusian', 'Беларуская'],
239       'bg' => ['Bulgarian', 'Български'],
240       'bn' => ['Bengali', 'বাংলা'],
241       'bo' => ['Tibetan', 'བོད་སྐད་'],
242       'bs' => ['Bosnian', 'Bosanski'],
243       'ca' => ['Catalan', 'Català'],
244       'cs' => ['Czech', 'Čeština'],
245       'cy' => ['Welsh', 'Cymraeg'],
246       'da' => ['Danish', 'Dansk'],
247       'de' => ['German', 'Deutsch'],
248       'dz' => ['Dzongkha', 'རྫོང་ཁ'],
249       'el' => ['Greek', 'Ελληνικά'],
250       'en' => ['English', 'English'],
251       'en-x-simple' => ['Simple English', 'Simple English'],
252       'eo' => ['Esperanto', 'Esperanto'],
253       'es' => ['Spanish', 'Español'],
254       'et' => ['Estonian', 'Eesti'],
255       'eu' => ['Basque', 'Euskera'],
256       'fa' => ['Persian, Farsi', /* Left-to-right marker "‭" */ 'فارسی', LanguageInterface::DIRECTION_RTL],
257       'fi' => ['Finnish', 'Suomi'],
258       'fil' => ['Filipino', 'Filipino'],
259       'fo' => ['Faeroese', 'Føroyskt'],
260       'fr' => ['French', 'Français'],
261       'fy' => ['Frisian, Western', 'Frysk'],
262       'ga' => ['Irish', 'Gaeilge'],
263       'gd' => ['Scots Gaelic', 'Gàidhlig'],
264       'gl' => ['Galician', 'Galego'],
265       'gsw-berne' => ['Swiss German', 'Schwyzerdütsch'],
266       'gu' => ['Gujarati', 'ગુજરાતી'],
267       'he' => ['Hebrew', /* Left-to-right marker "‭" */ 'עברית', LanguageInterface::DIRECTION_RTL],
268       'hi' => ['Hindi', 'हिन्दी'],
269       'hr' => ['Croatian', 'Hrvatski'],
270       'ht' => ['Haitian Creole', 'Kreyòl ayisyen'],
271       'hu' => ['Hungarian', 'Magyar'],
272       'hy' => ['Armenian', 'Հայերեն'],
273       'id' => ['Indonesian', 'Bahasa Indonesia'],
274       'is' => ['Icelandic', 'Íslenska'],
275       'it' => ['Italian', 'Italiano'],
276       'ja' => ['Japanese', '日本語'],
277       'jv' => ['Javanese', 'Basa Java'],
278       'ka' => ['Georgian', 'ქართული ენა'],
279       'kk' => ['Kazakh', 'Қазақ'],
280       'km' => ['Khmer', 'ភាសាខ្មែរ'],
281       'kn' => ['Kannada', 'ಕನ್ನಡ'],
282       'ko' => ['Korean', '한국어'],
283       'ku' => ['Kurdish', 'Kurdî'],
284       'ky' => ['Kyrgyz', 'Кыргызча'],
285       'lo' => ['Lao', 'ພາສາລາວ'],
286       'lt' => ['Lithuanian', 'Lietuvių'],
287       'lv' => ['Latvian', 'Latviešu'],
288       'mg' => ['Malagasy', 'Malagasy'],
289       'mk' => ['Macedonian', 'Македонски'],
290       'ml' => ['Malayalam', 'മലയാളം'],
291       'mn' => ['Mongolian', 'монгол'],
292       'mr' => ['Marathi', 'मराठी'],
293       'ms' => ['Bahasa Malaysia', 'بهاس ملايو'],
294       'my' => ['Burmese', 'ဗမာစကား'],
295       'ne' => ['Nepali', 'नेपाली'],
296       'nl' => ['Dutch', 'Nederlands'],
297       'nb' => ['Norwegian Bokmål', 'Norsk, bokmål'],
298       'nn' => ['Norwegian Nynorsk', 'Norsk, nynorsk'],
299       'oc' => ['Occitan', 'Occitan'],
300       'pa' => ['Punjabi', 'ਪੰਜਾਬੀ'],
301       'pl' => ['Polish', 'Polski'],
302       'pt-pt' => ['Portuguese, Portugal', 'Português, Portugal'],
303       'pt-br' => ['Portuguese, Brazil', 'Português, Brasil'],
304       'ro' => ['Romanian', 'Română'],
305       'ru' => ['Russian', 'Русский'],
306       'sco' => ['Scots', 'Scots'],
307       'se' => ['Northern Sami', 'Sámi'],
308       'si' => ['Sinhala', 'සිංහල'],
309       'sk' => ['Slovak', 'Slovenčina'],
310       'sl' => ['Slovenian', 'Slovenščina'],
311       'sq' => ['Albanian', 'Shqip'],
312       'sr' => ['Serbian', 'Српски'],
313       'sv' => ['Swedish', 'Svenska'],
314       'sw' => ['Swahili', 'Kiswahili'],
315       'ta' => ['Tamil', 'தமிழ்'],
316       'ta-lk' => ['Tamil, Sri Lanka', 'தமிழ், இலங்கை'],
317       'te' => ['Telugu', 'తెలుగు'],
318       'th' => ['Thai', 'ภาษาไทย'],
319       'tr' => ['Turkish', 'Türkçe'],
320       'tyv' => ['Tuvan', 'Тыва дыл'],
321       'ug' => ['Uyghur', /* Left-to-right marker "‭" */ 'ئۇيغۇرچە', LanguageInterface::DIRECTION_RTL],
322       'uk' => ['Ukrainian', 'Українська'],
323       'ur' => ['Urdu', /* Left-to-right marker "‭" */ 'اردو', LanguageInterface::DIRECTION_RTL],
324       'vi' => ['Vietnamese', 'Tiếng Việt'],
325       'xx-lolspeak' => ['Lolspeak', 'Lolspeak'],
326       'zh-hans' => ['Chinese, Simplified', '简体中文'],
327       'zh-hant' => ['Chinese, Traditional', '繁體中文'],
328     ];
329   }
330
331   /**
332    * The 6 official languages used at the United Nations.
333    *
334    * This list is based on
335    * http://www.un.org/en/sections/about-un/official-languages/index.html and it
336    * uses the same format as getStandardLanguageList().
337    *
338    * @return array
339    *   An array with language codes as keys, and English and native language
340    *   names as values.
341    */
342   public static function getUnitedNationsLanguageList() {
343     return [
344       'ar' => ['Arabic', /* Left-to-right marker "‭" */ 'العربية', LanguageInterface::DIRECTION_RTL],
345       'zh-hans' => ['Chinese, Simplified', '简体中文'],
346       'en' => ['English', 'English'],
347       'fr' => ['French', 'Français'],
348       'ru' => ['Russian', 'Русский'],
349       'es' => ['Spanish', 'Español'],
350     ];
351   }
352
353   /**
354    * {@inheritdoc}
355    *
356    * This function is a noop since the configuration cannot be overridden by
357    * language unless the Language module is enabled. That replaces the default
358    * language manager with a configurable language manager.
359    *
360    * @see \Drupal\language\ConfigurableLanguageManager::setConfigOverrideLanguage()
361    */
362   public function setConfigOverrideLanguage(LanguageInterface $language = NULL) {
363     return $this;
364   }
365
366   /**
367    * {@inheritdoc}
368    */
369   public function getConfigOverrideLanguage() {
370     return $this->getCurrentLanguage();
371   }
372
373   /**
374    * Filters the full list of languages based on the value of the flag.
375    *
376    * The locked languages are removed by default.
377    *
378    * @param \Drupal\Core\Language\LanguageInterface[] $languages
379    *    Array with languages to be filtered.
380    * @param int $flags
381    *   (optional) Specifies the state of the languages that have to be returned.
382    *   It can be: LanguageInterface::STATE_CONFIGURABLE,
383    *   LanguageInterface::STATE_LOCKED, or LanguageInterface::STATE_ALL.
384    *
385    * @return \Drupal\Core\Language\LanguageInterface[]
386    *   An associative array of languages, keyed by the language code.
387    */
388   protected function filterLanguages(array $languages, $flags = LanguageInterface::STATE_CONFIGURABLE) {
389     // STATE_ALL means we don't actually filter, so skip the rest of the method.
390     if ($flags == LanguageInterface::STATE_ALL) {
391       return $languages;
392     }
393
394     $filtered_languages = [];
395     // Add the site's default language if requested.
396     if ($flags & LanguageInterface::STATE_SITE_DEFAULT) {
397
398       // Setup a language to have the defaults with data appropriate of the
399       // default language only for runtime.
400       $defaultLanguage = $this->getDefaultLanguage();
401       $default = new Language(
402         [
403           'id' => $defaultLanguage->getId(),
404           'name' => new TranslatableMarkup("Site's default language (@lang_name)",
405             ['@lang_name' => $defaultLanguage->getName()]),
406           'direction' => $defaultLanguage->getDirection(),
407           'weight' => $defaultLanguage->getWeight(),
408         ]
409       );
410       $filtered_languages[LanguageInterface::LANGCODE_SITE_DEFAULT] = $default;
411     }
412
413     foreach ($languages as $id => $language) {
414       if (($language->isLocked() && ($flags & LanguageInterface::STATE_LOCKED)) || (!$language->isLocked() && ($flags & LanguageInterface::STATE_CONFIGURABLE))) {
415         $filtered_languages[$id] = $language;
416       }
417     }
418
419     return $filtered_languages;
420   }
421
422 }