diff --git a/core/includes/config.inc b/core/includes/config.inc index 8d0eea1..4f395eb 100644 --- a/core/includes/config.inc +++ b/core/includes/config.inc @@ -86,3 +86,21 @@ function config_get_storage_names_with_prefix($prefix = '') { function config($name, $class = 'Drupal\Core\Config\DrupalConfig') { return new $class(new DatabaseStorage($name)); } + +/** + * Wrapper for choosing the right translation from a config data array. + */ +function config_get_language($data, $langcode) { + if (!$langcode) { + $langcode = drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode; + } + if (isset($data[$langcode])) { + return $data[$langcode]; + } + elseif (isset($data['_default']['language'])) { + return $data[$data['_default']['language']]; + } + else { + return $data['en']; + } +} diff --git a/core/lib/Drupal/Core/Config/DrupalConfig.php b/core/lib/Drupal/Core/Config/DrupalConfig.php index f5a9220..806c609 100644 --- a/core/lib/Drupal/Core/Config/DrupalConfig.php +++ b/core/lib/Drupal/Core/Config/DrupalConfig.php @@ -86,7 +86,7 @@ class DrupalConfig { * @return * The data that was requested. */ - public function get($key = '') { + public function get($key = '', $subkey = '', $type = 'language') { global $conf; $name = $this->storage->getName(); @@ -103,14 +103,22 @@ class DrupalConfig { else { $parts = explode('.', $key); if (count($parts) == 1) { - return isset($merged_data[$key]) ? $merged_data[$key] : NULL; + $return = isset($merged_data[$key]) ? $merged_data[$key] : NULL; } else { $key_exists = NULL; $value = drupal_array_get_nested_value($merged_data, $parts, $key_exists); - return $key_exists ? $value : NULL; + $return = $key_exists ? $value : NULL; } } + if (is_array($return) && $subkey !== FALSE && isset($return['_default'])) { + $function = 'config_get_' . $type; + if (!function_exists($function)) { + throw new InvalidTypeException('Invalid type "'. $type . '" requested.'); + } + return $function($return, $subkey); + } + return $return; } /** @@ -131,14 +139,29 @@ class DrupalConfig { * @todo * @param $value * @todo + * @param $subkey + * Typically a langcode but can be anything. If the config data is new, + * this will be saved as _default. + * @param $type + * If a $subkey is used for the save, this will define the wrapper + * function called by get() to handle fallback. Defaults to language and + * rarely needs to be changed. */ - public function set($key, $value) { + public function set($key, $value, $subkey = '', $type = 'language') { // Type-cast value into a string. $value = $this->castValue($value); // The dot/period is a reserved character; it may appear between keys, but // not within keys. $parts = explode('.', $key); + if ($subkey) { + $default = $parts; + $default[] = '_default'; + if (!drupal_array_get_nested_value($this->data, $default)) { + drupal_array_set_nested_value($this->data, $default, array($type => $subkey)); + } + $parts[] = $subkey; + } if (count($parts) == 1) { $this->data[$key] = $value; } diff --git a/core/modules/config/config.test b/core/modules/config/config.test index f0e7df0..65fa139 100644 --- a/core/modules/config/config.test +++ b/core/modules/config/config.test @@ -7,6 +7,7 @@ use Drupal\Core\Config\FileStorage; use Drupal\simpletest\WebTestBase; +use Drupal\Core\DependencyInjection\ContainerBuilder; /** * Tests the secure file writer. @@ -387,3 +388,53 @@ class ConfigUpgradeTestCase extends WebTestBase { $this->assertFalse($variables); } } + +/** + * Tests the secure file writer. + */ +class ConfigTranslationTestCase extends WebTestBase { + + public static function getInfo() { + return array( + 'name' => 'Translation', + 'description' => 'Tests translation of configuration.', + 'group' => 'Configuration', + ); + } + function setUp() { + parent::setUp('language'); + + // Set up a new container to ensure we are building a new Language object + // for each test. + drupal_container(new ContainerBuilder()); + } + + function testConfigTranslation() { + $config = config('config.test'); + $config->set('testkey', 'french value', 'fr'); + $config->set('testkey', 'spanish value', 'es'); + $config->set('testkey', 'english value', 'en'); + // Without the language system, the default is english. + $this->assertIdentical($config->get('testkey'), 'english value'); + // This falls back to french because there is no german translation and + // fr was the first translation so it is the default. + $this->assertIdentical($config->get('testkey', 'de'), 'french value'); + // Set the default language to french. + $new_language_default = (object) array( + 'langcode' => 'fr', + 'name' => 'French', + 'direction' => 0, + 'weight' => 0, + 'default' => TRUE, + ); + variable_set('language_default', $new_language_default); + drupal_language_initialize(); + $this->assertIdentical($config->get('testkey'), 'french value'); + // Now verify the whole data. + $all_translations = $config->get('testkey', FALSE); + $this->assertIdentical($all_translations['_default']['language'], 'fr'); + $this->assertIdentical($all_translations['fr'], 'french value'); + $this->assertIdentical($all_translations['es'], 'spanish value'); + $this->assertIdentical($all_translations['en'], 'english value'); + } +}