diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index b358269..24d8e84 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -2177,6 +2177,7 @@ function drupal_bootstrap($phase = NULL, $new_phase = TRUE) {
           break;
 
         case DRUPAL_BOOTSTRAP_FULL:
+          config_context_initialize();
           _drupal_bootstrap_full();
           break;
       }
diff --git a/core/includes/config.inc b/core/includes/config.inc
index 8d0eea1..56a235b 100644
--- a/core/includes/config.inc
+++ b/core/includes/config.inc
@@ -2,6 +2,52 @@
 
 use Drupal\Core\Config\DatabaseStorage;
 use Drupal\Core\Config\FileStorage;
+use Drupal\Core\Config\DrupalConfig;
+use Drupal\Core\Config\DrupalConfigContext;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+
+/**
+ * Mark for file name parts that correspond to a configuration realm.
+ */
+const CONFIG_REALM_MARK = '=';
+/**
+ * Name for the default configuration realm.
+ */
+const CONFIG_REALM_DEFAULT = 'default';
+
+/**
+ * Configuration type: Request.
+ *
+ * Use the context for current page request, it will be used for all default
+ * configuration objects created after bootstrap.
+ */
+const CONFIG_TYPE_BOOTSTRAP = 'bootstrap';
+
+/**
+ * Configuration type: Request.
+ *
+ * Use the context for current page request, it will be used for all default
+ * configuration objects created after bootstrap.
+ */
+const CONFIG_TYPE_REQUEST = 'request';
+
+/**
+ * Configuration type: Administration
+ *
+ * For administering the configuration (settings forms), this should be independent
+ * from current page request.
+ */
+const CONFIG_TYPE_ADMIN = 'admin';
+
+/**
+ * Configuration type: Custom context.
+ *
+ * This is a configuration object that uses a custom context, which means it may be specific
+ * for an object / module, so these objects are not statically cached, and it is not
+ * depending on page request.
+ */
+const CONFIG_TYPE_CUSTOM = 'custom';
+
 
 /**
  * @file
@@ -28,6 +74,16 @@ function config_get_config_directory() {
 }
 
 /**
+ * Gets information about configuration.
+ *
+ * @param $name
+ *   Configuration name.
+ */
+function config_info($name) {
+  return array();
+}
+
+/**
  * Installs the default configuration of a given module.
  *
  * @param
@@ -39,6 +95,7 @@ function config_get_config_directory() {
 function config_install_default_config($module) {
   $module_config_dir = drupal_get_path('module', $module) . '/config';
   $drupal_config_dir = config_get_config_directory();
+  $installed = array();
   if (is_dir(drupal_get_path('module', $module) . '/config')) {
     $files = glob($module_config_dir . '/*.' . FileStorage::getFileExtension());
     foreach ($files as $key => $file) {
@@ -46,13 +103,25 @@ function config_install_default_config($module) {
       // file system in the drupal config directory. Note the config name
       // needs to be the same as the file name WITHOUT the extension.
       $config_name = basename($file, '.' . FileStorage::getFileExtension());
-
-      $database_storage = new DatabaseStorage($config_name);
-      $file_storage = new FileStorage($config_name);
+      // Check for existing realm name in the file name
+      $parts = explode('.', $config_name);
+      $last = array_pop($parts);
+      if (strpos($last, CONFIG_REALM_MARK)) {
+        $realm_name = $last;
+        $config_name = implode('.', $parts);
+      }
+      else {
+        $realm_name = CONFIG_REALM_DEFAULT;
+      }
+      $database_storage = config_storage($config_name, $realm_name);
+      $file_storage = new FileStorage($config_name, $realm_name);
       $file_storage->setPath($module_config_dir);
-      $database_storage->write($file_storage->read());
+      $data = $file_storage->read();
+      $database_storage->write($data);
+      $installed[$config_name][$realm_name] = $data;
     }
   }
+  module_invoke_all('config_install_default_config', $module, $installed);
 }
 
 /**
@@ -63,7 +132,7 @@ function config_get_storage_names_with_prefix($prefix = '') {
 }
 
 /**
- * Retrieves a configuration object.
+ * Retrieves a configuration object for the Current Context.
  *
  * This is the main entry point to the configuration API. Calling
  * @code config(book.admin) @endcode will return a configuration object in which
@@ -82,7 +151,181 @@ function config_get_storage_names_with_prefix($prefix = '') {
  *
  * @todo Replace this with an appropriate factory / ability to inject in
  *   alternate storage engines..
+ *
  */
 function config($name, $class = 'Drupal\Core\Config\DrupalConfig') {
-  return new $class(new DatabaseStorage($name));
+  return config_set_current_context()->getConfig($name, $class);
+}
+
+/**
+ * Retrieve custom configuration context.
+ */
+function config_context($data = array(), $type = CONFIG_TYPE_CUSTOM, $class = 'Drupal\Core\Config\DrupalConfigContext') {
+  $context = new $class($type, $data);
+  return $context->build();
+}
+
+/**
+ * Retrieves a configuration object for administration.
+ *
+ * Plug-ins should not override values of this type (admin) because this is used
+ * mainly for editing the configuration.
+ */
+function config_admin($name, $class = 'Drupal\Core\Config\DrupalConfig') {
+  return config_static_context(CONFIG_TYPE_ADMIN)->getConfig($name, $class);
+}
+
+/**
+ * Get / create configuration storage.
+ */
+function config_storage($name, $realm = CONFIG_REALM_DEFAULT, $class = 'Drupal\Core\Config\DatabaseStorage') {
+  $store = &drupal_static(__FUNCTION__);
+  if (!isset($store[$name][$realm][$class])) {
+    $store[$name][$realm][$class] = new $class($name, $realm);
+  }
+  return $store[$name][$realm][$class];
+}
+
+/**
+ * Retrieves a static configuration context object.
+ *
+ * The first time each context type is created, we'll invoke hook_config_context and
+ * then cache the values for subsequent calls.
+ *
+ * @see _config_default_plugins()
+ *
+ * @param $type
+ *   Configuration type.
+ */
+function config_static_context($type) {
+  try {
+    return drupal_container()->get('config.context.' . $type);
+  }
+  catch (InvalidArgumentException $e) {
+    $context = config_context(array(), $type);
+    drupal_container()->set('config.context.' . $type, $context);
+    return $context;
+  }
+}
+
+/**
+ * Initialize request context after bootstrap.
+ */
+function config_context_initialize() {
+  config_set_current_context(config_static_context(CONFIG_TYPE_REQUEST));
+}
+
+/**
+ * Get / set current configuration context.
+ */
+function config_set_current_context($context = NULL) {
+  static $current;
+
+  if ($context) {
+    $current = $context;
+  }
+  elseif (!isset($current)) {
+    // First time it is called without arguments we initialize the context system
+    $current = config_static_context(CONFIG_TYPE_BOOTSTRAP);
+  }
+
+  return $current;
+}
+
+/**
+ * Reset current configuration context to request.
+ */
+function config_context_reset() {
+  return config_set_current_context(config_static_context(CONFIG_TYPE_REQUEST));
+}
+
+/**
+ * Sort plug-ins by weight.
+ */
+function _drupal_config_sort_weight($a, $b) {
+  return $a->getWeight() - $b->getWeight();
+}
+
+/**
+ * Get configuration data from array.
+ */
+function config_array_get(&$array, $key = '') {
+  if (!$key) {
+    return $array;
+  }
+  else {
+    $parts = explode('.', $key);
+    if (count($parts) == 1) {
+      return isset($array[$key]) ? $array[$key] : NULL;
+    }
+    else {
+      $key_exists = NULL;
+      $value = drupal_array_get_nested_value($array, $parts, $key_exists);
+      return $key_exists ? $value : NULL;
+    }
+  }
+}
+
+/**
+ * Merge configuration data in array.
+ */
+function config_array_set(&$array, $key, $value) {
+  if (!$key) {
+    $array = $value;
+  }
+  else {
+    $parts = explode('.', $key);
+    if (count($parts) == 1) {
+      $array[$key] = $value;
+    }
+    else {
+      drupal_array_set_nested_value($array, $parts, $value);
+    }
+  }
+}
+
+/**
+ * Unset array element.
+ */
+function config_array_unset(&$array, $key) {
+  if (!$key) {
+    $array = array();
+  }
+  else {
+    $parts = explode('.', $key);
+    if (count($parts) == 1) {
+      unset($array[$key]);
+    }
+    else {
+      drupal_array_unset_nested_value($array, $parts);
+    }
+  }
+}
+
+/**
+ * Get container of configuration plug-ins.
+ */
+function config_plugin_container() {
+  try {
+    return drupal_container()->get('config.plugin');
+  }
+  catch (InvalidArgumentException $e) {
+    drupal_container()->register('config.plugin', 'Symfony\Component\DependencyInjection\ContainerBuilder');
+    return drupal_container()->get('config.plugin');
+  }
+}
+
+/**
+ * Get list of configuration plug-ins.
+ */
+function config_plugin_list() {
+  $plugins = array();
+  $container = config_plugin_container();
+  foreach ($container->getServiceIds() as $id) {
+    // This service is added by the container itself (?)
+    if ($id == 'service_container') continue;
+    $plugins[$id] = $container->get($id);
+  }
+  uasort($plugins, '_drupal_config_sort_weight');
+  return $plugins;
 }
