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