diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 86a45f7..e79ae80 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -709,6 +709,12 @@ function install_tasks($install_state) {
       'type' => 'batch',
       'run' => $needs_translations ? INSTALL_TASK_RUN_IF_NOT_COMPLETED : INSTALL_TASK_SKIP,
     ),
+    'install_update_configuration_translations' => array(
+      'display_name' => st('Translate configuration'),
+      'display' => $needs_translations,
+      'type' => 'batch',
+      'run' => $needs_translations ? INSTALL_TASK_RUN_IF_NOT_COMPLETED : INSTALL_TASK_SKIP,
+    ),
     'install_finished' => array(
       'display_name' => st('Finished'),
     ),
@@ -1782,6 +1788,20 @@ function install_import_translations_remaining(&$install_state) {
 }
 
 /**
+ * Creates configuration translations.
+ *
+ * @param array $install_state
+ *   An array of information about the current installation state.
+ *
+ * @return array
+ *   The batch definition, if there are configuration objects to update.
+ */
+function install_update_configuration_translations(&$install_state) {
+  module_load_include('bulk.inc', 'locale');
+  return locale_config_batch_update_components(array('langcode' => $install_state['parameters']['langcode']));
+}
+
+/**
  * Performs final installation steps and displays a 'finished' page.
  *
  * @param $install_state
diff --git a/core/lib/Drupal/Core/Config/InstallStorage.php b/core/lib/Drupal/Core/Config/InstallStorage.php
index 5a7044b..3ce03b8 100644
--- a/core/lib/Drupal/Core/Config/InstallStorage.php
+++ b/core/lib/Drupal/Core/Config/InstallStorage.php
@@ -15,6 +15,13 @@
 class InstallStorage extends FileStorage {
 
   /**
+   * Folder map indexed by configuration name.
+   *
+   * @var array
+   */
+  protected $folders;
+
+  /**
    * Overrides Drupal\Core\Config\FileStorage::__construct().
    */
   public function __construct() {
@@ -38,17 +45,9 @@ public function __construct() {
    *   afterwards check for a corresponding module or theme.
    */
   public function getFilePath($name) {
-    // Extract the owner.
-    $owner = strtok($name, '.');
-    // Determine the path to the owner.
-    $path = FALSE;
-    foreach (array('profile', 'module', 'theme') as $type) {
-      if ($path = drupal_get_path($type, $owner)) {
-        $file = $path . '/config/' . $name . '.' . static::getFileExtension();
-        if (file_exists($file)) {
-          return $file;
-        }
-      }
+    $folders = $this->getAllFolders();
+    if (isset($folders[$name])) {
+      return $folders[$name] . '/' . $name . '.' . $this->getFileExtension();
     }
     // If any code in the early installer requests a configuration object that
     // does not exist anywhere as default config, then that must be mistake.
@@ -86,11 +85,78 @@ public function rename($name, $new_name) {
 
   /**
    * Implements Drupal\Core\Config\StorageInterface::listAll().
-   *
-   * @throws Drupal\Core\Config\StorageException
    */
   public function listAll($prefix = '') {
-    throw new StorageException('List operation is not allowed during install.');
+    $names = array_keys($this->getAllFolders());
+    if (!$prefix) {
+      return $names;
+    }
+    else {
+      $return = array();
+      foreach ($names as $index => $name) {
+        if (strpos($name, $prefix) === 0 ) {
+          $return[$index] = $names[$index];
+        }
+      }
+      return $return;
+    }
+  }
+
+  /**
+   * Returns a map of all metadata names and the module they belong to.
+   *
+   * @return array
+   *   An array mapping metadata names with directories.
+   */
+  protected function getAllFolders() {
+    if (!isset($this->folders)) {
+      $this->folders = $this->getComponentNames('profile', array(drupal_get_profile()));
+      $this->folders += $this->getComponentNames('module', array_keys(drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.module$/', 'modules', 'name', 0)));
+      $this->folders += $this->getComponentNames('theme', array_keys(drupal_system_listing('/^' . DRUPAL_PHP_FUNCTION_PATTERN . '\.info$/', 'themes')));
+    }
+    return $this->folders;
+  }
+
+  /**
+   * Get all configuration names and folders for a list of modules or themes.
+   *
+   * @param string $type
+   *   Type of components: 'module' or 'theme' or 'profile'.
+   * @param array $list
+   *   Array of theme or module names.
+   *
+   * @return array
+   *   Folders indexed by configuration name.
+   */
+  public function getComponentNames($type, $list) {
+    $extension = '.' . $this->getFileExtension();
+    $folders = array();
+    foreach ($list as $name) {
+      $directory = $this->getComponentFolder($type, $name);
+      if (file_exists($directory)) {
+        $files = glob($directory . '/*' . $extension);
+        foreach ($files as $filename) {
+          $name = basename($filename, $extension);
+          $folders[$name] = $directory;
+        }
+      }
+    }
+    return $folders;
+  }
+
+  /**
+   * Get folder inside each component that contains the files.
+   *
+   * @param string $type
+   *   Component type: 'module' or 'theme' or 'profile'.
+   * @param string $name
+   *   Component name.
+   *
+   * @return string
+   *   The configuration folder name for this component.
+   */
+  protected function getComponentFolder($type, $name) {
+    return drupal_get_path($type, $name) . '/config';
   }
 
   /**
diff --git a/core/lib/Drupal/Core/Config/Schema/Element.php b/core/lib/Drupal/Core/Config/Schema/Element.php
index efe7147..04c544d 100644
--- a/core/lib/Drupal/Core/Config/Schema/Element.php
+++ b/core/lib/Drupal/Core/Config/Schema/Element.php
@@ -22,6 +22,15 @@
   protected $value;
 
   /**
+   * Checks whether this element is translatable.
+   *
+   * @return bool
+   */
+  public function isTranslatable() {
+    return !empty($this->definition['translatable']);
+  }
+
+  /**
    * Create typed config object.
    */
   protected function parseElement($key, $data, $definition) {
diff --git a/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php b/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php
new file mode 100644
index 0000000..73d01df
--- /dev/null
+++ b/core/modules/locale/lib/Drupal/locale/LocaleTypedConfig.php
@@ -0,0 +1,271 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\locale\LocaleTypedConfig.
+ */
+
+namespace Drupal\locale;
+
+use Drupal\Core\Config\Config;
+use Drupal\Core\Language\Language;
+use Drupal\Core\TypedData\TranslatableInterface;
+use Drupal\Core\Config\Schema\Element;
+
+/**
+ * Defines the locale configuration wrapper object.
+ */
+class LocaleTypedConfig extends Config implements TranslatableInterface {
+
+  /**
+   * The language code for which this is a translation.
+   *
+   * @var string
+   */
+  protected $translationLangcode;
+
+  /**
+   * Configuration wrapper used as translation source.
+   *
+   * @var \Drupal\locale\LocaleTypedConfig
+   */
+  protected $translationSource;
+
+  /**
+   * String storage object that will be used for translations.
+   *
+   * @var \Drupal\locale\StringStorageInterface $localeStorage
+   */
+  protected $localeStorage;
+
+  /**
+   * Temporary translations cache.
+   *
+   * @var array
+   */
+  protected $translations;
+
+  /**
+   * Constructs a configuration wrapper object.
+   *
+   * @param string $name
+   *   The configuration object name.
+   * @param array $data
+   *   The configuration data.
+   * @param \Drupal\locale\StringStorageInterface $localeStorage;
+   *   (optional) Locale string storage object that will be used for
+   *   translations.
+   */
+  public function __construct($name, $data, StringStorageInterface $localeStorage = NULL) {
+    $this->name = $name;
+    $this->data = $data;
+    $this->localeStorage = $localeStorage;
+  }
+
+  /**
+   * Sets translation parameters.
+   *
+   * @param string $langcode
+   *   The language code for the translation.
+   * @param \Drupal\locale\LocaleTypedConfig $source
+   *   Configuration wrapper used as translation source.
+   */
+  public function setTranslation($langcode, LocaleTypedConfig $source) {
+    $this->translationLangcode = $langcode;
+    $this->translationSource = $source;
+    return $this;
+  }
+
+  /**
+   * Checks whether we can translate these languages.
+   *
+   * @param string $from_langcode
+   *   Source language code.
+   * @param string $to_langcode
+   *   Destination language code.
+   *
+   * @return boolean
+   *   TRUE if this translator supports translations for these languages.
+   */
+  protected function canTranslate($from_langcode, $to_langcode) {
+    if ($from_langcode == 'en') {
+      return TRUE;
+    }
+    return FALSE;
+  }
+
+  /**
+   * Implements Drupal\Core\TypedData\TranslatableInterface::getTranslationLanguages().
+   */
+  public function getTranslationLanguages($include_default = TRUE) {
+    $languages = locale_translatable_language_list();
+    $default = $this->language();
+    if ($include_default) {
+      $languages[$default->langcode] = $default;
+    }
+    else {
+      unset($languages[$default->langcode]);
+    }
+    return $languages;
+  }
+
+  /**
+   * Implements Drupal\Core\TypedData\TranslatableInterface::getTranslation().
+   */
+  public function getTranslation($langcode, $strict = TRUE) {
+    if (isset($this->translationSource)) {
+      return $this->translationSource->getTranslation($langcode, $strict);
+    }
+    else {
+      $options = array(
+        'source' => $this->language()->langcode,
+        'target' => $langcode,
+        'strict' => $strict,
+      );
+      $data = $this->getTranslatedData($this->get(), $options);
+      $translation = new self($this->name, $data);
+      $translation->setTranslation($langcode, $this);
+      return $translation;
+    }
+  }
+
+  /**
+   * Gets the configuration language.
+   *
+   * @return \Drupal\Core\Language\Language
+   *   The language object.
+   */
+  public function getLanguage() {
+    // The default language will be English as this is hardcoded information.
+    $langcode = isset($this->data['langcode']) ? $this->data['langcode'] : 'en';
+    return new Language(array('langcode' => $langcode));
+  }
+
+  /**
+   * Implements Drupal\Core\TypedData\TranslatableInterface::language().
+   */
+  public function language() {
+    if (isset($this->translationLangcode)) {
+      return new Language(array('langcode' => $this->translationLangcode));
+    }
+    else {
+      return $this->getLanguage();
+    }
+  }
+
+  /**
+   * Get translated configuration data.
+   *
+   * @param \Traversable $elements
+   *   Configuration elements.
+   * @param array $options
+   *   Array with options that will depend on the translator used.
+   *
+   * @return array
+   *   Configuration data translated to the requested language.
+   */
+  protected function getTranslatedData($elements, $options) {
+    $strict = !empty($options['strict']);
+    $translation = array();
+    foreach ($elements as $key => $element) {
+      $value = NULL;
+      if ($element instanceof Element) {
+        $value = $this->getTranslatedData($element, $options);
+      }
+      elseif ($this->translateElement($element, $options)) {
+        $value = $element->getValue();
+      }
+      elseif (!$strict) {
+        $value = $element->getValue();
+      }
+      if ($value || !$strict) {
+        $translation[$key] = $value;
+      }
+    }
+    return $translation;
+  }
+
+  /**
+   * Translates element if it fits our translation criteria.
+   *
+   * For an element to be translatable by locale module it needs to be of type
+   * 'text'. Translatable elements may use these additional keys in their data
+   * definition:
+   * - 'translatable', FALSE to opt out of translation.
+   * - 'locale context', to define the string context.
+   *
+   * @param \Drupal\Core\TypedData\TypedDataInterface $element
+   *   Configuration element.
+   * @param array $options
+   *   Array with translation options that are dependent on the translator.
+   *
+   * @return bool
+   *   Whether the element fits the translation criteria.
+   */
+  public function translateElement($element, $options) {
+    if ($this->canTranslate($options['source'], $options['target'])) {
+      $definition = $element->getDefinition();
+      $value = $element->getValue();
+      if ($value && $element->isTranslatable()) {
+        $context = isset($definition['locale context']) ? $definition['locale context'] : '';
+        if ($translation = $this->translateString($options['target'], $value, $context)) {
+          $element->setValue($translation);
+          return TRUE;
+        }
+      }
+    }
+    // The element doesn't have a translation, if strict mode we drop it.
+    return empty($options['strict']);
+  }
+
+  /**
+   * Translates string using the localization system.
+   *
+   * So far we only know how to translate strings from English so we check
+   * whether the source data is English.
+   * Unlike regular t() translations, strings will be added to the source
+   * tables only if this is marked as default data.
+   *
+   * @param string $langcode
+   *   Language code to translate to.
+   * @param string $source
+   *   The source string.
+   * @param string $context
+   *   The string context.
+   *
+   * @return string|bool
+   *   Translated string if there is a translation, FALSE if not.
+   */
+  protected function translateString($langcode, $source, $context) {
+    if ($source) {
+      // Preload all translations for this configuration name and language.
+      if (!isset($this->translations[$langcode])) {
+        $this->translations[$langcode] = array();
+        foreach ($this->localeStorage->getTranslations(array('language' => $langcode, 'type' => 'configuration', 'name' => $this->name)) as $string){
+          $this->translations[$langcode][$string->context][$string->source] = $string;
+        }
+      }
+      if (!isset($this->translations[$langcode][$context][$source])) {
+        if ($translation = $this->localeStorage->findTranslation(array('source' => $source, 'context' => $context, 'language' => $langcode))) {
+          // The translation was there but the location was missing.
+          // Convert to SourceString because it may not have translation.
+          $string = $this->localeStorage->createString((array) $translation)
+            ->addLocation('configuration', $this->name)
+            ->save();
+        }
+        else {
+          // Add missing source string with the right location.
+          $translation = $this->localeStorage
+            ->createString(array('source' => $source, 'context' => $context))
+            ->addLocation('configuration', $this->name)
+            ->save();
+        }
+        $this->translations[$langcode][$context][$source] = $translation;
+      }
+      $translation = $this->translations[$langcode][$context][$source];
+      return $translation->isTranslation() ? $translation->getString() : FALSE;
+    }
+    return FALSE;
+  }
+
+}
diff --git a/core/modules/locale/lib/Drupal/locale/PoDatabaseWriter.php b/core/modules/locale/lib/Drupal/locale/PoDatabaseWriter.php
index 4c8b254..eb02890 100644
--- a/core/modules/locale/lib/Drupal/locale/PoDatabaseWriter.php
+++ b/core/modules/locale/lib/Drupal/locale/PoDatabaseWriter.php
@@ -102,6 +102,7 @@ function setReport($report = array()) {
       'updates' => 0,
       'deletes' => 0,
       'skips' => 0,
+      'strings' => array(),
     );
     $this->_report = $report;
   }
@@ -258,6 +259,7 @@ private function importString(PoItem $item) {
           $string->save();
           $this->_report['updates']++;
         }
+        $this->_report['strings'][] = $string->getId();
         return $string->lid;
       }
       else {
@@ -272,6 +274,7 @@ private function importString(PoItem $item) {
         ))->save();
 
         $this->_report['additions']++;
+        $this->_report['strings'][] = $string->getId();
         return $string->lid;
       }
     }
@@ -279,6 +282,7 @@ private function importString(PoItem $item) {
       // Empty translation, remove existing if instructed.
       $string->delete();
       $this->_report['deletes']++;
+      $this->_report['strings'][] = $string->lid;
       return $string->lid;
     }
   }
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php
new file mode 100644
index 0000000..7e2d12c
--- /dev/null
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleConfigTranslationTest.php
@@ -0,0 +1,154 @@
+<?php
+
+/**
+ * @file
+ * Contains Drupal\locale\Tests\LocaleConfigTranslationTest.
+ */
+
+namespace Drupal\locale\Tests;
+
+use Drupal\Core\Language\Language;
+use Drupal\simpletest\WebTestBase;
+use Drupal\locale\LocaleTypedConfig;
+
+/**
+ * Tests Metadata for configuration objects.
+ */
+class LocaleConfigTranslationTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('locale');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Configuration translation',
+      'description' => 'Tests translation of configuration strings.',
+      'group' => 'Locale',
+    );
+  }
+
+  function setUp() {
+    parent::setUp();
+    // Add a default locale storage for all these tests.
+    $this->storage = locale_storage();
+  }
+
+  /**
+   * Tests basic configuration translation.
+   */
+  function testConfigTranslation() {
+    // Add custom language
+    $langcode = 'xx';
+    $admin_user = $this->drupalCreateUser(array('administer languages', 'access administration pages', 'translate interface', 'administer modules'));
+    $this->drupalLogin($admin_user);
+    $name = $this->randomName(16);
+    $edit = array(
+      'predefined_langcode' => 'custom',
+      'langcode' => $langcode,
+      'name' => $name,
+      'direction' => '0',
+    );
+    $this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
+    $language = new Language(array('langcode' => $langcode));
+    // Set path prefix.
+    $edit = array( "prefix[$langcode]" => $langcode );
+    $this->drupalPost('admin/config/regional/language/detection/url', $edit, t('Save configuration'));
+
+    // Check site name string exists and create translation for it.
+    $string = $this->storage->findString(array('source' => 'Drupal', 'context' => '', 'type' => 'configuration'));
+    $this->assertTrue($string, 'Configuration strings have been created upon installation.');
+
+    // Translate using the UI so configuration is refreshed.
+    $site_name = $this->randomName(20);
+    $search = array(
+      'string' => $string->source,
+      'langcode' => $langcode,
+      'translation' => 'all',
+    );
+    $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
+    $textareas = $this->xpath('//textarea');
+    $textarea = current($textareas);
+    $lid = (string) $textarea[0]['name'];
+    $edit = array(
+      $lid => $site_name,
+    );
+    $this->drupalPost('admin/config/regional/translate/translate', $edit, t('Save translations'));
+
+    $data = config('system.site')->get();
+    $wrapper = new LocaleTypedConfig('system.site', $data, $this->storage);
+
+    // Get strict translation and check we've got only the site name.
+    $translation = $wrapper->getTranslation($langcode, TRUE);
+    $properties = $translation->get()->getProperties();
+    $this->assertEqual(count($properties), 1, 'Got the right number of properties with strict translation');
+    $this->assertEqual($properties['name']->getValue(), $site_name, 'Got the right translation for site name with strict translation');
+    // Get non strict translation and check we've got all properties.
+    $translation = $wrapper->getTranslation($langcode, FALSE);
+    $properties = $translation->get()->getProperties();
+    $this->assertTrue(count($properties) == 7 && count($wrapper->get('page')) == 3, 'Got the right number of properties with non strict translation');
+    $this->assertEqual($properties['name']->getValue(), $site_name, 'Got the right translation for site name with non strict translation');
+
+    // Check the translated site name is displayed.
+    $this->drupalGet($langcode);
+    $this->assertText($site_name, 'The translated site name is displayed after translations refreshed.');
+
+    // Assert strings from image module config are not available.
+    $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
+    $this->drupalPost('admin/modules', array('modules[Core][image][enable]' => "1"), t('Save configuration'));
+    $this->resetAll();
+
+    $string = $this->storage->findString(array('source' => 'Medium (220x220)', 'context' => '', 'type' => 'configuration'));
+    $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);
+    $this->assertTrue(count($translations) == 1 && $translation->source == $string->source && empty($translation->translation), 'Got only one string for image configuration and has no translation.');
+
+    // Translate using the UI so configuration is refreshed.
+    $image_style_label = $this->randomName(20);
+    $search = array(
+      'string' => $string->source,
+      'langcode' => $langcode,
+      'translation' => 'all',
+    );
+    $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
+    $textarea = current($this->xpath('//textarea'));
+    $lid = (string) $textarea[0]['name'];
+    $edit = array(
+      $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.
+    $data = config('image.style.medium')->get();
+    $wrapper = new LocaleTypedConfig('image.style.medium', $data, $this->storage);
+    $translation = $wrapper->getTranslation($langcode, TRUE);
+    $property = $translation->get('label');
+    $this->assertEqual($property->getValue(), $image_style_label, 'Got the right translation for image style name with strict translation');
+
+    // Quick test to ensure translation file exists.
+    $this->assertEqual(config('locale.config.xx.image.style.medium')->get('label'), $image_style_label);
+
+    // Disable and uninstall the module.
+    $this->drupalPost('admin/modules', array('modules[Core][image][enable]' => FALSE), t('Save configuration'));
+    $this->drupalPost('admin/modules/uninstall', array('uninstall[image]' => "image"), t('Uninstall'));
+    $this->drupalPost(NULL, array(), t('Uninstall'));
+
+    // Ensure that the translated configuration has been removed.
+    $this->assertFalse(config('locale.config.xx.image.style.medium')->get('label'), 'Translated configuration for image module removed.');
+  }
+
+}
diff --git a/core/modules/locale/locale.bulk.inc b/core/modules/locale/locale.bulk.inc
index 5420ac9..9a12153 100644
--- a/core/modules/locale/locale.bulk.inc
+++ b/core/modules/locale/locale.bulk.inc
@@ -6,9 +6,12 @@
  */
 
 use Drupal\Component\Gettext\PoStreamWriter;
