LanguageManager.php 14.6 KB
Newer Older
1 2 3 4
<?php

/**
 * @file
5
 * Contains \Drupal\Core\Language\LanguageManager.
6 7 8 9
 */

namespace Drupal\Core\Language;

10
use Drupal\Component\Utility\String;
11
use Drupal\Core\DependencyInjection\DependencySerializationTrait;
12
use Drupal\Core\StringTranslation\TranslationInterface;
13
use Drupal\Core\StringTranslation\TranslationWrapper;
14
use Drupal\Core\Url;
15 16

/**
17
 * Class responsible for providing language support on language-unaware sites.
18
 */
19 20
class LanguageManager implements LanguageManagerInterface {
  use DependencySerializationTrait;
21

22
  /**
23
   * The string translation service.
24
   *
25
   * @var \Drupal\Core\StringTranslation\TranslationInterface
26
   */
27
  protected $translation;
28

29
  /**
30 31 32 33 34
   * A static cache of translated language lists.
   *
   * Array of arrays to cache the result of self::getLanguages() keyed by the
   * language the list is translated to (first level) and the flags provided to
   * the method (second level).
35
   *
36
   * @var \Drupal\Core\Language\LanguageInterface[]
37 38
   *
   * @see \Drupal\Core\Language\LanguageManager::getLanguages()
39
   */
40
  protected $languages = array();
41

42
  /**
43
   * The default language object.
44
   *
45
   * @var \Drupal\Core\Language\LanguageDefault
46
   */
47
  protected $defaultLanguage;
48

49 50 51
  /**
   * Constructs the language manager.
   *
52
   * @param \Drupal\Core\Language\LanguageDefault $default_language
53 54 55 56 57 58
   *   The default language.
   */
  public function __construct(LanguageDefault $default_language) {
    $this->defaultLanguage = $default_language;
  }

59
  /**
60
   * {@inheritdoc}
61
   */
62
  public function setTranslation(TranslationInterface $translation) {
63 64
    $this->translation = $translation;
  }
65 66

  /**
67
   * Translates a string to the current language or to a given language.
68
   *
69
   * @see \Drupal\Core\StringTranslation\TranslationInterface()
70
   */
71 72 73
  protected function t($string, array $args = array(), array $options = array()) {
    return $this->translation ? $this->translation->translate($string, $args, $options) : String::format($string, $args);
  }
74

75
  /**
76
   * {@inheritdoc}
77
   */
78 79
  public function isMultilingual() {
    return FALSE;
80 81
  }

82
  /**
83
   * {@inheritdoc}
84
   */
85
  public function getLanguageTypes() {
86
    return array(LanguageInterface::TYPE_INTERFACE, LanguageInterface::TYPE_CONTENT, LanguageInterface::TYPE_URL);
87 88
  }

89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
  /**
   * {@inheritdoc}
   */
  public function getDefinedLanguageTypesInfo() {
    // This needs to have the same return value as
    // language_language_type_info(), so that even if the Language module is
    // not defined, users of this information, such as the Views module, can
    // access names and descriptions of the default language types.
    return array(
      LanguageInterface::TYPE_INTERFACE => array(
        'name' => $this->t('User interface text'),
        'description' => $this->t('Order of language detection methods for user interface text. If a translation of user interface text is available in the detected language, it will be displayed.'),
        'locked' => TRUE,
      ),
      LanguageInterface::TYPE_CONTENT => array(
        'name' => $this->t('Content'),
        'description' => $this->t('Order of language detection methods for content. If a version of content is available in the detected language, it will be displayed.'),
        'locked' => TRUE,
      ),
      LanguageInterface::TYPE_URL => array(
        'locked' => TRUE,
      ),
    );
  }

114
  /**
115
   * {@inheritdoc}
116
   */
117
  public function getCurrentLanguage($type = LanguageInterface::TYPE_INTERFACE) {
118
    return $this->getDefaultLanguage();
119 120
  }

121
  /**
122
   * {@inheritdoc}
123
   */
124
  public function reset($type = NULL) {
125
    return $this;
126
  }
127

128 129 130 131
  /**
   * {@inheritdoc}
   */
  public function getDefaultLanguage() {
132
    return $this->defaultLanguage->get();
133 134
  }

135
  /**
136
   * {@inheritdoc}
137
   */
138
  public function getLanguages($flags = LanguageInterface::STATE_CONFIGURABLE) {
139 140 141 142 143
    $static_cache_id = $this->getCurrentLanguage()->getId();
    if (!isset($this->languages[$static_cache_id][$flags])) {
      // If this language manager is used, there are no configured languages.
      // The default language and locked languages comprise the full language
      // list.
144
      $default = $this->getDefaultLanguage();
145 146
      $languages = array($default->getId() => $default);
      $languages += $this->getDefaultLockedLanguages($default->getWeight());
147

148 149
      // Filter the full list of languages based on the value of $flags.
      $this->languages[$static_cache_id][$flags] = $this->filterLanguages($languages, $flags);
150
    }
151
    return $this->languages[$static_cache_id][$flags];
152
  }
153

154 155 156 157 158 159 160 161
  /**
   * {@inheritdoc}
   */
  public function getNativeLanguages() {
    // In a language unaware site we don't have translated languages.
    return $this->getLanguages();
  }

162
  /**
163
   * {@inheritdoc}
164
   */
165
  public function getLanguage($langcode) {
166
    $languages = $this->getLanguages(LanguageInterface::STATE_ALL);
167
    return isset($languages[$langcode]) ? $languages[$langcode] : NULL;
168 169
  }

170
  /**
171
   * {@inheritdoc}
172
   */
173
  public function getLanguageName($langcode) {
174
    if ($langcode == LanguageInterface::LANGCODE_NOT_SPECIFIED) {
175 176 177
      return $this->t('None');
    }
    if ($language = $this->getLanguage($langcode)) {
178
      return $language->getName();
179
    }
180 181
    if (empty($langcode)) {
      return $this->t('Unknown');
182
    }
183 184 185 186 187 188 189 190 191 192 193 194
    return $this->t('Unknown (@langcode)', array('@langcode' => $langcode));
  }

