Issue #1879930 by fran seva, Gábor Hojtsy, martin107, markie, Schnitzel, alexpott, Sutharsan, mon_franco, YesCT, spearhead93, herom, Désiré: Fixed Language selectors are not showing localized to the page language.
parent
ed4cedc09a
commit
51fcd31ce5
|
@ -80,7 +80,9 @@ class Language implements LanguageInterface {
|
|||
public function __construct(array $values = array()) {
|
||||
// Set all the provided properties for the language.
|
||||
foreach ($values as $key => $value) {
|
||||
$this->{$key} = $value;
|
||||
if (property_exists($this, $key)) {
|
||||
$this->{$key} = $value;
|
||||
}
|
||||
}
|
||||
// If some values were not set, set sane defaults of a predefined language.
|
||||
if (!isset($values['name']) || !isset($values['direction'])) {
|
||||
|
|
|
@ -27,11 +27,17 @@ class LanguageManager implements LanguageManagerInterface {
|
|||
protected $translation;
|
||||
|
||||
/**
|
||||
* An array of all the available languages keyed by language code.
|
||||
* 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).
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageInterface[]
|
||||
*
|
||||
* @see \Drupal\Core\Language\LanguageManager::getLanguages()
|
||||
*/
|
||||
protected $languages;
|
||||
protected $languages = array();
|
||||
|
||||
/**
|
||||
* The default language object.
|
||||
|
@ -130,35 +136,19 @@ class LanguageManager implements LanguageManagerInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLanguages($flags = LanguageInterface::STATE_CONFIGURABLE) {
|
||||
// Initialize master language list.
|
||||
if (!isset($this->languages)) {
|
||||
// No language module, so use the default language only.
|
||||
$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.
|
||||
$default = $this->getDefaultLanguage();
|
||||
$this->languages = array($default->getId() => $default);
|
||||
// Add the special languages, they will be filtered later if needed.
|
||||
$this->languages += $this->getDefaultLockedLanguages($default->getWeight());
|
||||
$languages = array($default->getId() => $default);
|
||||
$languages += $this->getDefaultLockedLanguages($default->getWeight());
|
||||
|
||||
// Filter the full list of languages based on the value of $flags.
|
||||
$this->languages[$static_cache_id][$flags] = $this->filterLanguages($languages, $flags);
|
||||
}
|
||||
|
||||
// Filter the full list of languages based on the value of the $all flag. By
|
||||
// default we remove the locked languages, but the caller may request for
|
||||
// those languages to be added as well.
|
||||
$filtered_languages = array();
|
||||
|
||||
// Add the site's default language if flagged as allowed value.
|
||||
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 ($this->languages as $id => $language) {
|
||||
if (($language->isLocked() && ($flags & LanguageInterface::STATE_LOCKED)) || (!$language->isLocked() && ($flags & LanguageInterface::STATE_CONFIGURABLE))) {
|
||||
$filtered_languages[$id] = $language;
|
||||
}
|
||||
}
|
||||
|
||||
return $filtered_languages;
|
||||
return $this->languages[$static_cache_id][$flags];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -382,4 +372,44 @@ class LanguageManager implements LanguageManagerInterface {
|
|||
return $this->getCurrentLanguage();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@ use Drupal\Core\Language\LanguageManager;
|
|||
use Drupal\Core\Url;
|
||||
use Drupal\language\Config\LanguageConfigFactoryOverrideInterface;
|
||||
use Drupal\language\Entity\ConfigurableLanguage;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
/**
|
||||
|
@ -247,7 +246,7 @@ class ConfigurableLanguageManager extends LanguageManager implements Configurabl
|
|||
$this->negotiatedMethods = array();
|
||||
$this->languageTypes = NULL;
|
||||
$this->languageTypesInfo = NULL;
|
||||
$this->languages = NULL;
|
||||
$this->languages = array();
|
||||
if ($this->negotiator) {
|
||||
$this->negotiator->reset();
|
||||
}
|
||||
|
@ -279,37 +278,47 @@ class ConfigurableLanguageManager extends LanguageManager implements Configurabl
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLanguages($flags = LanguageInterface::STATE_CONFIGURABLE) {
|
||||
if (!isset($this->languages)) {
|
||||
// Prepopulate the language list with the default language to keep things
|
||||
// working even if we have no configuration.
|
||||
$default = $this->getDefaultLanguage();
|
||||
$this->languages = array($default->getId() => $default);
|
||||
|
||||
// Retrieve the list of languages defined in configuration.
|
||||
$prefix = 'language.entity.';
|
||||
$config_ids = $this->configFactory->listAll($prefix);
|
||||
|
||||
// Instantiate languages from config objects.
|
||||
$weight = 0;
|
||||
foreach ($this->configFactory->loadMultiple($config_ids) as $config) {
|
||||
$data = $config->get();
|
||||
$langcode = $data['id'];
|
||||
// Initialize default property so callers have an easy reference and can
|
||||
// save the same object without data loss.
|
||||
$data['default'] = ($langcode == $default->getId());
|
||||
$data['name'] = $data['label'];
|
||||
$this->languages[$langcode] = new Language($data);
|
||||
$weight = max(array($weight, $this->languages[$langcode]->getWeight()));
|
||||
}
|
||||
|
||||
// Add locked languages, they will be filtered later if needed.
|
||||
$this->languages += $this->getDefaultLockedLanguages($weight);
|
||||
|
||||
// Sort the language list by weight then title.
|
||||
Language::sort($this->languages);
|
||||
// If a config override is set, cache using that language's ID.
|
||||
if ($override_language = $this->getConfigOverrideLanguage()) {
|
||||
$static_cache_id = $override_language->getId();
|
||||
}
|
||||
else {
|
||||
$static_cache_id = $this->getCurrentLanguage()->getId();
|
||||
}
|
||||
|
||||
return parent::getLanguages($flags);
|
||||
if (!isset($this->languages[$static_cache_id][$flags])) {
|
||||
// Initialize the language list with the default language and default
|
||||
// locked languages. These cannot be removed. This serves as a fallback
|
||||
// list if this method is invoked while the language module is installed
|
||||
// and the configuration entities for languages are not yet fully
|
||||
// imported.
|
||||
$default = $this->getDefaultLanguage();
|
||||
$languages = array($default->getId() => $default);
|
||||
$languages += $this->getDefaultLockedLanguages($default->getWeight());
|
||||
|
||||
// Load configurable languages on top of the defaults. Ideally this could
|
||||
// use the entity API to load and instantiate ConfigurableLanguage
|
||||
// objects. However the entity API depends on the language system, so that
|
||||
// would result in infinite loops. We use the configuration system
|
||||
// directly and instantiate runtime Language objects. When language
|
||||
// entities are imported those cover the default and locked languages, so
|
||||
// site-specific configuration will prevail over the fallback values.
|
||||
// Having them in the array already ensures if this is invoked in the
|
||||
// middle of importing language configuration entities, the defaults are
|
||||
// always present.
|
||||
$config_ids = $this->configFactory->listAll('language.entity.');
|
||||
foreach ($this->configFactory->loadMultiple($config_ids) as $config) {
|
||||
$data = $config->get();
|
||||
$data['name'] = $data['label'];
|
||||
$languages[$data['id']] = new Language($data);
|
||||
}
|
||||
Language::sort($languages);
|
||||
|
||||
// Filter the full list of languages based on the value of $flags.
|
||||
$this->languages[$static_cache_id][$flags] = $this->filterLanguages($languages, $flags);
|
||||
}
|
||||
|
||||
return $this->languages[$static_cache_id][$flags];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\language\Tests\LanguageSelectorTranslatableTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\language\Tests;
|
||||
|
||||
use Drupal\simpletest\WebTestBase;
|
||||
|
||||
/**
|
||||
* Tests the content translation settings language selector options.
|
||||
*
|
||||
* @group language
|
||||
*/
|
||||
class LanguageSelectorTranslatableTest extends WebTestBase {
|
||||
|
||||
/**
|
||||
* Modules to enable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public static $modules = array(
|
||||
'language',
|
||||
'content_translation',
|
||||
'node',
|
||||
'comment',
|
||||
'field_ui',
|
||||
'entity_test',
|
||||
'locale',
|
||||
);
|
||||
|
||||
/**
|
||||
* The user with administrator privileges.
|
||||
*
|
||||
* @var \Drupal\user\Entity\User;
|
||||
*/
|
||||
public $administrator;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
// Create user and set permissions.
|
||||
$this->administrator = $this->drupalCreateUser($this->getAdministratorPermissions(), 'administrator');
|
||||
$this->drupalLogin($this->administrator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of permissions needed for the translator.
|
||||
*/
|
||||
protected function getAdministratorPermissions() {
|
||||
return array_filter(
|
||||
array('translate interface',
|
||||
'administer content translation',
|
||||
'create content translations',
|
||||
'update content translations',
|
||||
'delete content translations',
|
||||
'administer languages',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests content translation language selectors are correctly translated.
|
||||
*/
|
||||
public function testLanguageStringSelector() {
|
||||
// Add another language.
|
||||
$edit = array('predefined_langcode' => 'es');
|
||||
$this->drupalPostForm('admin/config/regional/language/add', $edit, t('Add language'));
|
||||
|
||||
// Translate the string English in Spanish (Inglés). Override config entity.
|
||||
$name_translation = 'Inglés';
|
||||
\Drupal::languageManager()
|
||||
->getLanguageConfigOverride('es', 'language.entity.en')
|
||||
->set('label', $name_translation)
|
||||
->save();
|
||||
|
||||
// Check content translation overview selector.
|
||||
$path = 'es/admin/config/regional/content-language';
|
||||
$this->drupalGet($path);
|
||||
|
||||
// Get en language from selector.
|
||||
$elements = $this->xpath('//select[@id=:id]//option[@value=:option]', array(':id' => 'edit-settings-node-node-settings-language-langcode', ':option' => 'en'));
|
||||
|
||||
// Check that the language text is translated.
|
||||
$this->assertEqual((string) $elements[0], $name_translation, 'Checking the option string English is translated to Spanish.');
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,20 @@ use Drupal\Tests\UnitTestCase;
|
|||
*/
|
||||
class LanguageUnitTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* @covers ::__construct
|
||||
*/
|
||||
public function testConstruct() {
|
||||
$name = $this->randomMachineName();
|
||||
$language_code = $this->randomMachineName(2);
|
||||
$uuid = $this->randomMachineName();
|
||||
$language = new Language(array('id' => $language_code, 'name' => $name, 'uuid' => $uuid));
|
||||
// Test that nonexistent properties are not added to the language object.
|
||||
$this->assertTrue(property_exists($language, 'id'));
|
||||
$this->assertTrue(property_exists($language, 'name'));
|
||||
$this->assertFalse(property_exists($language, 'uuid'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::getName()
|
||||
* @covers ::setName()
|
||||
|
|
Loading…
Reference in New Issue