diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index fd3b719..e7da6ec 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -508,7 +508,13 @@ function config_get_config_directory($type = CONFIG_ACTIVE_DIRECTORY) {
     $path = conf_path() . '/files/simpletest/' . substr($test_prefix, 10) . '/config_' . $type;
   }
   elseif (!empty($config_directories[$type])) {
-    $path = conf_path() . '/files/' . $config_directories[$type];
+    // Allow a configuration directory path to be outside of webroot.
+    if (empty($config_directories[$type]['absolute'])) {
+      $path = conf_path() . '/files/' . $config_directories[$type]['path'];
+    }
+    else {
+      $path = $config_directories[$type]['path'];
+    }
   }
   else {
     throw new Exception(format_string('The configuration directory type %type does not exist.', array('%type' => $type)));
diff --git a/core/includes/entity.inc b/core/includes/entity.inc
index b651e32..24e150f 100644
--- a/core/includes/entity.inc
+++ b/core/includes/entity.inc
@@ -530,3 +530,48 @@ function entity_form_submit_build_entity($entity_type, $entity, $form, &$form_st
     field_attach_submit($entity_type, $entity, $form, $form_state);
   }
 }
+
+/**
+ * Returns an entity list controller for a given entity type.
+ *
+ * Since there might be different scenarios in which an entity is edited,
+ * multiple form controllers suitable to the different operations may be defined.
+ * If no controller is found for the default operation, the base class will be
+ * used. If a non-existing non-default operation is specified an exception will
+ * be thrown.
+ *
+ * @see hook_entity_info()
+ *
+ * @param string $entity_type
+ *   The type of the entity.
+ *
+ * @return Drupal\Core\Entity\EntityListControllerInterface
+ *   An entity list controller instance.
+ */
+function entity_list_controller($entity_type) {
+  $instances = &drupal_static(__FUNCTION__, array());
+
+  if (isset($instances[$entity_type])) {
+    return $instances[$entity_type];
+  }
+
+  $info = entity_get_info($entity_type);
+
+  // Check whether there is a controller class for the specified operation.
+  if (!empty($info['list controller class'])) {
+    $class = $info['list controller class'];
+  }
+  // If no controller is specified default to the base implementation.
+  // @todo Provide a sane base implementation.
+  /*
+  elseif (empty($info['list controller class'])) {
+    $class = 'Drupal\Core\Entity\EntityListControllerBase';
+  }
+  */
+  else {
+    throw new \InvalidArgumentException("Missing list controller for '$entity_type'");
+  }
+
+  $instances[$entity_type] = new $class($entity_type);
+  return $instances[$entity_type];
+}
diff --git a/core/includes/install.inc b/core/includes/install.inc
index 330fc0e..efba3c1 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -266,8 +266,12 @@ function drupal_install_config_directories() {
   if (empty($config_directories)) {
     $settings['config_directories'] = array(
       'value' => array(
-        CONFIG_ACTIVE_DIRECTORY => 'config/active_' . drupal_hash_base64(drupal_random_bytes(55)),
-        CONFIG_STAGING_DIRECTORY => 'config/staging_' . drupal_hash_base64(drupal_random_bytes(55)),
+        CONFIG_ACTIVE_DIRECTORY => array(
+          'path' => 'config/active_' . drupal_hash_base64(drupal_random_bytes(55)),
+        ),
+        CONFIG_STAGING_DIRECTORY => array(
+          'path' => 'config/staging_' . drupal_hash_base64(drupal_random_bytes(55)),
+        ),
       ),
       'required' => TRUE,
     );
diff --git a/core/includes/mail.inc b/core/includes/mail.inc
index 1be3c38..e9778d8 100644
--- a/core/includes/mail.inc
+++ b/core/includes/mail.inc
@@ -26,13 +26,13 @@
  *
  * Finding out what language to send the e-mail with needs some consideration.
  * If you send e-mail to a user, her preferred language should be fine, so
- * use user_preferred_language(). If you send email based on form values
+ * use user_preferred_langcode(). If you send email based on form values
  * filled on the page, there are two additional choices if you are not
  * sending the e-mail to a user on the site. You can either use the language
- * used to generate the page ($language global variable) or the site default
- * language. See language_default(). The former is good if sending e-mail to
- * the person filling the form, the later is good if you send e-mail to an
- * address previously set up (like contact addresses in a contact form).
+ * used to generate the page or the site default language. See
+ * language_default(). The former is good if sending e-mail to the person
+ * filling the form, the later is good if you send e-mail to an address
+ * previously set up (like contact addresses in a contact form).
  *
  * Taking care of always using the proper language is even more important
  * when sending e-mails in a row to multiple users. Hook_mail() abstracts
@@ -47,13 +47,13 @@
  *     foreach ($accounts as $account) {
  *       $params['account'] = $account;
  *       // example_mail() will be called based on the first drupal_mail() parameter.
- *       drupal_mail('example', 'notice', $account->mail, user_preferred_language($account), $params);
+ *       drupal_mail('example', 'notice', $account->mail, user_preferred_langcode($account), $params);
  *     }
  *   }
  *
  *   function example_mail($key, &$message, $params) {
  *     $data['user'] = $params['account'];
- *     $options['langcode'] = $message['language'];
+ *     $options['langcode'] = $message['langcode'];
  *     user_mail_tokens($variables, $data, $options);
  *     switch($key) {
  *       case 'notice':
@@ -63,9 +63,8 @@
  *           $message['send'] = FALSE;
  *           break;
  *         }
- *         $langcode = $message['language']->langcode;
- *         $message['subject'] = t('Notification from !site', $variables, array('langcode' => $langcode));
- *         $message['body'][] = t("Dear !username\n\nThere is new content available on the site.", $variables, array('langcode' => $langcode));
+ *         $message['subject'] = t('Notification from !site', $variables, $options);
+ *         $message['body'][] = t("Dear !username\n\nThere is new content available on the site.", $variables, $options);
  *         break;
  *     }
  *   }
@@ -77,7 +76,7 @@
  * @code
  *   $params = array('current_conditions' => $data);
  *   $to = 'user@example.com';