+use Drupal\locale\LocaleTypedConfig;
 use Drupal\locale\Gettext;
 use Drupal\locale\PoDatabaseReader;
 use Drupal\Core\Language\Language;
+use Drupal\Core\Config\InstallStorage;
+use Drupal\Core\Config\StorageException;
 
 
 /**
@@ -123,6 +126,7 @@ function locale_translate_import_form_submit($form, &$form_state) {
       'langcode' => $form_state['values']['langcode'],
       'overwrite_options' => $form_state['values']['overwrite_options'],
       'customized' => $form_state['values']['customized'] ? LOCALE_CUSTOMIZED : LOCALE_NOT_CUSTOMIZED,
+      'refresh_configuration' => TRUE,
     );
     $file = locale_translate_file_attach_properties($file, $options);
     $batch = locale_translate_batch_build(array($file->uri => $file), $options);
@@ -278,8 +282,12 @@ function locale_translate_export_form_submit($form, &$form_state) {
  *     are customized translations or come from a community source. Use
  *     LOCALE_CUSTOMIZED or LOCALE_NOT_CUSTOMIZED. Optional, defaults to
  *     LOCALE_NOT_CUSTOMIZED.
+ *   - 'refresh_configuration': Whether or not to refresh configuration strings
+ *     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.
@@ -390,6 +398,7 @@ function locale_translate_batch_build($files, $options) {
     'overwrite_options' => array(),
     'customized' => LOCALE_NOT_CUSTOMIZED,
     'finish_feedback' => TRUE,
+    'refresh_configuration' => FALSE,
   );
   $t = get_t();
   if (count($files)) {
@@ -400,6 +409,8 @@ 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));
 
     $batch = array(
       'operations'    => $operations,
@@ -538,12 +549,66 @@ function locale_translate_batch_import_save($context) {
 }
 
 /**
+ * Refresh translations after importing strings.
+ *
+ * @param array $options
+ *   An array with options that can have the following elements:
+ *   - 'refresh_configuration': Whether or not to refresh configuration strings
+ *     after the import. Optional, defaults to FALSE.
+ *
+ * @param array $context
+ *   Contains a list of strings updated and information about the progress.
+ */
+function locale_translate_batch_refresh($options, &$context) {
+  if (!isset($context['sandbox']['refresh'])) {
+    $strings = $langcodes = array();
+    if (isset($context['results']['stats'])) {
+      // Get list of unique string identifiers and language codes updated.
+      $langcodes = array_unique(array_values($context['results']['languages']));
+      foreach ($context['results']['stats'] as $filepath => $report) {
+        $strings = array_merge($strings, $report['strings']);
+      }
+    }
+    if ($strings) {
+      $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_string_names($strings)) {
+        $context['sandbox']['refresh']['names'] = $names;
+        $context['sandbox']['refresh']['languages'] = $langcodes;
+        $context['sandbox']['refresh']['count'] = count($names);
+        $context['results']['stats']['config'] = 0;
+      }
+    }
+    if (isset($context['sandbox']['refresh'])) {
+      // We will update configuration on next steps.
+      $context['finished'] = 1 / $context['sandbox']['refresh']['count'];
+    }
+    else {
+      $context['finished'] = 1;
+    }
+  }
+  elseif ($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'];
+  }
+  else {
+    $context['finished'] = 1;
+  }
+}
+
+/**
  * Finished callback of system page locale import batch.
  */
 function locale_translate_batch_finished($success, $results) {
   if ($success) {
-    $additions = $updates = $deletes = $skips = 0;
-    $langcodes = array();
+    $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. <a href="@url">See the log</a> for details.', '@count translation files could not be imported. <a href="@url">See the log</a> for details.', array('@url' => url('admin/reports/dblog')));
@@ -566,8 +631,10 @@ function locale_translate_batch_finished($success, $results) {
           if ($report['skips'] > 0) {
             $skipped_files[] = $filepath;
           }
+          $strings = array_merge($strings, $report['strings']);
         }
-        // Get list of unique language codes updated.
+        // 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']),
@@ -588,8 +655,14 @@ function locale_translate_batch_finished($success, $results) {
         watchdog('locale', '@count disallowed HTML string(s) in files: @files.', array('@count' => $skips, '@files' => implode(',', $skipped_files)), WATCHDOG_WARNING);
       }
 
-      // Clear cache and force refresh of JavaScript translations.
-      _locale_refresh_translations($langcodes);
+      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);
+        }
+      }
     }
   }
 }
