annotate core/lib/Drupal/Core/Language/LanguageManager.php @ 19:fa3358dc1485 tip

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