- *   $message = drupal_mail('example', 'notice', $to, $language, $params, FALSE);
+ *   $message = drupal_mail('example', 'notice', $to, $langcode, $params, FALSE);
  *   // Only add to the spool if sending was not canceled.
  *   if ($message['send']) {
  *     example_spool_message($message);
@@ -98,10 +97,10 @@
  *   - user@example.com, anotheruser@example.com
  *   - User <user@example.com>
  *   - User <user@example.com>, Another User <anotheruser@example.com>
- * @param $language
- *   Language object to use to compose the e-mail.
+ * @param $langcode
+ *   Language code to use to compose the e-mail.
  * @param $params
- *   Optional parameters to build the e-mail.
+ *   (optional) parameters to build the e-mail.
  * @param $from
  *   Sets From to this value, if given.
  * @param $send
@@ -117,7 +116,7 @@
  *   written to the watchdog. (Success means nothing more than the message being
  *   accepted at php-level, which still doesn't guarantee it to be delivered.)
  */
-function drupal_mail($module, $key, $to, $language, $params = array(), $from = NULL, $send = TRUE) {
+function drupal_mail($module, $key, $to, $langcode, $params = array(), $from = NULL, $send = TRUE) {
   $site_mail = config('system.site')->get('mail');
   if (empty($site_mail)) {
     $site_mail = ini_get('sendmail_from');
@@ -131,7 +130,7 @@ function drupal_mail($module, $key, $to, $language, $params = array(), $from = N
     'key'      => $key,
     'to'       => $to,
     'from'     => isset($from) ? $from : $default_from,
-    'language' => $language,
+    'langcode' => $langcode,
     'params'   => $params,
     'send'     => TRUE,
     'subject'  => '',
diff --git a/core/lib/Drupal/Core/Entity/EntityListControllerBase.php b/core/lib/Drupal/Core/Entity/EntityListControllerBase.php
new file mode 100644
index 0000000..20b34ae
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/EntityListControllerBase.php
@@ -0,0 +1,110 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Entity\EntityListControllerBase.
+ */
+
+namespace Drupal\Core\Entity;
+
+/**
+ * Abstract base class for entity list controllers.
+ */
+abstract class EntityListControllerBase implements EntityListControllerInterface {
+
+  /**
+   * The entity storage controller class.
+   *
+   * @var Drupal\Core\Entity\EntityStorageControllerInterface
+   */
+  protected $storage;
+
+  /**
+   * The entity type name.
+   *
+   * @var string
+   */
+  protected $entityType;
+
+  /**
+   * The entity info.
+   *
+   * @var array
+   */
+  protected $entityInfo;
+
+  public function __construct($entity_type) {
+    $this->entityType = $entity_type;
+    $this->storage = entity_get_controller($this->entityType);
+    $this->entityInfo = entity_get_info($this->entityType);
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\EntityListControllerInterface::getStorageController();
+   */
+  public function getStorageController() {
+    return $this->storage;
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\EntityListControllerInterface::load();
+   */
+  public function load() {
+    return $this->storage->load();
+  }
+
+  public function getPath() {
+    return $this->entityInfo['list path'];
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\EntityListControllerInterface::buildHeader();
+   */
+  public function buildHeader() {
+    $row['label'] = t('Label');
+    $row['id'] = t('Machine name');
+    $row['operations'] = t('Operations');
+    return $row;
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\EntityListControllerInterface::buildRow();
+   */
+  public function buildRow(EntityInterface $entity) {
+    $row['label'] = $entity->label();
+    $row['id'] = $entity->id();
+    $row['operations']['data'] = $this->buildOperations($entity);
+    return $row;
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\EntityListControllerInterface::buildOperations();
+   */
+  public function buildOperations(EntityInterface $entity) {
+    $operations = $this->getOperations($entity);
+    return $operations;
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\EntityListControllerInterface::render();
+   */
+  public function render() {
+    $build = array(
+      '#theme' => 'table',
+      '#header' => $this->buildHeader(),
+      '#rows' => array(),
+      '#empty' => t('There is no @label yet. <a href="@add-url">Add one</a>.', array(
+        '@label' => $this->entityInfo['label'],
+        '@add-url' => $this->getPath() . '/add',
+      )),
+      '#attributes' => array(
+        'id' => 'config-entity-listing',
+      ),
+    );
+    foreach ($this->load() as $entity) {
+      $build['#rows'][$entity->id()] = $this->buildRow($entity);
+    }
+    return $build;
+  }
+
+}
diff --git a/core/lib/Drupal/Core/Entity/EntityListControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityListControllerInterface.php
new file mode 100644
index 0000000..d93d91c
--- /dev/null
+++ b/core/lib/Drupal/Core/Entity/EntityListControllerInterface.php
@@ -0,0 +1,74 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Entity\EntityListControllerInterface.
+ */
+
+namespace Drupal\Core\Entity;
+
+/**
+ * Defines an interface for entity list controllers.
+ */
+interface EntityListControllerInterface {
+
+  /**
+   * Gets the entity storage controller.
+   *
+   * @var Drupal\Core\Entity\EntityStorageControllerInterface
+   */
+  public function getStorageController();
+
+  /**
+   * Loads entities of this type.
+   *
+   * @return array
+   *   An array of entities implementing Drupal\Core\Entity\EntityInterface.
+   */
+  public function load();
+
+  /**
+   * Provides an array of information to render operation links.
+   *
+   * @return array
+   *   An array of operation link data to use in buildOperations.
+   *
+   * @todo Operations are specific to the *Entity*, not the list. Move into the Entity class.
+   */
+  public function getOperations(EntityInterface $entity);
+
+  /**
+   * Builds the header row.
+   *
+   * @return array
+   *   An array of header strings.
+   */
+  public function buildHeader();
+
+  /**
+   * Builds an array of data for each row.
+   *
+   * @param Drupal\Core\Entity\EntityInterface $entity
+   *
+   * @return array
+   *   An array of fields to use for this entity.
+   */
+  public function buildRow(EntityInterface $entity);
+
+  /**
+   * Renders a list of operation links.
+   *
+   * @return array
+   *   A renderable array of operation links.
+   */
+  public function buildOperations(EntityInterface $entity);
+
+  /**
+   * Renders the list page markup to be output.
+   *
+   * @return string
+   *   The output markup for the listing page.
+   */
+  public function render();
+
+}
diff --git a/core/modules/book/lib/Drupal/book/Tests/BookTest.php b/core/modules/book/lib/Drupal/book/Tests/BookTest.php
index e60142f..d11ffb3 100644
--- a/core/modules/book/lib/Drupal/book/Tests/BookTest.php
+++ b/core/modules/book/lib/Drupal/book/Tests/BookTest.php
@@ -142,7 +142,7 @@ function checkBookNode(Node $node, $nodes, $previous = FALSE, $up = FALSE, $next
 
     // Check outline structure.
     if ($nodes !== NULL) {
-      $this->assertPattern($this->generateOutlinePattern($nodes), t('Node ' . $number . ' outline confirmed.'));
+      $this->assertPattern($this->generateOutlinePattern($nodes), format_string('Node @number outline confirmed.', array('@number' => $number)));
     }
     else {
       $this->pass(t('Node ' . $number . ' doesn\'t have outline.'));
@@ -150,15 +150,15 @@ function checkBookNode(Node $node, $nodes, $previous = FALSE, $up = FALSE, $next
 
     // Check previous, up, and next links.
     if ($previous) {
-      $this->assertRaw(l('<b>‹</b> ' . $previous->label(), 'node/' . $previous->nid, array('html' => TRUE, 'attributes' => array('rel' => array('prev'), 'title' => t('Go to previous page')))), t('Previous page link found.'));
+      $this->assertRaw(l('<b>‹</b> ' . $previous->label(), 'node/' . $previous->nid, array('html' => TRUE, 'attributes' => array('rel' => array('prev'), 'title' => t('Go to previous page')))), 'Previous page link found.');
     }
 
     if ($up) {
-      $this->assertRaw(l('up', 'node/' . $up->nid, array('html'=> TRUE, 'attributes' => array('title' => t('Go to parent page')))), t('Up page link found.'));
+      $this->assertRaw(l('up', 'node/' . $up->nid, array('html'=> TRUE, 'attributes' => array('title' => t('Go to parent page')))), 'Up page link found.');
     }
 
     if ($next) {
-      $this->assertRaw(l($next->label() . ' <b>›</b>', 'node/' . $next->nid, array('html'=> TRUE, 'attributes' => array('rel' => array('next'), 'title' => t('Go to next page')))), t('Next page link found.'));
+      $this->assertRaw(l($next->label() . ' <b>›</b>', 'node/' . $next->nid, array('html'=> TRUE, 'attributes' => array('rel' => array('next'), 'title' => t('Go to next page')))), 'Next page link found.');
     }
 
     // Compute the expected breadcrumb.
@@ -176,12 +176,12 @@ function checkBookNode(Node $node, $nodes, $previous = FALSE, $up = FALSE, $next
     }
 
     // Compare expected and got breadcrumbs.
-    $this->assertIdentical($expected_breadcrumb, $got_breadcrumb, t('The breadcrumb is correctly displayed on the page.'));
+    $this->assertIdentical($expected_breadcrumb, $got_breadcrumb, 'The breadcrumb is correctly displayed on the page.');
 
     // Check printer friendly version.
     $this->drupalGet('book/export/html/' . $node->nid);
-    $this->assertText($node->label(), t('Printer friendly title found.'));
-    $this->assertRaw(check_markup($node->body[LANGUAGE_NOT_SPECIFIED][0]['value'], $node->body[LANGUAGE_NOT_SPECIFIED][0]['format']), t('Printer friendly body found.'));
+    $this->assertText($node->label(), 'Printer friendly title found.');
+    $this->assertRaw(check_markup($node->body[LANGUAGE_NOT_SPECIFIED][0]['value'], $node->body[LANGUAGE_NOT_SPECIFIED][0]['format']), 'Printer friendly body found.');
 
     $number++;
   }
@@ -229,7 +229,7 @@ function createBookNode($book_nid, $parent = NULL) {
 
     // Check to make sure the book node was created.
     $node = $this->drupalGetNodeByTitle($edit['title']);
-    $this->assertNotNull(($node === FALSE ? NULL : $node), t('Book node found in database.'));
+    $this->assertNotNull(($node === FALSE ? NULL : $node), 'Book node found in database.');
     $number++;
 
     return $node;
@@ -249,28 +249,28 @@ function testBookExport() {
 
     // Make sure each part of the book is there.
     foreach ($nodes as $node) {
-      $this->assertText($node->label(), t('Node title found in printer friendly version.'));
-      $this->assertRaw(check_markup($node->body[LANGUAGE_NOT_SPECIFIED][0]['value'], $node->body[LANGUAGE_NOT_SPECIFIED][0]['format']), t('Node body found in printer friendly version.'));
+      $this->assertText($node->label(), 'Node title found in printer friendly version.');
+      $this->assertRaw(check_markup($node->body[LANGUAGE_NOT_SPECIFIED][0]['value'], $node->body[LANGUAGE_NOT_SPECIFIED][0]['format']), 'Node body found in printer friendly version.');
     }
 
     // Make sure we can't export an unsupported format.
     $this->drupalGet('book/export/foobar/' . $this->book->nid);
-    $this->assertResponse('404', t('Unsupported export format returned "not found".'));
+    $this->assertResponse('404', 'Unsupported export format returned "not found".');
 
     // Make sure we get a 404 on a not existing book node.
     $this->drupalGet('book/export/html/123');
-    $this->assertResponse('404', t('Not existing book node returned "not found".'));
+    $this->assertResponse('404', 'Not existing book node returned "not found".');
 
     // Make sure an anonymous user cannot view printer-friendly version.
     $this->drupalLogout();
 
     // Load the book and verify there is no printer-friendly version link.
     $this->drupalGet('node/' . $this->book->nid);
-    $this->assertNoLink(t('Printer-friendly version'), t('Anonymous user is not shown link to printer-friendly version.'));
+    $this->assertNoLink(t('Printer-friendly version'), 'Anonymous user is not shown link to printer-friendly version.');
 
     // Try getting the URL directly, and verify it fails.
     $this->drupalGet('book/export/html/' . $this->book->nid);
-    $this->assertResponse('403', t('Anonymous user properly forbidden.'));
+    $this->assertResponse('403', 'Anonymous user properly forbidden.');
   }
 
   /**
@@ -282,26 +282,26 @@ function testBookNavigationBlock() {
     // Set block title to confirm that the interface is available.
     $block_title = $this->randomName(16);
     $this->drupalPost('admin/structure/block/manage/book/navigation/configure', array('title' => $block_title), t('Save block'));
-    $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
+    $this->assertText(t('The block configuration has been saved.'), 'Block configuration set.');
 
     // Set the block to a region to confirm block is available.
     $edit = array();
     $edit['blocks[book_navigation][region]'] = 'footer';
     $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
-    $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
+    $this->assertText(t('The block settings have been updated.'), 'Block successfully move to footer region.');
 
      // Give anonymous users the permission 'node test view'.
      $edit = array();
      $edit[DRUPAL_ANONYMOUS_RID . '[node test view]'] = TRUE;
      $this->drupalPost('admin/people/permissions/' . DRUPAL_ANONYMOUS_RID, $edit, t('Save permissions'));
-     $this->assertText(t('The changes have been saved.'), t("Permission 'node test view' successfully assigned to anonymous users."));
+     $this->assertText(t('The changes have been saved.'), "Permission 'node test view' successfully assigned to anonymous users.");
 
     // Test correct display of the block.
     $nodes = $this->createBook();
     $this->drupalGet('<front>');
-    $this->assertText($block_title, t('Book navigation block is displayed.'));
-    $this->assertText($this->book->label(), t('Link to book root (@title) is displayed.', array('@title' => $nodes[0]->label())));
-    $this->assertNoText($nodes[0]->label(), t('No links to individual book pages are displayed.'));
+    $this->assertText($block_title, 'Book navigation block is displayed.');
+    $this->assertText($this->book->label(), format_string('Link to book root (@title) is displayed.', array('@title' => $nodes[0]->label())));
+    $this->assertNoText($nodes[0]->label(), 'No links to individual book pages are displayed.');
   }
 
   /**
@@ -318,19 +318,19 @@ function testNavigationBlockOnAccessModuleEnabled() {
      // Set block display to 'Show block only on book pages'.
      $edit['book_block_mode'] = 'book pages';
      $this->drupalPost('admin/structure/block/manage/book/navigation/configure', $edit, t('Save block'));
-     $this->assertText(t('The block configuration has been saved.'), t('Block configuration set.'));
+     $this->assertText(t('The block configuration has been saved.'), 'Block configuration set.');
 
      // Set the block to a region to confirm block is available.
      $edit = array();
      $edit['blocks[book_navigation][region]'] = 'footer';
      $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
-     $this->assertText(t('The block settings have been updated.'), t('Block successfully move to footer region.'));
+     $this->assertText(t('The block settings have been updated.'), 'Block successfully move to footer region.');
 
      // Give anonymous users the permission 'node test view'.
      $edit = array();
      $edit[DRUPAL_ANONYMOUS_RID . '[node test view]'] = TRUE;
      $this->drupalPost('admin/people/permissions/' . DRUPAL_ANONYMOUS_RID, $edit, t('Save permissions'));
-     $this->assertText(t('The changes have been saved.'), t('Permission \'node test view\' successfully assigned to anonymous users.'));
+     $this->assertText(t('The changes have been saved.'), 'Permission \'node test view\' successfully assigned to anonymous users.');
 
      // Create a book.
      $this->createBook();
@@ -338,12 +338,12 @@ function testNavigationBlockOnAccessModuleEnabled() {
      // Test correct display of the block to registered users.
      $this->drupalLogin($this->web_user);
      $this->drupalGet('node/' . $this->book->nid);
-     $this->assertText($block_title, t('Book navigation block is displayed to registered users.'));
+     $this->assertText($block_title, 'Book navigation block is displayed to registered users.');
      $this->drupalLogout();
 
      // Test correct display of the block to anonymous users.
      $this->drupalGet('node/' . $this->book->nid);
-     $this->assertText($block_title, t('Book navigation block is displayed to anonymous users.'));
+     $this->assertText($block_title, 'Book navigation block is displayed to anonymous users.');
    }
 
   /**
@@ -359,7 +359,7 @@ function testBookDelete() {
      $this->assertResponse('403', t('Deleting top-level book node properly forbidden.'));
      $this->drupalPost('node/' . $nodes[4]->nid . '/outline/remove', $edit, t('Remove'));
      $node4 = node_load($nodes[4]->nid, TRUE);
-     $this->assertTrue(empty($node4->book), t('Deleting child book node properly allowed.'));
+     $this->assertTrue(empty($node4->book), 'Deleting child book node properly allowed.');
 
      // Delete all child book nodes and retest top-level node deletion.
      foreach ($nodes as $node) {
@@ -368,7 +368,7 @@ function testBookDelete() {
      node_delete_multiple($nids);
      $this->drupalPost('node/' . $this->book->nid . '/outline/remove', $edit, t('Remove'));
      $node = node_load($this->book->nid, TRUE);
-     $this->assertTrue(empty($node->book), t('Deleting childless top-level book node properly allowed.'));
+     $this->assertTrue(empty($node->book), 'Deleting childless top-level book node properly allowed.');
    }
 }
 
diff --git a/core/modules/config/lib/Drupal/config/ConfigEntityListController.php b/core/modules/config/lib/Drupal/config/ConfigEntityListController.php
new file mode 100644
index 0000000..1b56899
--- /dev/null
+++ b/core/modules/config/lib/Drupal/config/ConfigEntityListController.php
@@ -0,0 +1,49 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\config\ConfigEntityListController.
+ */
+
+namespace Drupal\config;
+
+use Drupal\Core\Entity\EntityListControllerBase;
+use Drupal\Core\Entity\EntityInterface;
+
+/**
+ * Default list controller for ConfigEntity objects.
+ */
+class ConfigEntityListController extends EntityListControllerBase {
+
+  /**
+   * Overrides Drupal\Core\Entity\EntityListControllerBase::load().
+   */
+  public function load() {
+    $entities = parent::load();
+    uasort($entities, 'Drupal\config\ConfigEntityBase::sort');
+    return $entities;
+  }
+
+  /**
+   * Implements Drupal\Core\Entity\EntityListControllerInterface::getOperations().
+   */
+  public function getOperations(EntityInterface $entity) {
+    $uri = $entity->uri();
+    $operations['edit'] = array(
+      '#type' => 'link',
+      '#title' => t('edit'),
+      '#href' => $uri['path'] . '/edit',
+      '#options' => $uri['options'],
+      '#weight' => 10,
+    );
+    $operations['delete'] = array(
+      '#type' => 'link',
+      '#title' => t('delete'),
+      '#href' => $uri['path'] . '/delete',
+      '#options' => $uri['options'],
+      '#weight' => 100,
+    );
+    return $operations;
+  }
+
+}
diff --git a/core/modules/config/lib/Drupal/config/Tests/ConfigEntityListTest.php b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityListTest.php
new file mode 100644
index 0000000..46d52f6
--- /dev/null
+++ b/core/modules/config/lib/Drupal/config/Tests/ConfigEntityListTest.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\config\Tests\ConfigEntityListTest.
+ */
+
+namespace Drupal\config\Tests;
+
+use Drupal\simpletest\WebTestBase;
+use Drupal\config_test\ConfigTest;
+
+/**
+ * Tests listing of configuration entities.
+ */
+class ConfigEntityListTest extends WebTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = array('config_test');
+
+  public static function getInfo() {
+    return array(
+      'name' => 'Configuration entity list',
+      'description' => 'Tests listing of configuration entities.',
+      'group' => 'Configuration',
+    );
+  }
+
+  /**
+   * Tests entity list controller functionality.
+   */
+  function testList() {
+    $controller = entity_list_controller('config_test');
+
+    // Get a list of ConfigTest entities.
+    $list = $controller->load();
+    $this->assertEqual(count($list), 1, '1 ConfigTest entity found.');
+    $this->assertTrue(!empty($list['default']), '"Default" ConfigTest entity ID found.');
+    $this->assertTrue($list['default'] instanceof ConfigTest, '"Default" ConfigTest entity is an instance of ConfigTest.');
+  }
+
+  /**
+   * Tests the listing UI.
+   */
+  function testListUI() {
+    $page = $this->drupalGet('admin/structure/config_test');
+    $this->assertText('Test configuration');
+
+    // Verify that the default ConfigTest configuration appears.
+    $this->assertText('default');
+    $this->assertText('Default');
+
+    // Verify that operation links appear.
+    foreach (array('edit', 'delete') as $link) {
+      $this->drupalSetContent($page);
+      $this->assertLink($link);
+      $this->clickLink($link);
+      $this->assertResponse(200);
+    }
+  }
+
+}
diff --git a/core/modules/config/tests/config_test/config_test.module b/core/modules/config/tests/config_test/config_test.module
index 44d4087..a75eff8 100644
--- a/core/modules/config/tests/config_test/config_test.module
+++ b/core/modules/config/tests/config_test/config_test.module
@@ -82,6 +82,8 @@ function config_test_entity_info() {
     'label' => 'Test configuration',
     'controller class' => 'Drupal\config\ConfigStorageController',
     'entity class' => 'Drupal\config_test\ConfigTest',
+    'list controller class' => 'Drupal\config\ConfigEntityListController',
+    'list path' => 'admin/structure/config_test',
     'uri callback' => 'config_test_uri',
     'config prefix' => 'config_test.dynamic',
     'entity keys' => array(
@@ -176,8 +178,10 @@ function config_test_delete($id) {
  * Page callback; Lists available ConfigTest objects.
  */
 function config_test_list_page() {
+  $controller = entity_list_controller('config_test');
+  return $controller->render();
+
   $entities = entity_load_multiple('config_test');
-  uasort($entities, 'Drupal\config\ConfigEntityBase::sort');
 
   $rows = array();
   foreach ($entities as $config_test) {
@@ -201,9 +205,6 @@ function config_test_list_page() {
     '#theme' => 'table',
     '#header' => array('Name', 'Operations'),
     '#rows' => $rows,
-    '#empty' => format_string('No test configuration defined. <a href="@add-url">Add some</a>', array(
-      '@add-url' => url('admin/structure/config_test/add'),
-    )),
   );
   return $build;
 }
diff --git a/core/modules/contact/contact.module b/core/modules/contact/contact.module
index 1ba70b9..985abbd 100644
--- a/core/modules/contact/contact.module
+++ b/core/modules/contact/contact.module
@@ -168,7 +168,7 @@ function contact_load($cid) {
  * Implements hook_mail().
  */
 function contact_mail($key, &$message, $params) {
-  $language = $message['language'];
+  $language = language_load($message['langcode']);
   $variables = array(
     '!site-name' => config('system.site')->get('name'),
     '!subject' => $params['subject'],
diff --git a/core/modules/contact/contact.pages.inc b/core/modules/contact/contact.pages.inc
index 08c1d12..e9a6c62 100644
--- a/core/modules/contact/contact.pages.inc
+++ b/core/modules/contact/contact.pages.inc
@@ -168,16 +168,16 @@ function contact_site_form_submit($form, &$form_state) {
   $from = $values['sender']->mail;
 
   // Send the e-mail to the recipients using the site default language.
-  drupal_mail('contact', 'page_mail', $to, language_default(), $values, $from);
+  drupal_mail('contact', 'page_mail', $to, language_default()->langcode, $values, $from);
 
   // If the user requests it, send a copy using the current language.
   if ($values['copy']) {
-    drupal_mail('contact', 'page_copy', $from, $language_interface, $values, $from);
+    drupal_mail('contact', 'page_copy', $from, $language_interface->langcode, $values, $from);
   }
 
   // Send an auto-reply if necessary using the current language.
   if ($values['category']['reply']) {
-    drupal_mail('contact', 'page_autoreply', $from, $language_interface, $values, $to);
+    drupal_mail('contact', 'page_autoreply', $from, $language_interface->langcode, $values, $to);
   }
 
   flood_register_event('contact', config('contact.settings')->get('flood.interval'));
@@ -308,11 +308,11 @@ function contact_personal_form_submit($form, &$form_state) {
   $from = $values['sender']->mail;
 
   // Send the e-mail in the requested user language.
-  drupal_mail('contact', 'user_mail', $to, user_preferred_language($values['recipient']), $values, $from);
+  drupal_mail('contact', 'user_mail', $to, user_preferred_langcode($values['recipient']), $values, $from);
 
   // Send a copy if requested, using current page language.
   if ($values['copy']) {
-    drupal_mail('contact', 'user_copy', $from, $language_interface, $values, $from);
+    drupal_mail('contact', 'user_copy', $from, $language_interface->langcode, $values, $from);
   }
 
   flood_register_event('contact', config('contact.settings')->get('flood.interval'));
diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php
index a407c74..73c4a83 100644
--- a/core/modules/field/field.api.php
+++ b/core/modules/field/field.api.php
@@ -33,6 +33,8 @@
  *   - label: The human readable name of the component.
  *   - description: A short description of the component contents.
  *   - weight: The default weight of the element.
+ *   - visible: The default visibility of the element. Only for 'display'
+ *     context.
  */
 function hook_field_extra_fields() {
   $extra['node']['poll'] = array(
diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc
index 0d00dbd..65c6bcc 100644
--- a/core/modules/field/field.info.inc
+++ b/core/modules/field/field.info.inc
@@ -431,6 +431,7 @@ function _field_info_prepare_extra_fields($extra_fields, $entity_type, $bundle)
   $data = $extra_fields['display'];
   foreach ($extra_fields['display'] as $name => $field_data) {
     $settings = isset($bundle_settings['extra_fields']['display'][$name]) ? $bundle_settings['extra_fields']['display'][$name] : array();
+    $field_data['visible'] = isset($field_data['visible']) ? $field_data['visible'] : TRUE;
     $view_modes = array_merge(array('default'), array_keys($entity_type_info['view modes']));
     foreach ($view_modes as $view_mode) {
       if (isset($settings[$view_mode])) {
@@ -439,7 +440,7 @@ function _field_info_prepare_extra_fields($extra_fields, $entity_type, $bundle)
       else {
         $field_data['display'][$view_mode] = array(
           'weight' => $field_data['weight'],
-          'visible' => TRUE,
+          'visible' => $field_data['visible'],
         );
       }
     }
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index ccdc879..775de2d 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -1205,6 +1205,9 @@ function theme_image_style($variables) {
   $variables['width'] = $dimensions['width'];
   $variables['height'] = $dimensions['height'];
 
+  // Add in the image style name as an HTML class.
+  $variables['attributes']['class'][] = 'image-style-' . drupal_html_class($variables['style_name']);
+
   // Determine the URL for the styled image.
   $variables['uri'] = image_style_url($variables['style_name'], $variables['uri']);
   return theme('image', $variables);
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php
index d2554cf..76110cf 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageDimensionsTest.php
@@ -69,7 +69,7 @@ function testImageDimensions() {
 
     image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img src="' . $url . '" width="120" height="60" alt="" />');
+    $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="120" height="60" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
@@ -90,7 +90,7 @@ function testImageDimensions() {
 
     image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img src="' . $url . '" width="60" height="120" alt="" />');
+    $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="60" height="120" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
@@ -112,7 +112,7 @@ function testImageDimensions() {
 
     image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img src="' . $url . '" width="45" height="90" alt="" />');
+    $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="45" height="90" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
@@ -134,7 +134,7 @@ function testImageDimensions() {
 
     image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img src="' . $url . '" width="45" height="90" alt="" />');
+    $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="45" height="90" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
@@ -152,7 +152,7 @@ function testImageDimensions() {
 
     image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img src="' . $url . '" width="45" height="90" alt="" />');
+    $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="45" height="90" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
@@ -173,7 +173,7 @@ function testImageDimensions() {
 
     image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img src="' . $url . '" alt="" />');
+    $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
@@ -193,7 +193,7 @@ function testImageDimensions() {
 
     image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img src="' . $url . '" width="30" height="30" alt="" />');
+    $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" width="30" height="30" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
@@ -214,7 +214,7 @@ function testImageDimensions() {
 
     $effect = image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img src="' . $url . '" alt="" />');
+    $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" alt="" />');
     $this->assertFalse(file_exists($generated_uri), t('Generated file does not exist.'));
     $this->drupalGet($url);
     $this->assertResponse(200, t('Image was generated at the URL.'));
@@ -232,6 +232,6 @@ function testImageDimensions() {
 
     image_effect_save('test', $effect);
     $img_tag = theme_image_style($variables);
-    $this->assertEqual($img_tag, '<img src="' . $url . '" alt="" />');
+    $this->assertEqual($img_tag, '<img class="image-style-test" src="' . $url . '" alt="" />');
   }
 }
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
index 601c3c2..9e00434 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php
@@ -104,10 +104,11 @@ function _testImageFieldFormatters($scheme) {
     // Ensure the derivative image is generated so we do not have to deal with
     // image style callback paths.
     $this->drupalGet(image_style_url('thumbnail', $image_uri));
-    $image_info['uri'] = image_style_path('thumbnail', $image_uri);
+    $image_info['uri'] = $image_uri;
     $image_info['width'] = 100;
     $image_info['height'] = 50;
-    $default_output = theme('image', $image_info);
+    $image_info['style_name'] = 'thumbnail';
+    $default_output = theme('image_style', $image_info);
     $this->drupalGet('node/' . $nid);
     $this->assertRaw($default_output, t('Image style thumbnail formatter displaying correctly on full node view.'));
 
@@ -158,11 +159,12 @@ function testImageFieldSettings() {
     // style.
     $node = node_load($nid, TRUE);
     $image_info = array(
-      'uri' => image_style_url('medium', file_load($node->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid'])->uri),
+      'uri' => file_load($node->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid'])->uri,
       'width' => 220,
       'height' => 110,
+      'style_name' => 'medium',
     );
-    $default_output = theme('image', $image_info);
+    $default_output = theme('image_style', $image_info);
     $this->assertRaw($default_output, t("Preview image is displayed using 'medium' style."));
 
     // Add alt/title fields to the image and verify that they are displayed.
diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageThemeFunctionTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageThemeFunctionTest.php
index 0e026f2..45de98e 100644
--- a/core/modules/image/lib/Drupal/image/Tests/ImageThemeFunctionTest.php
+++ b/core/modules/image/lib/Drupal/image/Tests/ImageThemeFunctionTest.php
@@ -56,7 +56,7 @@ function testImageFormatterTheme() {
       ),
     );
     $rendered_element = render($element);
-    $expected_result = '<a href="' . base_path() . $path . '"><img src="' . $url . '" alt="" /></a>';
+    $expected_result = '<a href="' . base_path() . $path . '"><img class="image-style-test" src="' . $url . '" alt="" /></a>';
     $this->assertEqual($expected_result, $rendered_element, 'theme_image_formatter() correctly renders without title, alt, or path options.');
 
     // Link the image to a fragment on the page, and not a full URL.
@@ -67,7 +67,7 @@ function testImageFormatterTheme() {
       'fragment' => $fragment,
     );
     $rendered_element = render($element);
-    $expected_result = '<a href="#' . $fragment . '"><img src="' . $url . '" alt="" /></a>';
+    $expected_result = '<a href="#' . $fragment . '"><img class="image-style-test" src="' . $url . '" alt="" /></a>';
     $this->assertEqual($expected_result, $rendered_element, 'theme_image_formatter() correctly renders a link fragment.');
   }
 
@@ -81,17 +81,17 @@ function testImageStyleTheme() {
     $original_uri = file_unmanaged_copy($file->uri, 'public://', FILE_EXISTS_RENAME);
 
     // Create a style.
-    image_style_save(array('name' => 'test'));
-    $url = image_style_url('test', $original_uri);
+    image_style_save(array('name' => 'image_test'));
+    $url = image_style_url('image_test', $original_uri);
 
     $path = $this->randomName();
     $element = array(
       '#theme' => 'image_style',
-      '#style_name' => 'test',
+      '#style_name' => 'image_test',
       '#uri' => $original_uri,
     );
     $rendered_element = render($element);
-    $expected_result = '<img src="' . $url . '" alt="" />';
+    $expected_result = '<img class="image-style-image-test" src="' . $url . '" alt="" />';
     $this->assertEqual($expected_result, $rendered_element, 'theme_image_style() renders an image correctly.');
   }
 
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
index 3ba3fe6..e191eca 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php
@@ -78,6 +78,13 @@ function testNodeTypeInitialLanguageDefaults() {
     $language_field = $this->xpath('//*[@id="language"]');
     $this->assert(!empty($language_field), 'Language field is visible on manage fields tab.');
 
+    // Tests if the language field can be rearranged on the manage display tab.
+    $this->drupalGet('admin/structure/types/manage/article/display');
+    $language_display = $this->xpath('//*[@id="language"]');
+    $this->assert(!empty($language_display), 'Language field is visible on manage display tab.');
+    // Tests if the language field is hidden by default.
+    $this->assertOptionSelected('edit-fields-language-type', 'hidden', 'Language is hidden by default on manage display tab.');
+
     // Changes the inital language settings.
     $edit = array(
       'node_type_language_default' => 'en',
@@ -86,4 +93,42 @@ function testNodeTypeInitialLanguageDefaults() {
     $this->drupalGet('node/add/article');
     $this->assertOptionSelected('edit-langcode', 'en', 'The inital language is the defined language.');
   }
+
+  /**
+   * Tests Language field visibility features.
+   */
+  function testLanguageFieldVisibility() {
+    $langcode = LANGUAGE_NOT_SPECIFIED;
+
+    // Creates a node to test Language field visibility feature.
+    $edit = array(
+      'title' => $this->randomName(8),
+      "body[$langcode][0][value]" => $this->randomName(16),
+    );
+    $this->drupalPost('node/add/article', $edit, t('Save'));
+    $node = $this->drupalGetNodeByTitle($edit['title']);
+    $this->assertTrue($node, 'Node found in database.');
+
+    // Loads node page and check if Language field is hidden by default.
+    $this->drupalGet('node/' . $node->nid);
+    $language_field = $this->xpath('//div[@id=:id]/div', array(
+      ':id' => 'field-language-display',
+    ));
+    $this->assertTrue(empty($language_field), 'Language field value is not shown by default on node page.');
+
+    // Changes Language field visibility to true and check if it is saved.
+    $edit = array(
+      'fields[language][type]' => 'visible',
+    );
+    $this->drupalPost('admin/structure/types/manage/article/display', $edit, t('Save'));
+    $this->drupalGet('admin/structure/types/manage/article/display');
+    $this->assertOptionSelected('edit-fields-language-type', 'visible', 'Language field has been set to visible.');
+
+    // Loads node page and check if Language field is shown.
+    $this->drupalGet('node/' . $node->nid);
+    $language_field = $this->xpath('//div[@id=:id]/div', array(
+      ':id' => 'field-language-display',
+    ));
+    $this->assertFalse(empty($language_field), 'Language field value is shown on node page.');
+  }
 }
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 2d87534..bfba2fd 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -678,13 +678,21 @@ function node_field_extra_fields() {
 
     // Add also the 'language' select if Language module is enabled and the
     // bundle has multilingual support.
-    // Visibility of the ordering of the language selector is the same as on the node/add form,
-    // i.e. node_type_language_hidden_TYPE variable
-    if ($module_language_enabled && !variable_get('node_type_language_hidden_' . $bundle->type, TRUE)) {
-      $extra['node'][$bundle->type]['form']['language'] = array(
+    // Visibility of the ordering of the language selector is the same as on the
+    // node/add form, i.e. node_type_language_hidden_TYPE variable.
+    if ($module_language_enabled) {
+      if (!variable_get('node_type_language_hidden_' . $bundle->type, TRUE)) {
+        $extra['node'][$bundle->type]['form']['language'] = array(
+          'label' => t('Language'),
+          'description' => $description,
+          'weight' => 0,
+        );
+      }
+      $extra['node'][$bundle->type]['display']['language'] = array(
         'label' => t('Language'),
         'description' => $description,
         'weight' => 0,
+        'visible' => FALSE,
       );
     }
   }
@@ -1167,6 +1175,18 @@ function node_view(Node $node, $view_mode = 'full', $langcode = NULL) {
   // Populate $node->content with a render() array.
   node_build_content($node, $view_mode, $langcode);
 
+  // Add language text element on node view if language module is enabled.
+  if (module_exists('language')) {
+    $node->content['language'] = array(
+      '#type' => 'item',
+      '#title' => t('Language'),
+      '#markup' => language_name($langcode),
+      '#weight' => 0,
+      '#prefix' => '<div id="field-language-display">',
+      '#suffix' => '</div>'
+    );
+  }
+
   $build = $node->content;
   // We don't need duplicate rendering info in node->content.
   unset($node->content);
diff --git a/core/modules/openid/openid.module b/core/modules/openid/openid.module
index eafb0b0..4a9136e 100644
--- a/core/modules/openid/openid.module
+++ b/core/modules/openid/openid.module
@@ -481,7 +481,7 @@ function openid_discovery($claimed_id) {
 }
 
 /**
- * Implementation of hook_openid_discovery_method_info().
+ * Implements hook_openid_discovery_method_info().
  *
  * Define standard discovery methods.
  */
@@ -619,7 +619,7 @@ function _openid_xrds_discovery($claimed_id) {
 }
 
 /**
- * Implementation of hook_openid_normalization_method_info().
+ * Implements hook_openid_normalization_method_info().
  *
  * Define standard normalization methods.
  */
@@ -1067,7 +1067,7 @@ function openid_verify_assertion_return_url($service, $response) {
 /**
  * Remove expired nonces from the database.
  *
- * Implementation of hook_cron().
+ * Implements hook_cron().
  */
 function openid_cron() {
   db_delete('openid_nonce')
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index 6f17f57..095981e 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -727,7 +727,7 @@ protected function prepareEnvironment() {
     // @see config_get_config_directory()
     $GLOBALS['config_directories'] = array();
     foreach (array(CONFIG_ACTIVE_DIRECTORY, CONFIG_STAGING_DIRECTORY) as $type) {
-      $GLOBALS['config_directories'][$type] = 'simpletest/' . substr($this->databasePrefix, 10) . '/config_' . $type;
+      $GLOBALS['config_directories'][$type]['path'] = 'simpletest/' . substr($this->databasePrefix, 10) . '/config_' . $type;
     }
 
     // Reset and create a new service container.
@@ -735,11 +735,11 @@ protected function prepareEnvironment() {
 
     $this->configDirectories = array();
     include_once DRUPAL_ROOT . '/core/includes/install.inc';
-    foreach ($GLOBALS['config_directories'] as $type => $path) {
+    foreach ($GLOBALS['config_directories'] as $type => $directory) {
       if (!install_ensure_config_directory($type)) {
         return FALSE;
       }
-      $this->configDirectories[$type] = $this->originalFileDirectory . '/' . $path;
+      $this->configDirectories[$type] = $this->originalFileDirectory . '/' . $directory['path'];
     }
 
     // Unset globals.
diff --git a/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php b/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php
index d75b593..4eaa4c8 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php
@@ -52,7 +52,7 @@ public function testPluggableFramework() {
     $language_interface = language(LANGUAGE_TYPE_INTERFACE);
 
     // Use MailTestCase for sending a message.
-    $message = drupal_mail('simpletest', 'mail_test', 'testing@example.com', $language_interface);
+    $message = drupal_mail('simpletest', 'mail_test', 'testing@example.com', $language_interface->langcode);
 
     // Assert whether the message was sent through the send function.
     $this->assertEqual(self::$sent_message['to'], 'testing@example.com', t('Pluggable mail system is extendable.'));
@@ -64,13 +64,13 @@ public function testPluggableFramework() {
    * @see simpletest_mail_alter()
    */
   public function testCancelMessage() {
-    global $language;
+    $language_interface = language(LANGUAGE_TYPE_INTERFACE);
 
     // Reset the class variable holding a copy of the last sent message.
     self::$sent_message = NULL;
 
     // Send a test message that simpletest_mail_alter should cancel.
-    $message = drupal_mail('simpletest', 'cancel_test', 'cancel@example.com', $language);
+    $message = drupal_mail('simpletest', 'cancel_test', 'cancel@example.com', $language_interface->langcode);
 
     // Assert that the message was not actually sent.
     $this->assertNull(self::$sent_message, 'Message was canceled.');
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index c7343ba..efdadb4 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -1945,7 +1945,7 @@ function hook_watchdog(array $log_entry) {
     '@message'       => strip_tags($log_entry['message']),
   ));
 
-  drupal_mail('emaillog', 'entry', $to, $language_interface, $params);
+  drupal_mail('emaillog', 'entry', $to, $language_interface->langcode, $params);
 }
 
 /**
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 80ba5ad..e5dc768 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -3661,14 +3661,14 @@ function system_send_email_action($entity, $context) {
   // language.
   $recipient_account = user_load_by_mail($recipient);
   if ($recipient_account) {
-    $language = user_preferred_language($recipient_account);
+    $langcode = user_preferred_langcode($recipient_account);
   }
   else {
-    $language = language_default();
+    $langcode = language_default()->langcode;
   }
   $params = array('context' => $context);
 
-  if (drupal_mail('system', 'action_send_email', $recipient, $language, $params)) {
+  if (drupal_mail('system', 'action_send_email', $recipient, $langcode, $params)) {
     watchdog('action', 'Sent email to %recipient', array('%recipient' => $recipient));
   }
   else {
diff --git a/core/modules/update/update.fetch.inc b/core/modules/update/update.fetch.inc
index 76eeb54..a4d1bd7 100644
--- a/core/modules/update/update.fetch.inc
+++ b/core/modules/update/update.fetch.inc
@@ -366,15 +366,15 @@ function _update_cron_notify() {
   if (!empty($params)) {
     $notify_list = $update_config->get('notification.emails');
     if (!empty($notify_list)) {
-      $default_language = language_default();
+      $default_langcode = language_default()->langcode;
       foreach ($notify_list as $target) {
         if ($target_user = user_load_by_mail($target)) {
-          $target_language = user_preferred_language($target_user);
+          $target_langcode = user_preferred_langcode($target_user);
         }
         else {
-          $target_language = $default_language;
+          $target_langcode = $default_langcode;
         }
-        $message = drupal_mail('update', 'status_notify', $target, $target_language, $params);
+        $message = drupal_mail('update', 'status_notify', $target, $target_langcode, $params);
         // Track when the last mail was successfully sent to avoid sending
         // too many e-mails.
         if ($message['result']) {
diff --git a/core/modules/update/update.module b/core/modules/update/update.module
index bee906f..f9445bc 100644
--- a/core/modules/update/update.module
+++ b/core/modules/update/update.module
@@ -510,11 +510,10 @@ function _update_get_cached_available_releases() {
  * @see _update_message_text()
  */
 function update_mail($key, &$message, $params) {
-  $language = $message['language'];
-  $langcode = $language->langcode;
+  $langcode = $message['langcode'];
   $message['subject'] .= t('New release(s) available for !site_name', array('!site_name' => config('system.site')->get('name')), array('langcode' => $langcode));
   foreach ($params as $msg_type => $msg_reason) {
-    $message['body'][] = _update_message_text($msg_type, $msg_reason, FALSE, $language);
+    $message['body'][] = _update_message_text($msg_type, $msg_reason, FALSE, $langcode);
   }
   $message['body'][] = t('See the available updates page for more information:', array(), array('langcode' => $langcode)) . "\n" . url('admin/reports/updates', array('absolute' => TRUE, 'language' => $language));
   if (update_manager_access()) {
@@ -544,14 +543,13 @@ function update_mail($key, &$message, $params) {
  * @param $report_link
  *   (optional) Boolean that controls if a link to the updates report should be
  *   added. Defaults to FALSE.
- * @param $language
- *   (optional) A language object to use. Defaults to NULL.
+ * @param $langcode
+ *   (optional) A language code to use. Defaults to NULL.
  *
  * @return
  *   The properly translated error message for the given key.
  */
-function _update_message_text($msg_type, $msg_reason, $report_link = FALSE, $language = NULL) {
-  $langcode = isset($language) ? $language->langcode : NULL;
+function _update_message_text($msg_type, $msg_reason, $report_link = FALSE, $langcode = NULL) {
   $text = '';
   switch ($msg_reason) {
     case UPDATE_NOT_SECURE:
@@ -602,7 +600,12 @@ function _update_message_text($msg_type, $msg_reason, $report_link = FALSE, $lan
       }
       break;
   }
-
+  if (!empty($langcode)) {
+    $language = language_load(langcode);
+  }
+  else {
+    $language = NULL;
+  }
   if ($report_link) {
     if (update_manager_access()) {
       $text .= ' ' . t('See the <a href="@available_updates">available updates</a> page for more information and to install your missing updates.', array('@available_updates' => url('admin/reports/updates/update', array('language' => $language))), array('langcode' => $langcode));
diff --git a/core/modules/user/lib/Drupal/user/AccountFormController.php b/core/modules/user/lib/Drupal/user/AccountFormController.php
index 44acf72..a5545f4 100644
--- a/core/modules/user/lib/Drupal/user/AccountFormController.php
+++ b/core/modules/user/lib/Drupal/user/AccountFormController.php
@@ -204,9 +204,9 @@ public function form(array $form, array &$form_state, EntityInterface $account)
 
     $form['#validate'][] = 'user_validate_picture';
 
-    $user_preferred_language = $register ? $language_interface : user_preferred_language($account);
+    $user_preferred_langcode = $register ? $language_interface->langcode : user_preferred_langcode($account);
 
-    $user_preferred_admin_language = $register ? $language_interface : user_preferred_language($account, 'admin');
+    $user_preferred_admin_langcode = $register ? $language_interface->langcode : user_preferred_langcode($account, 'admin');
 
     // Is default the interface language?
     include_once DRUPAL_ROOT . '/core/includes/language.inc';
@@ -223,7 +223,7 @@ public function form(array $form, array &$form_state, EntityInterface $account)
       '#type' => 'language_select',
       '#title' => t('Site language'),
       '#languages' => LANGUAGE_CONFIGURABLE,
-      '#default_value' => $user_preferred_language->langcode,
+      '#default_value' => $user_preferred_langcode,
       '#description' => $interface_language_is_default ? t("This account's preferred language for e-mails and site presentation.") : t("This account's preferred language for e-mails."),
     );
 
@@ -231,7 +231,7 @@ public function form(array $form, array &$form_state, EntityInterface $account)
       '#type' => 'language_select',
       '#title' => t('Administration pages language'),
       '#languages' => LANGUAGE_CONFIGURABLE,
-      '#default_value' => $user_preferred_admin_language->langcode,
+      '#default_value' => $user_preferred_admin_langcode,
       '#access' => user_access('access administration pages', $account),
     );
 
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index e2a73fc..3b69966 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -1812,13 +1812,8 @@ function user_external_login_register($name, $module) {
  */
 function user_pass_reset_url($account, $options = array()) {
   $timestamp = REQUEST_TIME;
-  $url_options = array('absolute' => TRUE);
-  if (isset($options['langcode'])) {
-    $url_options['language'] = language_load($options['langcode']);
-  }
-  else {
-    $url_options['language'] = user_preferred_language($account);
-  }
+  $langcode = isset($options['langcode']) ? $options['langcode'] : user_preferred_langcode($account);
+  $url_options = array('absolute' => TRUE, 'language' => language_load($langcode));
   return url("user/reset/$account->uid/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login), $url_options);
 }
 
@@ -1845,13 +1840,8 @@ function user_pass_reset_url($account, $options = array()) {
  */
 function user_cancel_url($account, $options = array()) {
   $timestamp = REQUEST_TIME;
-  $url_options = array('absolute' => TRUE);
-  if (isset($options['langcode'])) {
-    $url_options['language'] = language_load($options['langcode']);
-  }
-  else {
-    $url_options['language'] = user_preferred_language($account);
-  }
+  $langcode = isset($options['langcode']) ? $options['langcode'] : user_preferred_langcode($account);
+  $url_options = array('absolute' => TRUE, 'language' => language_load($langcode));
   return url("user/$account->uid/cancel/confirm/$timestamp/" . user_pass_rehash($account->pass, $timestamp, $account->login), $url_options);
 }
 
@@ -2105,10 +2095,10 @@ function user_build_content($account, $view_mode = 'full', $langcode = NULL) {
  * Implements hook_mail().
  */
 function user_mail($key, &$message, $params) {
-  $language = $message['language'];
+  $langcode = $message['langcode'];
   $variables = array('user' => $params['account']);
-  $message['subject'] .= _user_mail_text($key . '.subject', $language, $variables);
-  $message['body'][] = _user_mail_text($key . '.body', $language, $variables);
+  $message['subject'] .= _user_mail_text($key . '.subject', $langcode, $variables);
+  $message['body'][] = _user_mail_text($key . '.body', $langcode, $variables);
 }
 
 /**
@@ -2116,16 +2106,15 @@ function user_mail($key, &$message, $params) {
  *
  * @param string $key
  *   The config key that provides the mail text.
- * @param object $language
- *   A language object.
+ * @param string $langcode
+ *   (optional) A language code to use to generate the e-mail text.
  * @param array $variables
- *   An array of token keys and values.
+ *   (optional) An array of token keys and values.
  *
  * @return
  *   A string value containing the text for the user.mail config key.
  */
-function _user_mail_text($key, $language = NULL, $variables = array()) {
-  $langcode = isset($language) ? $language->langcode : NULL;
+function _user_mail_text($key, $langcode = NULL, $variables = array()) {
   // We do not sanitize the token replacement, since the output of this
   // replacement is intended for an e-mail message, not a web browser.
   return token_replace(config('user.mail')->get($key), $variables, array('langcode' => $langcode, 'callback' => 'user_mail_tokens', 'sanitize' => FALSE, 'clear' => TRUE));
@@ -2795,10 +2784,10 @@ function theme_user_signature($variables) {
  *   Default to 'preferred_langcode' property.
  *   If set 'preferred_$type_langcode' is used.
  * @param $default
- *   Optional default language object to return if the account
+ *   Optional default language code to return if the account
  *   has no valid language.
  */
-function user_preferred_language($account, $type = NULL, $default = NULL) {
+function user_preferred_langcode($account, $type = NULL, $default = NULL) {
   $language_list = language_list();
   if (isset($type)) {
     $preferred_langcode = $account->{'preferred_' . $type . '_langcode'};
@@ -2807,10 +2796,10 @@ function user_preferred_language($account, $type = NULL, $default = NULL) {
     $preferred_langcode = $account->preferred_langcode;
   }
   if (!empty($preferred_langcode) && isset($language_list[$preferred_langcode])) {
-    return $language_list[$preferred_langcode];
+    return $language_list[$preferred_langcode]->langcode;
   }
   else {
-    return $default ? $default : language_default();
+    return $default ? $default : language_default()->langcode;
   }
 }
 
@@ -2837,20 +2826,21 @@ function user_preferred_language($account, $type = NULL, $default = NULL) {
  * @param $account
  *   The user object of the account being notified. Must contain at
  *   least the fields 'uid', 'name', and 'mail'.
- * @param $language
- *   Optional language to use for the notification, overriding account language.
+ * @param $langcode
+ *   Optional language code to use for the notification, overriding account
+ *   language.
  *
  * @return
  *   The return value from drupal_mail_system()->mail(), if ends up being
  *   called.
  */
-function _user_mail_notify($op, $account, $language = NULL) {
+function _user_mail_notify($op, $account, $langcode = NULL) {
   // By default, we always notify except for canceled and blocked.
   $notify = config('user.settings')->get('notify.' . $op);
   if ($notify || ($op != 'status_canceled' && $op != 'status_blocked')) {
     $params['account'] = $account;
-    $language = $language ? $language : user_preferred_language($account);
-    $mail = drupal_mail('user', $op, $account->mail, $language, $params);
+    $langcode = $langcode ? $langcode : user_preferred_langcode($account);
+    $mail = drupal_mail('user', $op, $account->mail, $langcode, $params);
     if ($op == 'register_pending_approval') {
       // If a user registered requiring admin approval, notify the admin, too.
       // We use the site default language for this.
@@ -2858,7 +2848,7 @@ function _user_mail_notify($op, $account, $language = NULL) {
       if (empty($site_mail)) {
         $site_mail = ini_get('sendmail_from');
       }
-      drupal_mail('user', 'register_pending_approval_admin', $site_mail, language_default(), $params);
+      drupal_mail('user', 'register_pending_approval_admin', $site_mail, language_default()->langcode, $params);
     }
   }
   return empty($mail) ? NULL : $mail['result'];
diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc
index d26ca6d..9dd2cc9 100644
--- a/core/modules/user/user.pages.inc
+++ b/core/modules/user/user.pages.inc
@@ -81,7 +81,7 @@ function user_pass_submit($form, &$form_state) {
 
   $account = $form_state['values']['account'];
   // Mail one time login URL and instructions using current language.
-  $mail = _user_mail_notify('password_reset', $account, $language_interface);
+  $mail = _user_mail_notify('password_reset', $account, $language_interface->langcode);
   if (!empty($mail)) {
     watchdog('user', 'Password reset instructions mailed to %name at %email.', array('%name' => $account->name, '%email' => $account->mail));
     drupal_set_message(t('Further instructions have been sent to your e-mail address.'));
diff --git a/sites/default/default.settings.php b/sites/default/default.settings.php
index 7010b6a..8e95dba 100755
--- a/sites/default/default.settings.php
+++ b/sites/default/default.settings.php
@@ -259,8 +259,14 @@
  * Example:
  * @code
  *   $config_directories = array(
- *     CONFIG_ACTIVE_DIRECTORY => '/some/directory/outside/webroot',
- *     CONFIG_STAGING_DIRECTORY => '/another/directory/outside/webroot',
+ *     CONFIG_ACTIVE_DIRECTORY => array(
+ *       'path' => '/some/directory/outside/webroot',
+ *       'absolute' => TRUE,
+ *     ),
+ *     CONFIG_STAGING_DIRECTORY => array(
+ *       'path' => '/another/directory/outside/webroot',
+ *       'absolute' => TRUE,
+ *     ),
  *   );
  * @endcode
  */