@@ -686,3 +759,252 @@ function locale_translate_delete_translation_files($projects = array(), $langcod
   }
   return !$fail;
 }
+
+/**
+ * Build a locale batch to refresh configuration.
+ *
+ * @param array $options
+ *   An array with options that can have the following elements:
+ *   - 'finish_feedback': Whether or not to give feedback to the user when the
+ *     batch is finished. Optional, defaults to TRUE.
+ * @param array $langcodes
+ *   Array of language codes. Defaults to all translatable languages.
+ * @param array $components
+ *   (optional) Array of component lists indexed by type. If not present or it
+ *   is an empty array, it will update all components.
+ *
+ * @return array
+ *   The batch definition.
+ */
+function locale_config_batch_update_components($options, $langcodes = array(), $components = array()) {
+  $langcodes = $langcodes ? $langcodes : array_keys(locale_translatable_language_list());
+  if ($langcodes && $names = _locale_config_component_names($components)) {
+    return locale_config_batch_build($names, $langcodes, $options);
+  }
+}
+
+/**
+ * Creates a locale batch to refresh specific configuration.
+ *
+ * @param array $names
+ *   List of configuration object names to update.
+ * @param array $langcodes
+ *   List of language codes to refresh.
+ * @param array $options
+ *   An array with options that can have the following elements:
+ *   - 'finish_feedback': Whether or not to give feedback to the user when the
+ *     batch is finished. Optional, defaults to TRUE.
+ *
+ * @return array
+ *   The batch definition.
+ */
+function locale_config_batch_build($names, $langcodes, $options = array()) {
+  $options += array('finish_feedback' => TRUE);
+  $t = get_t();
+  foreach ($names as $name) {
+    $operations[] = array('locale_config_batch_refresh_name', array($name, $langcodes));
+  }
+  $batch = array(
+      'operations'    => $operations,
+      'title'         => $t('Updating configuration translations'),
+      'init_message'  => $t('Starting update'),
+      'error_message' => $t('Error updating configuration translations'),
+      'file'          => drupal_get_path('module', 'locale') . '/locale.bulk.inc',
+  );
+  if (!empty($options['finish_feedback'])) {
+    $batch['completed'] = 'locale_config_batch_finished';
+  }
+  return $batch;
+}
+
+/**
+ * Perform configuration translation refresh as a batch step.
+ *
+ * @param array $name
+ *   Name of configuration object to update.
+ * @param array $langcodes
+ *   (optional) Array of language codes to update. Defaults to all languages.
+ * @param $context
+ *   Contains a list of files imported.
+ */
+function locale_config_batch_refresh_name($name, $langcodes, &$context) {
+  if (!isset($context['result']['stats']['config'])) {
+    $context['result']['stats']['config'] = 0;
+  }
+  $context['result']['stats']['config'] += locale_config_update_multiple(array($name), $langcodes);
+  $context['result']['names'][] = $name;
+  $context['result']['langcodes'] = $langcodes;
+  $context['finished'] = 1;
+}
+
+/**
+ * Finished callback of system page locale import batch.
+ *
+ * @param bool $success
+ *   Information about the success of the batch import.
+ * @param array $results
+ *   Information about the results of the batch import.
+ */
+function locale_config_batch_finished($success, $results) {
+  if ($success) {
+    $configuration = isset($results['stats']['config']) ? $results['stats']['config'] : 0;
+    if ($configuration) {
+      drupal_set_message(t('The configuration was successfully updated. There are %number configuration objects updated.', array('%number' => $configuration)));
+      watchdog('locale', 'The configuration was successfully updated. %number configuration objects updated.', array('%number' => $configuration));
+    }
+    else {
+      drupal_set_message(t('No configuration objects have been updated.'));
+      watchdog('locale', 'No configuration objects have been updated.', array(), WATCHDOG_WARNING);
+    }
+  }
+}
+
+/**
+ * Delete configuration for language.
+ *
+ * @param $langcode
+ *   Language code to delete.
+ */
+function locale_config_delete_language($langcode) {
+  $locale_name = 'locale.config.' . $langcode;
+  $storage = drupal_container()->get('config.storage');
+  foreach ($storage->listAll($locale_name) as $name) {
+    $storage->delete($name);
+  }
+}
+
+/**
+ * Update all configuration for names / languages.
+ *
+ * @param array $names
+ *   Array of names of configuration objects to update.
+ * @param array $langcodes
+ *   (optional) Array of language codes to update. Defaults to all languages.
+ * @return int
+ *   Number of configuration objects retranslated.
+ */
+function locale_config_update_multiple($names, $langcodes = array()) {
+  $default_storage = new InstallStorage();
+  $config_storage = drupal_container()->get('config.storage');
+  $langcodes = $langcodes ? $langcodes : array_keys(locale_translatable_language_list());
+  $count = 0;
+  foreach ($names as $name) {
+    $wrapper = NULL;
+    try {
+      if ($data = $default_storage->read($name)) {
+        $updated = $config_storage->read($name);
+        if ($data = _locale_config_data_compare($data, $updated)) {
+          $wrapper = new LocaleTypedConfig($name, $data, locale_storage());
+        }
+      }
+      foreach ($langcodes as $langcode) {
+        $locale_name = 'locale.config.' . $langcode . '.' . $name;
+        $translation = $wrapper ? $wrapper->getTranslation($langcode, TRUE)->getData() : NULL;
+        if ($translation) {
+          $config_storage->write($locale_name, $translation);
+          $count++;
+        }
+        else {
+          $config_storage->delete($locale_name);
+        }
+      }
+    }
+    catch (StorageException $e) {
+      // The configuration name does not exist, just continue.
+    }
+  }
+  return $count;
+}
+
+/**
+ * Compare default configuration with updated data.
+ *
+ * @param array $default
+ *   Default configuration data.
+ * @param array $updated
+ *   Current configuration data.
+ *
+ * @return array
+ *   The elements of default configuration that haven't changed.
+ */
+function _locale_config_data_compare($default, $updated) {
+  // Speed up comparison, specially for install operations.
+  if ($default === $updated) {
+    return $default;
+  }
+  $result = array();
+  foreach ($default as $key => $value) {
+    if (isset($updated[$key])) {
+      if (is_array($value)) {
+        $result[$key] = _locale_config_data_compare($value, $updated[$key]);
+      }
+      elseif ($value === $updated[$key]) {
+        $result[$key] = $value;
+      }
+    }
+  }
+  return $result;
+}
+
+/**
+ * Delete configuration for uninstalled components.
+ *
+ * @param array $components
+ *   Array with string identifiers.
+ */
+function locale_config_delete_components($components) {
+  $names = _locale_config_component_names($components);
+  $langcodes = array_keys(locale_translatable_language_list());
+  if ($names && $langcodes) {
+    $storage = drupal_container()->get('config.storage');
+    foreach ($names as $name) {
+      foreach ($langcodes as $langcode) {
+        $storage->delete('locale.config.' . $langcode . '.' . $name);
+      }
+    }
+  }
+}
+
+/**
+ * Get configuration names associated with components.
+ *
+ * @param array $components
+ *   Array with string identifiers.
+ *
+ * @return array
+ *   Array of configuration object names.
+ */
+function _locale_config_component_names($components) {
+  $storage = new InstallStorage();
+  $components = array_filter($components);
+  if ($components) {
+    $names = array();
+    foreach ($components as $type => $list) {
+      // InstallStorage::getComponentNames returns a list of folders keyed by
+      // config name.
+      $names = array_merge($names, array_keys($storage->getComponentNames($type, $list)));
+    }
+    return $names;
+  }
+  else {
+    return $storage->listAll();
+  }
+}
+
+/**
+ * Get configuration names associated with strings.
+ *
+ * @param array $lids
+ *   Array with string identifiers.
+ *
+ * @return array
+ *   Array of configuration object names.
+ */
+function _locale_config_string_names($lids) {
+  $names = array();
+  $locations = locale_storage()->getLocations(array('sid' => $lids, 'type' => 'configuration'));
+  foreach ($locations as $location) {
+    $names[$location->name] = $location->name;
+  }
+  return $names;
+}
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 5ba05d2..942b271 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -322,6 +322,9 @@ function locale_language_delete($language) {
   module_load_include('inc', 'locale', 'locale.bulk');
   locale_translate_delete_translation_files(array(), array($language->langcode));
 
+  // Remove translated configuration objects.
+  locale_config_delete_language($language->langcode);
+
   // Changing the language settings impacts the interface:
   _locale_invalidate_js($language->langcode);
   cache('page')->deleteAll();
@@ -476,14 +479,16 @@ function locale_get_plural($count, $langcode = NULL) {
  * Implements hook_modules_installed().
  */
 function locale_modules_installed($modules) {
-  locale_system_update($modules);
+  $components['module'] = $modules;
+  locale_system_update($components);
 }
 
 /**
  * Implements hook_modules_uninstalled().
  */
 function locale_modules_uninstalled($modules) {
-  locale_system_remove($modules);
+  $components['module'] = $modules;
+  locale_system_remove($components);
 }
 
 /**
@@ -493,14 +498,16 @@ function locale_modules_uninstalled($modules) {
  *   initial installation. The theme system is missing an installation hook.
  */
 function locale_themes_enabled($themes) {
-  locale_system_update($themes);
+  $components['theme'] = $themes;
+  locale_system_update($components);
 }
 
 /**
  * Implements hook_themes_disabled().
  */
 function locale_themes_disabled($themes) {
-  locale_system_remove($themes);
+  $components['theme'] = $themes;
+  locale_system_remove($components);
 }
 
 /**
@@ -509,11 +516,15 @@ function locale_themes_disabled($themes) {
  * This function will start a batch to import translations for the added
  * components.
  *
- * @param array $components
- *   An array of component (theme and/or module) names to import
- *   translations for.
+ * @param $components
+ *   An array of arrays of component (theme and/or module) names to import
+ *   translations for, indexed by type.
  */
 function locale_system_update($components) {
+
+  $components += array('module' => array(), 'theme' => array());
+  $list = array_merge($components['module'], $components['theme']);
+
   // Skip running the translation imports if in the installer,
   // because it would break out of the installer flow. We have
   // built-in support for translation imports in the installer.
@@ -524,11 +535,15 @@ function locale_system_update($components) {
     // Only when new projects are added the update batch will be triggered. Not
     // each enabled module will introduce a new project. E.g. sub modules.
     $projects = array_keys(locale_translation_build_projects());
-    if ($components = array_intersect($components, $projects)) {
+    if ($list = array_intersect($list, $projects)) {
       module_load_include('fetch.inc', 'locale');
       // Get translation status of the projects, download and update translations.
       $options = _locale_translation_default_update_options();
-      $batch = locale_translation_batch_update_build($components, array(), $options);
+      $batch = locale_translation_batch_update_build($list, array(), $options);
+      batch_set($batch);
+    }
+    module_load_include('bulk.inc', 'locale');
+    if ($batch = locale_config_batch_update_components(array(), array(), $components)) {
       batch_set($batch);
     }
   }
@@ -542,33 +557,38 @@ function locale_system_update($components) {
  * modules and we have no record of which string is used by which module.
  *
  * @param array $components
- *   An array of component (theme and/or module) names to remove
- *   translation history.
+ *   An array of arrays of component (theme and/or module) names to import
+ *   translations for, indexed by type.
  */
 function locale_system_remove($components) {
+  $components += array('module' => array(), 'theme' => array());
+  $list = array_merge($components['module'], $components['theme']);
   if (locale_translatable_language_list()) {
     module_load_include('compare.inc', 'locale');
+    module_load_include('bulk.inc', 'locale');
+    // Delete configuration translations.
+    locale_config_delete_components($components);
 
     // 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.
     $projects = array_keys(locale_translation_get_projects());
-    if ($components = array_intersect($components, $projects)) {
-      locale_translation_file_history_delete($components);
+    if ($list = array_intersect($list, $projects)) {
+      locale_translation_file_history_delete($list);
 
       // Remove translation files.
-      module_load_include('inc', 'locale', 'locale.bulk');
-      locale_translate_delete_translation_files($components, array());
+      locale_translate_delete_translation_files($list, array());
 
       // Remove translatable projects.
       // Followup issue http://drupal.org/node/1842362 to replace the
       // {locale_project} table. Then change this to a function call.
       db_delete('locale_project')
-        ->condition('name', $components)
+        ->condition('name', $list)
         ->execute();
 
       // Clear the translation status.
-      locale_translation_status_delete_projects($components);
+      locale_translation_status_delete_projects($list);
     }
+
   }
 }
 
@@ -769,6 +789,12 @@ function locale_form_language_admin_add_form_alter_submit($form, $form_state) {
   $options = _locale_translation_default_update_options();
   $batch = locale_translation_batch_update_build(array(), array($langcode), $options);
   batch_set($batch);
+
+  // Create or update all configuration translations for this language.
+  module_load_include('bulk.inc', 'locale');
+  if ($batch = locale_config_batch_update_components($options, array($langcode))) {
+    batch_set($batch);
+  }
 }
 
 /**
@@ -1044,6 +1070,27 @@ function _locale_refresh_translations($langcodes, $lids = array()) {
 }
 
 /**
+ * Refresh configuration after string translations have been updated.
+ *
+ * The information that will be refreshed includes:
+ * - JavaScript translations.
+ * - Locale cache.
+ *
+ * @param array $langcodes
+ *   Language codes for updated translations.
+ * @param array $lids
+ *   List of string identifiers that have been updated / created.
+ */
+function _locale_refresh_configuration($langcodes, $lids) {
+  if ($lids && $langcodes) {
+    module_load_include('bulk.inc', 'locale');
+    if ($names = _locale_config_string_names($lids)) {
+      locale_config_update_multiple($names, $langcodes);
+    }
+  }
+}
+
+/**
  * Parses a JavaScript file, extracts strings wrapped in Drupal.t() and
  * Drupal.formatPlural() and inserts them into the database.
  *
diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc
index 125af8d..f8e6f92 100644
--- a/core/modules/locale/locale.pages.inc
+++ b/core/modules/locale/locale.pages.inc
@@ -453,8 +453,8 @@ function locale_translate_edit_form_submit($form, &$form_state) {
   }
 
   if ($updated) {
-    // Clear cache and force refresh of JavaScript translations.
-    _locale_refresh_translations(array($langcode), $updated);
+    // Clear cache and refresh configuration and JavaScript translations.
+    _locale_refresh_configuration(array($langcode), $updated);
   }
 
 }
diff --git a/core/modules/system/config/system.schema.yml b/core/modules/system/config/system.schema.yml
index 3514260..a199e5e 100644
--- a/core/modules/system/config/system.schema.yml
+++ b/core/modules/system/config/system.schema.yml
@@ -37,6 +37,7 @@ default:
 label:
   type: string
   label: 'Label'
+  translatable: true
 
 # Internal Drupal path
 path:
@@ -47,6 +48,7 @@ path:
 text:
   type: string
   label: 'Text'
+  translatable: true
 
 # Complex extended data types:
 