  /**
   * {@inheritdoc}
   */
  public function getDefaultLockedLanguages($weight = 0) {
    $languages = array();

    $locked_language = array(
      'default' => FALSE,
      'locked' => TRUE,
195
    );
196 197
    // This is called very early while initializing the language system. Prevent
    // early t() calls by using the TranslationWrapper.
198 199
    $languages[LanguageInterface::LANGCODE_NOT_SPECIFIED] = new Language(array(
      'id' => LanguageInterface::LANGCODE_NOT_SPECIFIED,
200
      'name' => new TranslationWrapper('Not specified'),
201 202 203
      'weight' => ++$weight,
    ) + $locked_language);

204 205
    $languages[LanguageInterface::LANGCODE_NOT_APPLICABLE] = new Language(array(
      'id' => LanguageInterface::LANGCODE_NOT_APPLICABLE,
206
      'name' => new TranslationWrapper('Not applicable'),
207 208 209 210 211
      'weight' => ++$weight,
    ) + $locked_language);

    return $languages;
  }
212

213 214 215 216 217
  /**
   * {@inheritdoc}
   */
  public function isLanguageLocked($langcode) {
    $language = $this->getLanguage($langcode);
218
    return ($language ? $language->isLocked() : FALSE);
219 220
  }

221
  /**
222
   * {@inheritdoc}
223
   */
224
  public function getFallbackCandidates(array $context = array()) {
225
    return array(LanguageInterface::LANGCODE_DEFAULT);
226 227 228
  }

