diff --git a/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php b/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php
index 66e9ecc..252778d 100644
--- a/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php
+++ b/core/modules/locale/lib/Drupal/locale/LocaleConfigManager.php
@@ -11,7 +11,7 @@
use Drupal\Core\Config\StorageInterface;
/**
- * Manages config type plugins.
+ * Manages localized configuration type plugins.
*/
class LocaleConfigManager extends TypedConfigManager {
@@ -44,7 +44,8 @@ class LocaleConfigManager extends TypedConfigManager {
* @param \Drupal\Core\Config\StorageInterface $installStorage
* The storage controller object to use for reading default configuration data.
* @param \Drupal\locale\StringStorageInterface $localeStorage
- * The locale storage to use for reading string translations.
+ * (Optional) The locale storage to use for reading string translations.
+ * Defaults to locale_storage().
*/
public function __construct(StorageInterface $configStorage, StorageInterface $schemaStorage, StorageInterface $installStorage, StringStorageInterface $localeStorage = NULL) {
// Note we use the install storage for the parent constructor.
@@ -59,24 +60,25 @@ public function __construct(StorageInterface $configStorage, StorageInterface $s
* @param string $name
* Configuration object name.
*
- * @return Drupal\locale\LocaleTypedConfig
+ * @return \Drupal\locale\LocaleTypedConfig
* Locale-wrapped configuration element.
*/
public function get($name) {
- // Note we get only the data that didn't change from default.
+ // Read default and current configuration data.
$default = $this->installStorage->read($name);
- // Unless the configuration has a explicit language code we assume English.
- $langcode = isset($default['langcode']) ? $default['langcode'] : 'en';
$updated = $this->configStorage->read($name);
+ // We get only the data that didn't change from default.
$data = $this->compareConfigData($default, $updated);
$definition = $this->getDefinition($name);
+ // Unless the configuration has a explicit language code we assume English.
+ $langcode = isset($default['langcode']) ? $default['langcode'] : 'en';
$wrapper = new LocaleTypedConfig($definition, $name, $langcode, $this);
$wrapper->setValue($data);
return $wrapper;
}
/**
- * Compare default configuration with updated data.
+ * Compares default configuration with updated data.
*
* @param array $default
* Default configuration data.
@@ -106,13 +108,16 @@ protected function compareConfigData($default, $updated) {
}
/**
- * Save translated configuration data.
+ * Saves translated configuration data.
*
* @param string $name
+ * Configuration object name.
* @param string $langcode
+ * Language code.
* @param array $data
+ * Configuration data to be saved, that will be only the translated values.
*/
- public function saveConfigData($name, $langcode, $data) {
+ public function saveTranslationData($name, $langcode, $data) {
$locale_name = 'locale.config.' . $langcode . '.' . $name;
$this->configStorage->write($locale_name, $data);
}
@@ -121,10 +126,11 @@ public function saveConfigData($name, $langcode, $data) {
* Save translated configuration data.
*
* @param string $name
+ * Configuration object name.
* @param string $langcode
- * @param array $data
+ * Language code.
*/
- public function deleteConfigData($name, $langcode) {
+ public function deleteTranslationData($name, $langcode) {
$locale_name = 'locale.config.' . $langcode . '.' . $name;
$this->configStorage->delete($locale_name);
}
@@ -133,7 +139,8 @@ public function deleteConfigData($name, $langcode) {
* Gets configuration names associated with components.
*
* @param array $components
- * Array with string identifiers.
+ * (optional) Array of component lists indexed by type. If not present or it
+ * is an empty array, it will update all components.
*
* @return array
* Array of configuration object names.
@@ -155,19 +162,19 @@ public function getComponentNames($components) {
}
/**
- * Deletes configuration for uninstalled components.
+ * Deletes configuration translations for uninstalled components.
*
* @param array $components
* Array with string identifiers.
* @param array $langcodes
- * Array of language codes
+ * Array of language codes.
*/
- public function deleteComponents($components, $langcodes) {
+ public function deleteComponentTranslations($components, $langcodes) {
$names = $this->getComponentNames($components);
if ($names && $langcodes) {
foreach ($names as $name) {
foreach ($langcodes as $langcode) {
- $this->deleteConfigData($name, $langcode);
+ $this->deleteTranslationData($name, $langcode);
}
}
}
@@ -197,14 +204,13 @@ public function getStringNames($lids) {
* @param $langcode
* Language code to delete.
*/
- public function deleteLanguage($langcode) {
+ public function deleteLanguageTranslations($langcode) {
$locale_name = 'locale.config.' . $langcode;
foreach ($this->configStorage->listAll($locale_name) as $name) {
$this->configStorage->delete($name);
}
}
-
/**
* Translates string using the localization system.
*
@@ -252,6 +258,7 @@ public function translateString($name, $langcode, $source, $context) {
$this->translations[$name][$langcode][$context][$source] = $translation;
}
$translation = $this->translations[$name][$langcode][$context][$source];
+ // Return the string only when the object is an actual translation.
return $translation->isTranslation() ? $translation->getString() : FALSE;
}
return FALSE;
diff --git a/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php b/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php
index 69462b1..5f184a8 100644
--- a/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php
+++ b/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php
@@ -19,13 +19,6 @@
class LocaleTypedConfig extends Element implements TranslatableInterface {
/**
- * The configuration name.
- *
- * @var string
- */
- //protected $name;
-
- /**
* The typed configuration data.
*
* @var \Drupal\Core\Config\Schema\Element
@@ -49,14 +42,14 @@ class LocaleTypedConfig extends Element implements TranslatableInterface {
/**
* Constructs a configuration wrapper object.
*
+ * @param array $definition
+ * The data definition.
* @param string $name
* The configuration object name.
- * @param \Drupal\Core\Config\Schema\Element $typedConfig
- * Typed configuration element.
* @param string $langcode
* Language code for the source configuration data.
* @param \Drupal\locale\LocaleConfigManager $localeConfig;
- * Locale configuration manager that produced this wrapper.
+ * The locale configuration manager object.
*/
public function __construct(array $definition, $name, $langcode, \Drupal\locale\LocaleConfigManager $localeConfig) {
parent::__construct($definition, $name);
@@ -125,17 +118,18 @@ protected function canTranslate($from_langcode, $to_langcode) {
}
/**
- * Get translated configuration data.
+ * Gets translated configuration data for a typed configuration element.
*
* @param \Drupal\Core\Config\Schema\Element $element
* Typed configuration element.
* @param array $options
- * Array with options that will depend on the translator used.
+ * Array with translation options that must contain the keys defined in
+ * LocaleTypedConfig::translateElement()
*
* @return array
* Configuration data translated to the requested language.
*/
- protected function getElementTranslation($element, $options) {
+ protected function getElementTranslation($element, array $options) {
$translation = NULL;
if ($element instanceof ArrayElement) {
$translation = $this->getArrayTranslation($element, $options);
@@ -152,17 +146,18 @@ protected function getElementTranslation($element, $options) {
}
/**
- * Get translated configuration data.
+ * Gets translated configuration data for an element of type ArrayElement.
*
* @param \Traversable $element
* Typed configuration element.
* @param array $options
- * Array with options that will depend on the translator used.
+ * Array with translation options that must contain the keys defined in
+ * LocaleTypedConfig::translateElement()
*
* @return array
* Configuration data translated to the requested language.
*/
- protected function getArrayTranslation($element, $options) {
+ protected function getArrayTranslation(\Traversable $element, array $options) {
$translation = array();
foreach ($element as $key => $property) {
$value = $this->getElementTranslation($property, $options);
@@ -186,12 +181,15 @@ protected function getArrayTranslation($element, $options) {
* @param \Drupal\Core\TypedData\TypedDataInterface $element
* Configuration element.
* @param array $options
- * Array with translation options that are dependent on the translator.
+ * Array with translation options that must contain the following keys:
+ * - 'source', Source language code.
+ * - 'target', Target language code.
+ * - 'strict', True to return only elements that actually have translation.
*
* @return bool
* Whether the element fits the translation criteria.
*/
- protected function translateElement($element, $options) {
+ protected function translateElement(\Drupal\Core\TypedData\TypedDataInterface $element, array $options) {
if ($this->canTranslate($options['source'], $options['target'])) {
$definition = $element->getDefinition();
$value = $element->getValue();
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php
index c42844f..eabdef0 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php
@@ -78,8 +78,6 @@ function testConfigTranslation() {
);
$this->drupalPost('admin/config/regional/translate/translate', $edit, t('Save translations'));
- //$typed_config = config_typed()->get('system.site');
- //$wrapper = new LocaleTypedConfig('system.site', 'en', $typed_config, $this->storage);
$wrapper = locale_config()->get('system.site');
// Get strict translation and check we've got only the site name.
@@ -102,7 +100,7 @@ function testConfigTranslation() {
$string = $this->storage->findString(array('source' => 'Medium (220x220)', 'context' => '', 'type' => 'configuration'));
$this->assertFalse($string, 'Configuration strings have been created upon installation.');
- // Enable the image module
+ // Enable the image module.
$this->drupalPost('admin/modules', array('modules[Core][image][enable]' => "1"), t('Save configuration'));
$this->resetAll();
@@ -110,6 +108,7 @@ function testConfigTranslation() {
$this->assertTrue($string, 'Configuration strings have been created upon installation.');
$locations = $string->getLocations();
$this->assertTrue(isset($locations['configuration']) && isset($locations['configuration']['image.style.medium']), 'Configuration string has been created with the right location');
+
// Check the string is unique and has no translation yet.
$translations = $this->storage->getTranslations(array('language' => $langcode, 'type' => 'configuration', 'name' => 'image.style.medium'));
$translation = reset($translations);
@@ -129,14 +128,13 @@ function testConfigTranslation() {
$lid => $image_style_label,
);
$this->drupalPost('admin/config/regional/translate/translate', $edit, t('Save translations'));
+
// Check the right single translation has been created.
$translations = $this->storage->getTranslations(array('language' => $langcode, 'type' => 'configuration', 'name' => 'image.style.medium'));
$translation = reset($translations);
$this->assertTrue(count($translations) == 1 && $translation->source == $string->source && $translation->translation == $image_style_label, 'Got only one translation for image configuration.');
- // This really should be testing entity_load_multiple.
- //$typed_config = config_typed()->get('image.style.medium');
- //$wrapper = new LocaleTypedConfig('image.style.medium', 'en', $typed_config, $this->storage);
+ // Try more complex configuration data.
$wrapper = locale_config()->get('image.style.medium');
$translation = $wrapper->getTranslation($langcode, TRUE);
$property = $translation->get('label');
diff --git a/core/modules/locale/locale.bulk.inc b/core/modules/locale/locale.bulk.inc
index 0547aa3..0b6f1b2 100644
--- a/core/modules/locale/locale.bulk.inc
+++ b/core/modules/locale/locale.bulk.inc
@@ -285,8 +285,6 @@ function locale_translate_export_form_submit($form, &$form_state) {
* after the import. Optional, defaults to FALSE.
* - 'finish_feedback': Whether or not to give feedback to the user when the
* batch is finished. Optional, defaults to TRUE.
- * - 'components': Array of arrays of components to refresh the configuration
- * indexed by type ('module' or 'theme'). Optional, defaults to none.
*
* @param $force
* (optional) Import all available files, even if they were imported before.
@@ -408,6 +406,7 @@ function locale_translate_batch_build($files, $options) {
}
// Save the translation status of all files.
$operations[] = array('locale_translate_batch_import_save', array());
+
// Add a final step to refresh JavaScript and configuration strings.
$operations[] = array('locale_translate_batch_refresh', array($options));
@@ -569,32 +568,40 @@ function locale_translate_batch_refresh($options, &$context) {
}
}
if ($strings) {
+ // Initialize multi-step string refresh.
$context['message'] = t('Updating translations for JavaScript and Configuration strings.');
- $strings = array_unique($strings);
- // Clear cache and force refresh of JavaScript translations.
- _locale_refresh_translations($langcodes, $strings);
- // Check whether we need to refresh configuration objects.
- if ($options['refresh_configuration'] && $names = locale_config()->getStringNames($strings)) {
- $context['sandbox']['refresh']['names'] = $names;
- $context['sandbox']['refresh']['languages'] = $langcodes;
- $context['sandbox']['refresh']['count'] = count($names);
+ $context['sandbox']['refresh']['strings'] = array_unique($strings);
+ $context['sandbox']['refresh']['languages'] = $langcodes;
+ if (!empty($options['refresh_configuration'])) {
+ $context['sandbox']['refresh']['names'] = array();
$context['results']['stats']['config'] = 0;
}
- }
- if (isset($context['sandbox']['refresh'])) {
- // We will update configuration on next steps.
- $context['finished'] = 1 / $context['sandbox']['refresh']['count'];
+ $context['sandbox']['refresh']['count'] = count($strings);
+
+ // We will update strings on later steps.
+ $context['finished'] = 1 - 1 / $context['sandbox']['refresh']['count'];
}
else {
$context['finished'] = 1;
}
}
- elseif ($name = array_shift($context['sandbox']['refresh']['names'])) {
+ elseif (!empty($options['refresh_configuration']) && $name = array_shift($context['sandbox']['refresh']['names'])) {
// Refresh all languages for one object at a time.
$count = locale_config_update_multiple(array($name), $context['sandbox']['refresh']['languages']);
$context['results']['stats']['config'] += $count;
- // Not perfect but will give some idea of progress.
- $context['finished'] = 1 - count($context['sandbox']['refresh']['names']) / $context['sandbox']['refresh']['count'];
+ }
+ elseif (!empty($context['sandbox']['refresh']['strings'])) {
+ // Not perfect but will give some indication of progress.
+ $context['finished'] = 1 - count($context['sandbox']['refresh']['strings']) / $context['sandbox']['refresh']['count'];
+ // Pending strings, refresh 100 at a time, get next pack.
+ $next = array_slice($context['sandbox']['refresh']['strings'], 0, 100);
+ array_splice($context['sandbox']['refresh']['strings'], 0, count($next));
+ // Clear cache and force refresh of JavaScript translations.
+ _locale_refresh_translations($context['sandbox']['refresh']['languages'], $next);
+ // Check whether we need to refresh configuration objects.
+ if (!empty($options['refresh_configuration']) && $names = locale_config()->getStringNames($next)) {
+ $context['sandbox']['refresh']['names'] = $names;
+ }
}
else {
$context['finished'] = 1;
@@ -607,7 +614,6 @@ function locale_translate_batch_refresh($options, &$context) {
function locale_translate_batch_finished($success, $results) {
if ($success) {
$additions = $updates = $deletes = $skips = $config = 0;
- $strings = $langcodes = array();
if (isset($results['failed_files'])) {
if (module_exists('dblog')) {
$message = format_plural(count($results['failed_files']), 'One translation file could not be imported. See the log for details.', '@count translation files could not be imported. See the log for details.', array('@url' => url('admin/reports/dblog')));
@@ -630,11 +636,7 @@ function locale_translate_batch_finished($success, $results) {
if ($report['skips'] > 0) {
$skipped_files[] = $filepath;
}
- $strings = array_merge($strings, $report['strings']);
}
- // Get list of unique string identifiers and language codes updated.
- $strings = array_unique($strings);
- $langcodes = array_unique(array_values($results['languages']));
}
drupal_set_message(format_plural(count($results['files']),
'One translation file imported. %number translations were added, %update translations were updated and %delete translations were removed.',
@@ -653,17 +655,12 @@ function locale_translate_batch_finished($success, $results) {
drupal_set_message($message, 'warning');
watchdog('locale', '@count disallowed HTML string(s) in files: @files.', array('@count' => $skips, '@files' => implode(',', $skipped_files)), WATCHDOG_WARNING);
}
-
- if ($strings) {
- // Clear cache and force refresh of JavaScript translations.
- _locale_refresh_translations($langcodes);
- // Merge feedback about configuration updates too.
- if (isset($results['stats']['config'])) {
- locale_config_batch_finished($success, $results);
- }
- }
}
}
+ // Add messages for configuration too.
+ if (isset($results['stats']['config'])) {
+ locale_config_batch_finished($success, $results);
+ }
}
/**
@@ -684,7 +681,7 @@ function locale_translate_file_create($filepath) {
}
/**
- * Generate file properties from filename and options.
+ * Generates file properties from filename and options.
*
* An attempt is made to determine the translation language, project name and
* project version from the file name. Supported file name patterns are:
@@ -806,7 +803,7 @@ function locale_config_batch_build($names, $langcodes, $options = array()) {
$batch = array(
'operations' => $operations,
'title' => $t('Updating configuration translations'),
- 'init_message' => $t('Starting update'),
+ 'init_message' => $t('Starting configuration update'),
'error_message' => $t('Error updating configuration translations'),
'file' => drupal_get_path('module', 'locale') . '/locale.bulk.inc',
);
@@ -859,7 +856,7 @@ function locale_config_batch_finished($success, $results) {
}
/**
- * Update all configuration for names / languages.
+ * Updates all configuration for names / languages.
*
* @param array $names
* Array of names of configuration objects to update.
@@ -876,11 +873,11 @@ function locale_config_update_multiple($names, $langcodes = array()) {
foreach ($langcodes as $langcode) {
$translation = $wrapper->getValue() ? $wrapper->getTranslation($langcode, TRUE)->getValue() : NULL;
if ($translation) {
- locale_config()->saveConfigData($name, $langcode, $translation);
+ locale_config()->saveTranslationData($name, $langcode, $translation);
$count++;
}
else {
- locale_config()->deleteConfigData($name, $langcode);
+ locale_config()->deleteTranslationData($name, $langcode);
}
}
}
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 76cd7dc..59ad5cd 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -320,7 +320,7 @@ function locale_language_delete($language) {
locale_translate_delete_translation_files(array(), array($language->langcode));
// Remove translated configuration objects.
- locale_config()->deleteLanguage($language->langcode);
+ locale_config()->deleteLanguageTranslations($language->langcode);
// Changing the language settings impacts the interface:
_locale_invalidate_js($language->langcode);
@@ -564,7 +564,7 @@ function locale_system_remove($components) {
module_load_include('compare.inc', 'locale');
module_load_include('bulk.inc', 'locale');
// Delete configuration translations.
- locale_config()->deleteComponents($components, array_keys($language_list));
+ locale_config()->deleteComponentTranslations($components, array_keys($language_list));
// Only when projects are removed, the translation files and records will be
// deleted. Not each disabled module will remove a project. E.g. sub modules.
@@ -1356,14 +1356,14 @@ function _locale_rebuild_js($langcode = NULL) {
}
/**
- * Returns the locale config manager service.
+ * Returns the locale configuration manager service.
*
* Use the locale config manager service for creating locale-wrapped typed
* configuration objects.
*
* @see Drupal\Core\TypedData\TypedDataManager::create()
*
- * @return Drupal\locale\LocaleConfigManager
+ * @return \Drupal\locale\LocaleConfigManager
*/
function locale_config() {
return drupal_container()->get('locale.config.typed');
diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc
index f571ce5..a109f5f 100644
--- a/core/modules/locale/locale.pages.inc
+++ b/core/modules/locale/locale.pages.inc
@@ -453,6 +453,7 @@ function locale_translate_edit_form_submit($form, &$form_state) {
if ($updated) {
// Clear cache and refresh configuration and JavaScript translations.
+ _locale_refresh_translations(array($langcode), $updated);
_locale_refresh_configuration(array($langcode), $updated);
}