diff --git a/core/lib/Drupal/Core/Config/ConfigContextInterface.php b/core/lib/Drupal/Core/Config/ConfigContextInterface.php
new file mode 100644
index 0000000..922eb88
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/ConfigContextInterface.php
@@ -0,0 +1,47 @@
+<?php
+namespace Drupal\Core\Config;
+
+/**
+ * Represents a configuration context object.
+ *
+ * A configuration context keeps the data needed to create new configuration
+ * objects for the same context. There are two types of contexts:
+ * - Global / Static, it is the same object always for the same configuration
+ * type, it can be created and retrieved by using config_static_context()
+ * - Custom. To be used by pieces of code that get configuration with specific
+ * parameters (user, language, etc...). It is created every time we invoke
+ * config_context() and is not statically cached.
+ *
+ * This is just a way of encapsulating the data and pass it around without
+ * using too many references everywhere.
+ */
+interface ConfigContextInterface {
+  /**
+   * Class constructor.
+   */
+  public function __construct($type, $data = array());
+  /**
+   * Build invoking current config plug-ins.
+   */
+  public function build();
+  /**
+   * Get context type.
+   */
+  public function getType();
+  /**
+   * Get context data.
+   */
+  public function get($key);
+  /**
+   * Set context data.
+   */
+  public function set($key, $value);
+  /**
+   * Check whether some context data is set.
+   */
+  public function hasData($key);
+  /**
+   * Get configuration object with this context.
+   */
+  public function getConfig($name, $class = 'Drupal\Core\Config\DrupalConfig');
+}
diff --git a/core/lib/Drupal/Core/Config/ConfigGlobalPlugin.php b/core/lib/Drupal/Core/Config/ConfigGlobalPlugin.php
new file mode 100644
index 0000000..db2a5b7
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/ConfigGlobalPlugin.php
@@ -0,0 +1,36 @@
+<?php
+/**
+ * @file
+ * Configuration plug-in
+ *
+ * Allows overriding the configuration with global $conf values.
+ *
+ */
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\DrupalConfigPlugin;
+
+class ConfigGlobalPlugin extends DrupalConfigPlugin {
+  /**
+   * Plug-in name.
+   */
+  protected $name = 'global';
+  /**
+   * Implements ConfigPluginInterface::getTitle()
+   */
+  public function getTitle() {
+    return t('Global');
+  }
+
+  /**
+   * Implements ConfigPluginInterface::read()
+   */
+  public function read($config) {
+    global $conf;
+
+    $name = $config->getStorage()->getName();
+    if (isset($conf[$name])) {
+      $config->setOverride($conf[$name]);
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/ConfigPluginInterface.php b/core/lib/Drupal/Core/Config/ConfigPluginInterface.php
new file mode 100644
index 0000000..85d5889
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/ConfigPluginInterface.php
@@ -0,0 +1,49 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\DatabaseStorage;
+use Drupal\Core\Config\FileStorage;
+
+interface ConfigPluginInterface {
+  /**
+   * Build context object.
+   */
+  public function context($context);
+  /**
+   * Build current configuration.
+   */
+  public function build($config, &$data);
+  /**
+   * Delete configuration.
+   */
+  public function delete($config);
+  /**
+   * Read from store.
+   */
+  public function read($config);
+  /**
+   * Save to store.
+   */
+  public function save($config);
+  /**
+   * Get plug-in human readable title.
+   */
+  public function getTitle();
+  /**
+   * Get plug-in machine name.
+   */
+  public function getName();
+  /**
+   * Set plug-in machine name.
+   */
+  public function setName($name);
+  /**
+   * Get plug-in weight.
+   */
+  public function getWeight();
+  /**
+   * Set plug-in weight.
+   */
+  public function setWeight($weight = 0);
+}
diff --git a/core/lib/Drupal/Core/Config/ConfigWatchdogPlugin.php b/core/lib/Drupal/Core/Config/ConfigWatchdogPlugin.php
new file mode 100644
index 0000000..8dd3df6
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/ConfigWatchdogPlugin.php
@@ -0,0 +1,46 @@
+<?php
+/**
+ * @file
+ * Configuration plug-in
+ *
+ * Allows tracking configuration changes in the watchdog.
+ *
+ */
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\DrupalConfigPlugin;
+
+class ConfigWatchdogPlugin extends DrupalConfigPlugin {
+  /**
+   * Plug-in name.
+   */
+  protected $name = 'watchdog';
+  /**
+   * Implements ConfigPluginInterface::getTitle()
+   */
+  public function getTitle() {
+    return t('Watchdog');
+  }
+
+  /**
+   * Implements ConfigPluginInterface::read()
+   */
+  public function read($config) {
+    $name = $config->getStorage()->getName();
+    watchdog('config', 'Read !name configuration', array('!name' => $name));
+  }
+  /**
+   * Implements ConfigPluginInterface::delete()
+   */
+  public function delete($config) {
+    $name = $config->getStorage()->getName();
+    watchdog('config', 'Deleted !name configuration', array('!name' => $name));
+  }
+  /**
+   * Implements ConfigPluginInterface::save()
+   */
+  public function save($config) {
+    $name = $config->getStorage()->getName();
+    watchdog('config', 'Saved !name configuration', array('!name' => $name));
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/DatabaseStorage.php b/core/lib/Drupal/Core/Config/DatabaseStorage.php
index c736245..55f8caf 100644
--- a/core/lib/Drupal/Core/Config/DatabaseStorage.php
+++ b/core/lib/Drupal/Core/Config/DatabaseStorage.php
@@ -14,29 +14,35 @@ class DatabaseStorage extends StorageBase {
    * Implements StorageInterface::read().
    */
   public function read() {
-    // There are situations, like in the installer, where we may attempt a
-    // read without actually having the database available. In this case,
-    // catch the exception and just return an empty array so the caller can
-    // handle it if need be.
-    $data = array();
-    try {
-      $raw = db_query('SELECT data FROM {config} WHERE name = :name', array(':name' => $this->name))->fetchField();
-      if ($raw !== FALSE) {
-        $data = $this->decode($raw);
+    if (!isset($this->data)) {
+      // There are situations, like in the installer, where we may attempt a
+      // read without actually having the database available. In this case,
+      // catch the exception and just return an empty array so the caller can
+      // handle it if need be.
+      $data = array();
+      try {
+        $raw = db_query('SELECT data FROM {config} WHERE realm = :realm AND name = :name', array(':realm' => $this->realm, ':name' => $this->name))->fetchField();
+        if ($raw !== FALSE) {
+          $this->data = $this->decode($raw);
+        }
+        else {
+          $this->data = array();
+        }
+      }
+      catch (Exception $e) {
       }
     }
-    catch (Exception $e) {
-    }
-    return $data;
+    return $this->data;
   }
 
   /**
    * Implements StorageInterface::writeToActive().
    */
   public function writeToActive($data) {
+    $this->data = $data;
     $data = $this->encode($data);
     return db_merge('config')
-      ->key(array('name' => $this->name))
+      ->key(array('name' => $this->name, 'realm' => $this->realm))
       ->fields(array('data' => $data))
       ->execute();
   }
@@ -45,6 +51,7 @@ class DatabaseStorage extends StorageBase {
    * @todo
    */
   public function deleteFromActive() {
+    $this->data = array();
     db_delete('config')
       ->condition('name', $this->name)
       ->execute();
@@ -67,7 +74,7 @@ class DatabaseStorage extends StorageBase {
   /**
    * Implements StorageInterface::getNamesWithPrefix().
    */
-  static public function getNamesWithPrefix($prefix = '') {
-    return db_query('SELECT name FROM {config} WHERE name LIKE :name', array(':name' => db_like($prefix) . '%'))->fetchCol();
+  static public function getNamesWithPrefix($prefix = '', $realm = '') {
+    return db_query('SELECT name FROM {config} WHERE realm = :realm AND name LIKE :name', array(':realm' => $realm, ':name' => db_like($prefix) . '%'))->fetchCol();
   }
 }
diff --git a/core/lib/Drupal/Core/Config/DrupalConfig.php b/core/lib/Drupal/Core/Config/DrupalConfig.php
index f5a9220..40ba5c5 100644
--- a/core/lib/Drupal/Core/Config/DrupalConfig.php
+++ b/core/lib/Drupal/Core/Config/DrupalConfig.php
@@ -9,7 +9,6 @@ use Drupal\Core\Config\ConfigException;
  * Represents the default configuration storage object.
  */
 class DrupalConfig {
-
   /**
    * The storage engine to save this config object to.
    *
@@ -22,27 +21,124 @@ class DrupalConfig {
    *
    * @var array
    */
-  protected $data = array();
+  protected $data;
+
+  /**
+   * Temporary overrides for the configuration object.
+   *
+   * @var array
+   */
+  protected $override = array();
+
+  /**
+   * The current data of the configuration object ($data + $override).
+   *
+   * @var array
+   */
+  protected $current;
+
+  /**
+   * Context for this configuration.
+   */
+  protected $context;
 
   /**
    * Constructs a DrupalConfig object.
    *
    * @param StorageInterface $storage
    *   The storage engine where this config object should be saved.
+   * @param ConfigContext $context
+   *   Configuration context.
    *
    * @todo $this should really know about $name and make it publicly accessible.
    */
-  public function __construct(StorageInterface $storage) {
+  public function __construct(StorageInterface $storage, ConfigContextInterface $context) {
+    $this->context = $context;
     $this->storage = $storage;
     $this->read();
   }
+  /**
+   * Build current configuration with stored data + overrides.
+   */
+  public function build() {
+    $data = $this->data;
+    if (!empty($this->override)) {
+      $data = drupal_array_merge_deep($data, $this->override);
+    }
+    $this->invokePlugins('build', $data);
+    return $data;
+  }
+  /**
+   * Get configuration name.
+   */
+  public function getName() {
+    return $this->storage->getName();
+  }
+  /**
+   * Get storage object.
+   */
+  public function getStorage() {
+    return $this->storage;
+  }
+  /**
+   * Get current config context.
+   */
+  public function getContext() {
+    return $this->context;
+  }
+  /**
+   * Rebuild current configuration (mark to be rebuilt)
+   */
+  public function rebuild() {
+    unset($this->current);
+  }
 
   /**
+   * Replaces the data of this configuration object.
+   *
+   * @param array $data
+   *   The new configuration data.
+   */
+  public function setData(array $data, $key = '') {
+    config_array_set($this->data, $key, $data);
+    $this->rebuild();
+    return $this;
+  }
+
+  /**
+   * Overrides the data of this configuration object.
+   *
+   * @param array $data
+   *   The new configuration data.
+   */
+  public function setOverride(array $data, $key = '') {
+    config_array_set($this->override, $key, $data);
+    return $this;
+  }
+
+  /**
+   * Gets configuration data.
+   */
+  public function &getData() {
+    if (!isset($this->data)) {
+      $this->read();
+    }
+    return $this->data;
+  }
+
+  /**
+   * Set storage object.
+   */
+  public function setStorage(StorageInterface $storage) {
+    $this->storage = $storage;
+  }
+  /**
    * Reads config data from the active store into our object.
    */
   public function read() {
     $data = $this->storage->read();
-    $this->setData($data !== FALSE ? $data : array());
+    $this->data = $data !== FALSE ? $data : array();
+    $this->invokePlugins('read');
     return $this;
   }
 
@@ -60,7 +156,7 @@ class DrupalConfig {
   }
 
   /**
-   * Gets data from this config object.
+   * Gets run-time data from this config object.
    *
    * @param $key
    *   A string that maps to a key within the configuration data.
@@ -87,45 +183,15 @@ class DrupalConfig {
    *   The data that was requested.
    */
   public function get($key = '') {
-    global $conf;
-
-    $name = $this->storage->getName();
-    if (isset($conf[$name])) {
-      $merged_data = drupal_array_merge_deep($this->data, $conf[$name]);
-    }
-    else {
-      $merged_data = $this->data;
-    }
-
-    if (empty($key)) {
-      return $merged_data;
-    }
-    else {
-      $parts = explode('.', $key);
-      if (count($parts) == 1) {
-        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;
-      }
+    if (!isset($this->current)) {
+      $this->current = $this->build();
     }
+    // Set current value that may be overridden by plug-ins.
+    return config_array_get($this->current, $key);
   }
 
   /**
-   * Replaces the data of this configuration object.
-   *
-   * @param array $data
-   *   The new configuration data.
-   */
-  public function setData(array $data) {
-    $this->data = $data;
-    return $this;
-  }
-
-  /**
-   * Sets value in this config object.
+   * Sets value in this config object base.
    *
    * @param $key
    *   @todo
@@ -135,19 +201,10 @@ class DrupalConfig {
   public function set($key, $value) {
     // 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 (count($parts) == 1) {
-      $this->data[$key] = $value;
-    }
-    else {
-      drupal_array_set_nested_value($this->data, $parts, $value);
-    }
+    $old_value = config_array_get($this->data, $key);
+    config_array_set($this->data, $key, $value);
     return $this;
   }
-
   /**
    * Casts a saved value to a string.
    *
@@ -194,20 +251,18 @@ class DrupalConfig {
    *   Name of the key whose value should be unset.
    */
   public function clear($key) {
-    $parts = explode('.', $key);
-    if (count($parts) == 1) {
-      unset($this->data[$key]);
-    }
-    else {
-      drupal_array_unset_nested_value($this->data, $parts);
-    }
+    $old_value = config_array_get($this->data, $key);
+    config_array_unset($this->data, $key);
+    $this->rebuild();
   }
 
   /**
    * Saves the configuration object.
    */
   public function save() {
-    $this->storage->write($this->data);
+    $data = $this->data;
+    $this->invokePlugins('save', $data);
+    $this->storage->write($data);
   }
 
   /**
@@ -216,5 +271,20 @@ class DrupalConfig {
   public function delete() {
     $this->data = array();
     $this->storage->delete();
+    $this->rebuild();
+    $this->invokePlugins('delete');
+  }
+
+  /**
+   * Invoke method on all current configuration plug-ins.
+   *
+   * @return
+   *   Boolean that is true if the operation has been completed.
+   */
+  protected function invokePlugins($method, &$var1  = NULL, &$var2  = NULL, &$var3 = NULL, &$var4 = NULL) {
+    foreach (config_plugin_list() as $plugin) {
+      $plugin->$method($this, $var1, $var2, $var3, $var4);
+    }
   }
 }
+
diff --git a/core/lib/Drupal/Core/Config/DrupalConfigContext.php b/core/lib/Drupal/Core/Config/DrupalConfigContext.php
new file mode 100644
index 0000000..05c1908
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/DrupalConfigContext.php
@@ -0,0 +1,73 @@
+<?php
+namespace Drupal\Core\Config;
+
+/**
+ * Represents a configuration context object.
+ */
+class DrupalConfigContext implements ConfigContextInterface {
+  /**
+   * Configuration type.
+   */
+  protected $type;
+  /**
+   * Context data, array of objects indexed by type.
+   */
+  protected $data;
+  /**
+   * Store other configuration objects with this context.
+   *
+   * These will be indexed by name and class.
+   */
+  protected $config = array();
+  /**
+   * Class constructor.
+   */
+  public function __construct($type, $data = array()) {
+    $this->type = $type;
+    $this->data = $data;
+  }
+  /**
+   * Build invoking current config plug-ins.
+   */
+  public function build() {
+    foreach (config_plugin_list() as $plugin) {
+      $plugin->context($this);
+    }
+    return $this;
+  }
+  /**
+   * Get context type.
+   */
+  public function getType() {
+    return $this->type;
+  }
+  /**
+   * Get context data.
+   */
+  public function get($key) {
+    return isset($this->data[$key]) ? $this->data[$key] : NULL;
+  }
+  /**
+   * Set context data.
+   */
+  public function set($key, $value) {
+    $this->data[$key] = $value;
+    return $this;
+  }
+  /**
+   * Check whether some context data is set.
+   */
+  public function hasData($key) {
+    return isset($this->data[$key]);
+  }
+  /**
+   * Get configuration object with this context.
+   */
+  public function getConfig($name, $class = 'Drupal\Core\Config\DrupalConfig') {
+    if (!isset($this->config[$name][$class])) {
+      $storage = config_storage($name);
+      $this->config[$name][$class] = new $class($storage, $this);
+    }
+    return $this->config[$name][$class];
+  }
+}
diff --git a/core/lib/Drupal/Core/Config/DrupalConfigPlugin.php b/core/lib/Drupal/Core/Config/DrupalConfigPlugin.php
new file mode 100644
index 0000000..a6bb3b7
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/DrupalConfigPlugin.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\ConfigPluginInterface;
+
+/**
+ * Basic implementation of ConfigPluginInterface
+ */
+abstract class DrupalConfigPlugin implements ConfigPluginInterface {
+  /**
+   * Plugin name.
+   */
+  protected $name = 'default';
+
+  /**
+   * Plugin-weight.
+   */
+  protected $weight = 0;
+
+  /**
+   * Implements ConfigPluginInterface::context()
+   */
+  public function context($context) {
+  }
+  /**
+   * Implements ConfigPluginInterface::read()
+   */
+  public function read($config) {
+  }
+  /**
+   * Implements ConfigPluginInterface::save()
+   */
+  public function save($config) {
+  }
+  /**
+   * Implements ConfigPluginInterface::build()
+   */
+  public function build($config, &$data) {
+  }
+
+  /**
+   * Implements ConfigPluginInterface::delete()
+   */
+  public function delete($config) {
+  }
+
+  /**
+   * Implements ConfigPluginInterface::getWeigt()
+   */
+  public function getWeight() {
+    return $this->weight;
+  }
+  public function setWeight($weight = 0) {
+    $this->weight = $weight;
+  }
+  /**
+   * Implements ConfigPluginInterface::getName()
+   */
+  public function getName() {
+    return $this->name;
+  }
+  /**
+   * Implements ConfigPluginInterface::setName()
+   */
+  public function setName($name) {
+    $this->name = $name;
+  }
+}
+
diff --git a/core/lib/Drupal/Core/Config/FileStorage.php b/core/lib/Drupal/Core/Config/FileStorage.php
index 2a6d448..66ef284 100644
--- a/core/lib/Drupal/Core/Config/FileStorage.php
+++ b/core/lib/Drupal/Core/Config/FileStorage.php
@@ -29,8 +29,9 @@ class FileStorage {
   /**
    * Implements StorageInterface::__construct().
    */
-  public function __construct($name = NULL) {
+  public function __construct($name = NULL, $realm = CONFIG_REALM_DEFAULT) {
     $this->name = $name;
+    $this->realm = $realm;
   }
 
   /**
@@ -63,7 +64,8 @@ class FileStorage {
    *   The path to the configuration file.
    */
   public function getFilePath() {
-    return $this->getPath() . '/' . $this->getName() . '.' . self::getFileExtension();
+    $realm_suffix = $this->realm == CONFIG_REALM_DEFAULT ? '' : '.' . $this->realm;
+    return $this->getPath() . '/' . $this->getName() . $realm_suffix . '.' . self::getFileExtension();
   }
 
   /**
@@ -92,6 +94,7 @@ class FileStorage {
    * @throws FileStorageException
    */
   public function write($data) {
+    $this->data = $data;
     $data = $this->encode($data);
     if (!file_put_contents($this->getFilePath(), $data)) {
       throw new FileStorageException('Failed to write configuration file: ' . $this->getFilePath());
@@ -104,6 +107,9 @@ class FileStorage {
    * @throws FileStorageReadException
    */
   public function read() {
+    if (isset($this->data)) {
+      return $this->data;
+    }
     if (!$this->exists()) {
       throw new FileStorageReadException("Configuration file '$this->name' does not exist.");
     }
@@ -113,6 +119,9 @@ class FileStorage {
     if ($data === FALSE) {
       throw new FileStorageReadException("Failed to decode configuration file '$this->name'.");
     }
+
+    $this->data = $data;
+
     return $data;
   }
 
@@ -160,7 +169,7 @@ class FileStorage {
   /**
    * Implements StorageInterface::getNamesWithPrefix().
    */
-  public static function getNamesWithPrefix($prefix = '') {
+  public static function getNamesWithPrefix($prefix = '', $realm = '') {
     // @todo Use $this->getPath() to allow for contextual search of files in
     //   custom paths.
     $files = glob(config_get_config_directory() . '/' . $prefix . '*.' . FileStorage::getFileExtension());
diff --git a/core/lib/Drupal/Core/Config/LocaleConfigPlugin.php b/core/lib/Drupal/Core/Config/LocaleConfigPlugin.php
new file mode 100644
index 0000000..a2d55ac
--- /dev/null
+++ b/core/lib/Drupal/Core/Config/LocaleConfigPlugin.php
@@ -0,0 +1,145 @@
+<?php
+
+namespace Drupal\Core\Config;
+
+use Drupal\Core\Config\DatabaseStorage;
+use Drupal\Core\Config\FileStorage;
+use Drupal\Core\Config\DrupalConfigPlugin;
+
+
+/**
+ * Locale Config plug-in.
+ *
+ * $config is always a DrupalConfig object.
+ */
+class LocaleConfigPlugin extends DrupalConfigPlugin {
+  /**
+   * Plug-in name.
+   */
+  protected $name = 'locale';
+
+  /**
+   * Implements ConfigPluginInterface::getTitle()
+   */
+  public function getTitle() {
+    return t('Locale');
+  }
+
+  /**
+   * Implements ConfigPluginInterface::context();
+   */
+  public function context($context) {
+    if ($context->getType() == CONFIG_TYPE_REQUEST) {
+      $context->set('language', $GLOBALS[LANGUAGE_TYPE_INTERFACE]);
+    }
+    elseif ($context->getType() == CONFIG_TYPE_CUSTOM) {
+      // Custom configuration, determine whether this has / needs a language.
+      if (!$context->hasData('language')) {
+        $language_list = language_list();
+        if ($user = $context->get('user')) {
+          // Resolve user language context.
+          $context->set('language', user_preferred_language($user));
+        }
+        elseif (($node = $context->get('node')) && !empty($node->language) && $isset($language_list[$node->language])) {
+          // Resolve node language context.
+          $context->set('language', $language_list[$node->language]);
+        }
+      }
+    }
+  }
+  /**
+   * Implements ConfigPluginInterface::read()
+   */
+  public function read($config) {
+    if ($language = $config->getContext()->get('language')) {
+      if ($override = $this->getStorage($config, $language)->read()) {
+        $config->setOverride($override);
+      }
+    }
+  }
+  /**
+   * Implements ConfigPluginInterface::save()
+   *
+   * Save al related language configurations.
+   */
+  public function save($config) {
+    $context = $config->getContext();
+    // If this configuration doesn't have a specific realm, think about translations.
+    /*
+    if ($context->getType() != CONFIG_TYPE_REALM) {
+      if ($language = $context->get('language')) {
+        // This configuration has a language so store instead in the proper file
+        $language_config = $this->getStorage($config, $language)->read();
+        $language_config->set($config->get());
+        $language_config->save();
+        // Return 'done' so the main configuration doesn't get saved.
+        return TRUE;
+      }
+      elseif ($this->isDefaultConfig($config) && $translate = $this->getConfigTranslatableProperties($config)) {
+        // This is English configuration and has translatable properties, think about defaults.
+        $this->updateTranslations($config, $translate);
+      }
+    }
+*/
+  }
+
+  /**
+   * Get configuration for a language.
+   */
+  protected static function getStorage($config, $language) {
+    $realm = locale_config_realm_name($language);
+    return config_storage($config->getName(), $realm);
+  }
+
+  /**
+   * Get current language from context.
+   */
+  protected static function getCurrentLanguage() {
+    return $GLOBALS[LANGUAGE_TYPE_INTERFACE];
+  }
+  /**
+   * Get language list.
+   */
+  protected static function getLanguageList() {
+    $language_list = language_list();
+    return $language_list;
+  }
+  /**
+   * Check whether this is the default configuration language.
+   */
+  protected static function isDefaultConfig($config) {
+    $langcode = $config->get('language');
+    return !$langcode || $langcode == 'en';
+  }
+  /**
+   * Get translatable properties from configuration object.
+   */
+  protected static function getConfigTranslatableProperties($config) {
+    return locale_config_translatable_properties($config->getName(), $config->get());
+  }
+  /**
+   * Save translations for all languages.
+   *
+   * @param $config
+   *   Configuration object.
+   * @param $translate
+   *   Array of key => value properties to translate.
+   */
+  protected static function updateTranslations($config, $translate) {
+    foreach (self::getLanguageList() as $language) {
+      $storage = self::getStorage($config, $language);
+      $translation = $storage->read();
+      $updated = FALSE;
+      foreach ($translate as $key => $default) {
+        if ($value = locale_config_translate($name, $key, $default)) {
+          config_array_set($translation, $key, $value);
+          $updated = TRUE;
+        }
+      }
+      if ($updated) {
+        $storage->save($translation);
+      }
+    }
+  }
+}
+
diff --git a/core/lib/Drupal/Core/Config/StorageBase.php b/core/lib/Drupal/Core/Config/StorageBase.php
index b03ff27..ba74845 100644
--- a/core/lib/Drupal/Core/Config/StorageBase.php
+++ b/core/lib/Drupal/Core/Config/StorageBase.php
@@ -18,6 +18,17 @@ abstract class StorageBase implements StorageInterface {
   protected $name;
 
   /**
+   * The realm of the configuration object.
+   *
+   * @var string
+   */
+  protected $realm;
+
+  /**
+   * Current stored data.
+   */
+  protected $data;
+  /**
    * The local file object to read from and write to.
    *
    * @var Drupal\Core\Config\FileStorage
@@ -27,8 +38,9 @@ abstract class StorageBase implements StorageInterface {
   /**
    * Implements StorageInterface::__construct().
    */
-  function __construct($name = NULL) {
+  function __construct($name = NULL, $realm = CONFIG_REALM_DEFAULT) {
     $this->name = $name;
+    $this->realm = $realm;
   }
 
   /**
@@ -39,7 +51,7 @@ abstract class StorageBase implements StorageInterface {
    */
   protected function fileStorage() {
     if (!isset($this->fileStorage)) {
-      $this->fileStorage = new FileStorage($this->name);
+      $this->fileStorage = config_storage($this->name, $this->realm, 'Drupal\Core\Config\FileStorage');
     }
     return $this->fileStorage;
   }
@@ -88,6 +100,7 @@ abstract class StorageBase implements StorageInterface {
   public function write($data) {
     $this->writeToActive($data);
     $this->writeToFile($data);
+    $this->data = $data;
   }
 
   /**
@@ -103,6 +116,7 @@ abstract class StorageBase implements StorageInterface {
   public function delete() {
     $this->deleteFromActive();
     $this->deleteFile();
+    $this->data = array();
   }
 
   /**
@@ -111,7 +125,12 @@ abstract class StorageBase implements StorageInterface {
   public function getName() {
     return $this->name;
   }
-
+  /**
+   * Implements StorageInterface::getRealm().
+   */
+  public function getRealm() {
+    return $this->realm;
+  }
   /**
    * Implements StorageInterface::setName().
    */
diff --git a/core/lib/Drupal/Core/Config/StorageInterface.php b/core/lib/Drupal/Core/Config/StorageInterface.php
index 43141a5..f120496 100644
--- a/core/lib/Drupal/Core/Config/StorageInterface.php
+++ b/core/lib/Drupal/Core/Config/StorageInterface.php
@@ -18,7 +18,7 @@ interface StorageInterface {
    * @param string $name
    *   (optional) The name of a configuration object to load.
    */
-  function __construct($name = NULL);
+  function __construct($name = NULL, $realm = CONFIG_REALM_DEFAULT);
 
   /**
    * Reads the configuration data from the storage.
@@ -110,6 +110,11 @@ interface StorageInterface {
   public function getName();
 
   /**
+   * Gets the realm name of this object.
+   */
+  public function getRealm();
+
+  /**
    * Sets the name of this object.
    */
   public function setName($name);
@@ -131,5 +136,5 @@ interface StorageInterface {
    * @return array
    *   An array containing matching configuration object names.
    */
-  static function getNamesWithPrefix($prefix = '');
+  static function getNamesWithPrefix($prefix = '', $realm = '');
 }
diff --git a/core/modules/book/config/node.type.book.language=es.yml b/core/modules/book/config/node.type.book.language=es.yml
new file mode 100644
index 0000000..2175638
--- /dev/null
+++ b/core/modules/book/config/node.type.book.language=es.yml
@@ -0,0 +1,3 @@
+title: 'Página de libro'
+description: '<em>Los libros</em> tienen navegación jerárquica. Se usan para manuales o tutoriales.'
+
diff --git a/core/modules/book/config/node.type.book.yml b/core/modules/book/config/node.type.book.yml
new file mode 100644
index 0000000..a1e38f1
--- /dev/null
+++ b/core/modules/book/config/node.type.book.yml
@@ -0,0 +1,7 @@
+type: 'book'
+title: 'Book page'
+base: 'node_content'
+description: '<em>Books</em> have a built-in hierarchical navigation. Use for handbooks or tutorials.'
+custom: '1'
+modified: '1'
+locked: '0'
diff --git a/core/modules/config/config.module b/core/modules/config/config.module
index b3d9bbc..50cce95 100644
--- a/core/modules/config/config.module
+++ b/core/modules/config/config.module
@@ -1 +1,3 @@
 <?php
+
+
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 35f8032..b9322db 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -1177,3 +1177,94 @@ function locale_get_localized_date_format($languages) {
 
   return $formats;
 }
+
+/**
+ * Implements hook_language_init()
+ */
+function locale_language_init() {
+  // Add locale plug-in to configuration.
+  config_plugin_container()->register('locale', 'Drupal\Core\Config\LocaleConfigPlugin');
+}
+
+/**
+ * Implements hook_config_install_default_config().
+ */
+function locale_config_install_default_config($module, $installed) {
+  foreach ($installed as $config_name => $config_data) {
+    // If installed default realm, we may need to translate string defaults
+    if (isset($config_data[CONFIG_REALM_DEFAULT])) {
+      $default_data = $config_data[CONFIG_REALM_DEFAULT];
+      $langcode = isset($default_data['language']) ? $default_data['language'] : 'en';
+      // Localize only if base language is English and we've got translatable properties.
+      if ($langcode == 'en' && ($translate = locale_config_translatable_properties($config_name, $default_data))) {
+        // For each translatable property and language check whether we already have it.
+        foreach (language_list() as $language) {
+          $merge = FALSE;
+          $language_realm = locale_config_realm_name($language);
+          $localized = isset($config_data[$language_realm]) ? $config_data[$language_realm] : array();
+          foreach ($translate as $key => $default) {
+            if (!config_array_get($localized, $key) && ($translation = locale_config_translate($config_name, $key, $default, $language))) {
+              config_array_set($localized, $key, $translation);
+              $merge = TRUE;
+            }
+          }
+          if ($merge) {
+            $database_storage = config_storage($config_name, $realm_name);
+            $database_storage->write($localized);
+          }
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Find list of translatable properties for config data.
+ */
+function locale_config_translatable_properties($config_name, $config_data) {
+  $translate = array();
+  foreach (config_info($config_name) as $name => $info) {
+    // @todo Check whether a property is translatable.
+    if ($value = config_array_get($config_data, $name)) {
+      switch ($info['type']) {
+        case 'label':
+        case 'description':
+        case 'string':
+          $translate[$name] = $value;
+      }
+    }
+  }
+  return $translate;
+}
+
+/**
+ * Build configuration realm name for language.
+ *
+ * @param $language
+ *   Language object or language code.
+ */
+function locale_config_realm_name($language) {
+  $langcode = is_object($language) ? $language->langcode : $language;
+  return 'language' . CONFIG_REALM_MARK . $langcode;
+}
+
+/**
+ * Translate value from configuration.
+ *
+ * This should return a value only when we have a translation.
+ *
+ * @todo
+ *   Improve locale to properly handle string keys.
+ */
+function locale_config_translate($config_name, $config_key, $string, $language) {
+  $locale = &drupal_static('locale');
+  $langcode = $language->langcode;
+  $context = 'config:' . $config_name . '.' . $config_key;
+  $translation = locale($string, $context, $langcode);
+  if ($locale[$langcode][$context][$string] === TRUE) {
+    return FALSE;
+  }
+  else {
+    return $translation;
+  }
+}
diff --git a/core/modules/system/config/system.site_information.language=es.yml b/core/modules/system/config/system.site_information.language=es.yml
new file mode 100644
index 0000000..459933c
--- /dev/null
+++ b/core/modules/system/config/system.site_information.language=es.yml
@@ -0,0 +1,7 @@
+site_name: 'Spanish Drupal'
+site_slogan: 'Bienvenido'
+site_mail: ''
+site_frontpage: ''
+default_nodes_main: '10'
+site_403: ''
+site_404: ''
diff --git a/core/modules/system/config/system.site_information.yml b/core/modules/system/config/system.site_information.yml
new file mode 100644
index 0000000..62935ab
--- /dev/null
+++ b/core/modules/system/config/system.site_information.yml
@@ -0,0 +1,8 @@
+language: 'en'
+site_name: 'Drupal'
+site_slogan: 'Welcome'
+site_mail: ''
+site_frontpage: ''
+default_nodes_main: '10'
+site_403: ''
+site_404: ''
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 168f2fc..3fddc53 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -755,6 +755,13 @@ function system_schema() {
         'not null' => TRUE,
         'default' => '',
       ),
+      'realm' => array(
+        'description' => 'The realm for the configuration entry, such as language=de.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
       'data' => array(
         'description' => 'The raw data for this configuration entry.',
         'type' => 'blob',
@@ -763,7 +770,7 @@ function system_schema() {
         'translatable' => TRUE,
       ),
     ),
-    'primary key' => array('name'),
+    'primary key' => array('name', 'realm'),
   );
 
 
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 39755dc..d021656 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -259,6 +259,9 @@ function system_hook_info() {
   $hooks['tokens_alter'] = array(
     'group' => 'tokens',
   );
+  $hooks['config_info'] = array(
+    'group' => 'config',
+  );
 
   return $hooks;
 }