  /**
229
   * {@inheritdoc}
230
   */
231
  public function getLanguageSwitchLinks($type, Url $url) {
232
    return array();
233 234
  }

235 236 237 238
  /**
   * Some common languages with their English and native names.
   *
   * Language codes are defined by the W3C language tags document for
239 240 241 242
   * interoperability. Language codes typically have a language and, optionally,
   * a script or regional variant name. See:
   * http://www.w3.org/International/articles/language-tags/ for more
   * information.
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
   *
   * This list is based on languages available from localize.drupal.org. See
   * http://localize.drupal.org/issues for information on how to add languages
   * there.
   *
   * The "Left-to-right marker" comments and the enclosed UTF-8 markers are to
   * make otherwise strange looking PHP syntax natural (to not be displayed in
   * right to left). See http://drupal.org/node/128866#comment-528929.
   *
   * @return array
   *   An array of language code to language name information.
   *   Language name information itself is an array of English and native names.
   */
  public static function getStandardLanguageList() {
    return array(
      'af' => array('Afrikaans', 'Afrikaans'),
      'am' => array('Amharic', 'አማርኛ'),
260
      'ar' => array('Arabic', /* Left-to-right marker "‭" */ 'العربية', LanguageInterface::DIRECTION_RTL),
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
      'ast' => array('Asturian', 'Asturianu'),
      'az' => array('Azerbaijani', 'Azərbaycanca'),
      'be' => array('Belarusian', 'Беларуская'),
      'bg' => array('Bulgarian', 'Български'),
      'bn' => array('Bengali', 'বাংলা'),
      'bo' => array('Tibetan', 'བོད་སྐད་'),
      'bs' => array('Bosnian', 'Bosanski'),
      'ca' => array('Catalan', 'Català'),
      'cs' => array('Czech', 'Čeština'),
      'cy' => array('Welsh', 'Cymraeg'),
      'da' => array('Danish', 'Dansk'),
      'de' => array('German', 'Deutsch'),
      'dz' => array('Dzongkha', 'རྫོང་ཁ'),
      'el' => array('Greek', 'Ελληνικά'),
      'en' => array('English', 'English'),
      'eo' => array('Esperanto', 'Esperanto'),
      'es' => array('Spanish', 'Español'),
      'et' => array('Estonian', 'Eesti'),
      'eu' => array('Basque', 'Euskera'),
280
      'fa' => array('Persian, Farsi', /* Left-to-right marker "‭" */ 'فارسی', LanguageInterface::DIRECTION_RTL),
281 282 283 284
      'fi' => array('Finnish', 'Suomi'),
      'fil' => array('Filipino', 'Filipino'),
      'fo' => array('Faeroese', 'Føroyskt'),
      'fr' => array('French', 'Français'),
285 286
      'fy' => array('Frisian, Western', 'Frysk'),
      'ga' => array('Irish', 'Gaeilge'),
287 288 289 290
      'gd' => array('Scots Gaelic', 'Gàidhlig'),
      'gl' => array('Galician', 'Galego'),
      'gsw-berne' => array('Swiss German', 'Schwyzerdütsch'),
      'gu' => array('Gujarati', 'ગુજરાતી'),
291
      'he' => array('Hebrew', /* Left-to-right marker "‭" */ 'עברית', LanguageInterface::DIRECTION_RTL),
292 293 294 295
      'hi' => array('Hindi', 'हिन्दी'),
      'hr' => array('Croatian', 'Hrvatski'),
      'ht' => array('Haitian Creole', 'Kreyòl ayisyen'),
      'hu' => array('Hungarian', 'Magyar'),
296
      'hy' => array('Armenian', 'Հայերեն'),
297 298 299 300 301 302 303
      'id' => array('Indonesian', 'Bahasa Indonesia'),
      'is' => array('Icelandic', 'Íslenska'),
      'it' => array('Italian', 'Italiano'),
      'ja' => array('Japanese', '日本語'),
      'jv' => array('Javanese', 'Basa Java'),
      'ka' => array('Georgian', 'ქართული ენა'),
      'kk' => array('Kazakh', 'Қазақ'),
304
      'km' => array('Khmer', 'ភាសាខ្មែរ'),
305 306 307 308 309 310 311 312 313 314 315 316
      'kn' => array('Kannada', 'ಕನ್ನಡ'),
      'ko' => array('Korean', '한국어'),
      'ku' => array('Kurdish', 'Kurdî'),
      'ky' => array('Kyrgyz', 'Кыргызча'),
      'lo' => array('Lao', 'ພາສາລາວ'),
      'lt' => array('Lithuanian', 'Lietuvių'),
      'lv' => array('Latvian', 'Latviešu'),
      'mg' => array('Malagasy', 'Malagasy'),
      'mk' => array('Macedonian', 'Македонски'),
      'ml' => array('Malayalam', 'മലയാളം'),
      'mn' => array('Mongolian', 'монгол'),
      'mr' => array('Marathi', 'मराठी'),
317
      'ms' => array('Bahasa Malaysia', 'بهاس ملايو'),
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
      'my' => array('Burmese', 'ဗမာစကား'),
      'ne' => array('Nepali', 'नेपाली'),
      'nl' => array('Dutch', 'Nederlands'),
      'nb' => array('Norwegian Bokmål', 'Bokmål'),
      'nn' => array('Norwegian Nynorsk', 'Nynorsk'),
      'oc' => array('Occitan', 'Occitan'),
      'pa' => array('Punjabi', 'ਪੰਜਾਬੀ'),
      'pl' => array('Polish', 'Polski'),
      'pt-pt' => array('Portuguese, Portugal', 'Português, Portugal'),
      'pt-br' => array('Portuguese, Brazil', 'Português, Brasil'),
      'ro' => array('Romanian', 'Română'),
      'ru' => array('Russian', 'Русский'),
      'sco' => array('Scots', 'Scots'),
      'se' => array('Northern Sami', 'Sámi'),
      'si' => array('Sinhala', 'සිංහල'),
      'sk' => array('Slovak', 'Slovenčina'),
      'sl' => array('Slovenian', 'Slovenščina'),
      'sq' => array('Albanian', 'Shqip'),
      'sr' => array('Serbian', 'Српски'),
      'sv' => array('Swedish', 'Svenska'),
338
      'sw' => array('Swahili', 'Kiswahili'),
339 340 341 342 343 344 345 346
      'ta' => array('Tamil', 'தமிழ்'),
      'ta-lk' => array('Tamil, Sri Lanka', 'தமிழ், இலங்கை'),
      'te' => array('Telugu', 'తెలుగు'),
      'th' => array('Thai', 'ภาษาไทย'),
      'tr' => array('Turkish', 'Türkçe'),
      'tyv' => array('Tuvan', 'Тыва дыл'),
      'ug' => array('Uyghur', 'Уйғур'),
      'uk' => array('Ukrainian', 'Українська'),
347
      'ur' => array('Urdu', /* Left-to-right marker "‭" */ 'اردو', LanguageInterface::DIRECTION_RTL),
348 349 350 351 352 353 354
      'vi' => array('Vietnamese', 'Tiếng Việt'),
      'xx-lolspeak' => array('Lolspeak', 'Lolspeak'),
      'zh-hans' => array('Chinese, Simplified', '简体中文'),
      'zh-hant' => array('Chinese, Traditional', '繁體中文'),
    );
  }

355 356 357
  /**
   * {@inheritdoc}
   *
358
   * This function is a noop since the configuration cannot be overridden by
359
   * language unless the Language module is enabled. That replaces the default
360
   * language manager with a configurable language manager.
361 362 363
   *
   * @see \Drupal\language\ConfigurableLanguageManager::setConfigOverrideLanguage()
   */
364
  public function setConfigOverrideLanguage(LanguageInterface $language = NULL) {
365 366 367 368 369 370 371 372 373 374
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getConfigOverrideLanguage() {
    return $this->getCurrentLanguage();
  }

375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414

  /**
   * Filters the full list of languages based on the value of the flag.
   *
   * The locked languages are removed by default.
   *
   * @param \Drupal\Core\Language\LanguageInterface[] $languages
   *    Array with languages to be filtered.
   * @param int $flags
   *   (optional) Specifies the state of the languages that have to be returned.
   *   It can be: LanguageInterface::STATE_CONFIGURABLE,
   *   LanguageInterface::STATE_LOCKED, or LanguageInterface::STATE_ALL.
   *
   * @return \Drupal\Core\Language\LanguageInterface[]
   *   An associative array of languages, keyed by the language code.
   */
  protected function filterLanguages(array $languages, $flags = LanguageInterface::STATE_CONFIGURABLE) {
    // STATE_ALL means we don't actually filter, so skip the rest of the method.
    if ($flags == LanguageInterface::STATE_ALL) {
      return $languages;
    }

    $filtered_languages = array();
    // Add the site's default language if requested.
    if ($flags & LanguageInterface::STATE_SITE_DEFAULT) {
      // Setup a language to have the defaults, but with overridden name.
      $default = $this->getDefaultLanguage();
      $default->setName($this->t("Site's default language (@lang_name)", array('@lang_name' => $default->getName())));
      $filtered_languages[LanguageInterface::LANGCODE_SITE_DEFAULT] = $default;
    }

    foreach ($languages as $id => $language) {
      if (($language->isLocked() && ($flags & LanguageInterface::STATE_LOCKED)) || (!$language->isLocked() && ($flags & LanguageInterface::STATE_CONFIGURABLE))) {
        $filtered_languages[$id] = $language;
      }
    }

    return $filtered_languages;
  }

Crell's avatar
Crell committed
415
}