diff --git a/core/lib/Drupal/Core/Language/Language.php b/core/lib/Drupal/Core/Language/Language.php index 46fb892f8a597af55699ed6fb8f052a53fa0fc3a..675ca477773f48887281f912892dffb367ed47d3 100644 --- a/core/lib/Drupal/Core/Language/Language.php +++ b/core/lib/Drupal/Core/Language/Language.php @@ -7,6 +7,8 @@ namespace Drupal\Core\Language; +use Drupal\Core\StringTranslation\TranslatableMarkup; + /** * An object containing the information for an interface language. * @@ -151,7 +153,17 @@ public static function sort(&$languages) { $a_weight = $a->getWeight(); $b_weight = $b->getWeight(); if ($a_weight == $b_weight) { - return strnatcasecmp($a->getName(), $b->getName()); + $a_name = $a->getName(); + $b_name = $b->getName(); + // If either name is a TranslatableMarkup object it can not be converted + // to a string. This is because translation requires a sorted list of + // languages thereby causing an infinite loop. Determine the order based + // on ID if this is the case. + if ($a_name instanceof TranslatableMarkup || $b_name instanceof TranslatableMarkup) { + $a_name = $a->getId(); + $b_name = $b->getId(); + } + return strnatcasecmp($a_name, $b_name); } return ($a_weight < $b_weight) ? -1 : 1; }); diff --git a/core/modules/locale/src/Tests/LocaleConfigurableLanguageManagerTest.php b/core/modules/locale/src/Tests/LocaleConfigurableLanguageManagerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6bdbc43731431f2068ae3515361546826afbedea --- /dev/null +++ b/core/modules/locale/src/Tests/LocaleConfigurableLanguageManagerTest.php @@ -0,0 +1,51 @@ +<?php + +/** + * @file + * Contains \Drupal\locale\Tests\LocaleConfigurableLanguageManagerTest. + */ + +namespace Drupal\locale\Tests; + +use Drupal\Core\Language\LanguageInterface; +use Drupal\language\Entity\ConfigurableLanguage; +use Drupal\simpletest\KernelTestBase; + + +/** + * Tests that the configurable language manager and locale operate correctly. + * + * @group locale + */ +class LocaleConfigurableLanguageManagerTest extends KernelTestBase { + + /** + * A list of modules to install for this test. + * + * @var array + */ + public static $modules = ['language', 'locale']; + + public function testGetLanguages() { + $this->installSchema('locale', ['locales_source', 'locales_target', 'locales_location']); + $default_language = new ConfigurableLanguage(['label' => $this->randomMachineName(), 'id' => 'default', 'weight' => 0], 'configurable_language'); + $default_language->save(); + + // Set new default language. + \Drupal::service('language.default')->set($default_language); + \Drupal::service('string_translation')->setDefaultLangcode($default_language->getId()); + + $languages = \Drupal::service('language_manager')->getLanguages(LanguageInterface::STATE_ALL); + $this->assertEqual(['default', 'und', 'zxx'], array_keys($languages)); + + $configurableLanguage = new ConfigurableLanguage(['label' => $this->randomMachineName(), 'id' => 'test', 'weight' => 1], 'configurable_language'); + // Simulate a configuration sync by setting the flag otherwise the locked + // language weights would be updated whilst saving. + // @see \Drupal\language\Entity\ConfigurableLanguage::postSave() + $configurableLanguage->setSyncing(TRUE)->save(); + + $languages = \Drupal::service('language_manager')->getLanguages(LanguageInterface::STATE_ALL); + $this->assertEqual(['default', 'test', 'und', 'zxx'], array_keys($languages)); + } + +}