diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index b667d89..758a289 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -1,9 +1,12 @@
 <?php
 
 use Drupal\Core\Database\Database;
+use Drupal\Core\DependencyInjection\BootstrapContainer;
 use Symfony\Component\ClassLoader\UniversalClassLoader;
 use Symfony\Component\ClassLoader\ApcUniversalClassLoader;
-use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
 use Symfony\Component\HttpFoundation\Request;
 use Drupal\Core\Language\Language;
 
@@ -1473,7 +1476,7 @@ function t($string, array $args = array(), array $options = array()) {
 
   // Merge in default.
   if (empty($options['langcode'])) {
-    $options['langcode'] = drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode;
+    $options['langcode'] = language_manager(LANGUAGE_TYPE_INTERFACE)->langcode;
   }
   if (empty($options['context'])) {
     $options['context'] = '';
@@ -1628,29 +1631,6 @@ function request_uri($omit_query_string = FALSE) {
 }
 
 /**
- * Returns the current global request object.
- *
- * @todo Replace this function with a proper dependency injection container.
- *
- * @staticvar Symfony\Component\HttpFoundation\Request $request
- *
- * @param Symfony\Component\HttpFoundation\Request $new_request
- *   Optional. The new request object to store. This parameter should only be
- *   used by index.php.
- *
- * @return Symfony\Component\HttpFoundation\Request
- *   The current request object.
- */
-function request(Request $new_request = NULL) {
-  static $request;
-
-  if ($new_request) {
-    $request = $new_request;
-  }
-  return $request;
-}
-
-/**
  * Logs an exception.
  *
  * This is a wrapper function for watchdog() which automatically decodes an
@@ -1764,37 +1744,22 @@ function watchdog($type, $message, $variables = array(), $severity = WATCHDOG_NO
 }
 
 /**
- * Sets a message to display to the user.
+ * Sets a message which reflects the status of the performed operation.
  *
- * Messages are stored in a session variable and displayed in page.tpl.php via
- * the $messages theme variable.
+ * If the function is called with no arguments, this function returns all set
+ * messages without clearing them.
  *
- * Example usage:
- * @code
- * drupal_set_message(t('An error occurred and processing did not complete.'), 'error');
- * @endcode
- *
- * @param string $message
- *   (optional) The translated message to be displayed to the user. For
- *   consistency with other messages, it should begin with a capital letter and
- *   end with a period.
- * @param string $type
- *   (optional) The message's type. Defaults to 'status'. These values are
- *   supported:
+ * @param $message
+ *   The message to be displayed to the user. For consistency with other
+ *   messages, it should begin with a capital letter and end with a period.
+ * @param $type
+ *   The type of the message. One of the following values are possible:
  *   - 'status'
  *   - 'warning'
  *   - 'error'
- * @param bool $repeat
- *   (optional) If this is FALSE and the message is already set, then the
- *   message won't be repeated. Defaults to TRUE.
- *
- * @return array|null
- *   A multidimensional array with keys corresponding to the set message types.
- *   The indexed array values of each contain the set messages for that type.
- *   Or, if there are no messages set, the function returns NULL.
- *
- * @see drupal_get_messages()
- * @see theme_status_messages()
+ * @param $repeat
+ *   If this is FALSE and the message is already set, then the message won't
+ *   be repeated.
  */
 function drupal_set_message($message = NULL, $type = 'status', $repeat = TRUE) {
   if ($message) {
@@ -2455,28 +2420,23 @@ function drupal_get_bootstrap_phase() {
 /**
  * Retrieves the Drupal Container to standardize object construction.
  *
- * Example:
- * @code
- * // Register the LANGUAGE_TYPE_INTERFACE definition. Registered definitions
- * // do not necessarily need to be named by a constant.
- * // See 
- * // http://symfony.com/doc/current/components/dependency_injection/introduction.html
- * // for usage examples of adding object initialization code after register().
- * $container = drupal_container();
- * $container->register(LANGUAGE_TYPE_INTERFACE, 'Drupal\\Core\\Language\\Language');
- *
- * // Retrieve the LANGUAGE_TYPE_INTERFACE object.
- * $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
- * @endcode
+ * On a normal page request the container is built by the kernel and passed in
+ * to this function which stores it statically. Any full bootstrap outside of
+ * the context of a page request will require a container with a minimal set of
+ * services. If this function is called without the $reset parameter, and no
+ * container object has been statically cached, it builds this minimal container,
+ * registering the services that are required.
+ *
+ * @see Drupal\Core\DrupalKernel
  *
  * @param $reset
  *   A new container instance to reset the Drupal container to.
  *
- * @return Drupal\Component\DependencyInjection\ContainerBuilder
- *   The instance of the Drupal Container used to set up and maintain object
+ * @return Symfony\Component\DependencyInjection\Container
+ *   The instance of the Container used to set up and maintain object
  *   instances.
  */
-function drupal_container(ContainerBuilder $reset = NULL) {
+function drupal_container(Container $reset = NULL) {
   // We do not use drupal_static() here because we do not have a mechanism by
   // which to reinitialize the stored objects, so a drupal_static_reset() call
   // would leave Drupal in a nonfunctional state.
@@ -2485,7 +2445,9 @@ function drupal_container(ContainerBuilder $reset = NULL) {
     $container = $reset;
   }
   elseif (!isset($container)) {
-    $container = new ContainerBuilder();
+    // Return a ContainerBuilder instance with the bare essentials needed for any
+    // full bootstrap regardless of whether there will be a DrupalKernel involved.
+    $container = new BootstrapContainer();
   }
   return $container;
 }
@@ -2633,34 +2595,67 @@ function get_t() {
 /**
  * Initializes all the defined language types.
  *
- * @see Drupal\Core\Language\Language
+ * @see language_manager()
  */
 function drupal_language_initialize() {
-  $types = language_types_get_all();
-  $container = drupal_container();
-
-  // Ensure a language object is registered for each language type, whether the
-  // site is multilingual or not.
   if (language_multilingual()) {
-    include_once DRUPAL_ROOT . '/core/includes/language.inc';
+    $types = language_types_get_all();
     foreach ($types as $type) {
-      $language = language_types_initialize($type);
-      $container->set($type, NULL);
-      $container->register($type, 'Drupal\\Core\\Language\\Language')
-        ->addMethodCall('extend', array($language));
+      language_manager($type);
     }
     // Allow modules to react on language system initialization in multilingual
     // environments.
     bootstrap_invoke_all('language_init');
   }
-  else {
-    $default = language_default();
-    foreach ($types as $type) {
-      $container->set($type, NULL);
-      $container->register($type, 'Drupal\\Core\\Language\\Language')
-        ->addMethodCall('extend', array($default));
+}
+
+/**
+ * Initializes the passed in language type.
+ *
+ * The 'language_manager' service is only available within the scope of a kernel
+ * request. When it's not available, we return a default language object,
+ * regardless of the type passed in.
+ *
+ * Note that this function is provided for legacy code that needs to get e.g.
+ * the interface language outside the scope of a request. Code that runs within
+ * the scope of a request should call
+ * drupal_container()->get('language_manager')->getLanguage($type)
+ * directly.
+ *
+ * @see Drupal\Core\Language\LanguageManager
+ */
+function language_manager($type = NULL) {
+  // Keep track of whether we are in a multilingual environment.
+  static $multilingual = FALSE;
+  // Keep track of whether the language_manager service is available.
+  static $language_manager_service = FALSE;
+  if ($multilingual && $language_manager_service) {
+    if (!$type) {
+      drupal_container()->get('language_manager')->reset();
+      return;
     }
+    return drupal_container()->get('language_manager')->getLanguage($type);
+  }
+  if (language_multilingual()) {
+    $multilingual = TRUE;
+    if (drupal_container()->has('language_manager')) {
+      $language_manager_service = TRUE;
+      return drupal_container()->get('language_manager')->getLanguage($type);
+    }
+  }
+  // We can't use drupal_static() here because resetting is not a simple case of
+  // drupal_static_reset().
+  static $languages;
+  // If no type was passed in, reset the languages array.
+  if (!$type) {
+    $languages = array();
+  }
+  // If this is not a multilingual environment or we have not yet entered the
+  // request scope, just use the default language regardless of $type.
+  if (!isset($languages[$type])) {
+    $languages[$type] = language_default();
   }
+  return $languages[$type];
 }
 
 /**
diff --git a/core/includes/common.inc b/core/includes/common.inc
index f2a4003..fb0e731 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -1597,7 +1597,7 @@ function filter_xss_bad_protocol($string, $decode = TRUE) {
  * Arbitrary elements may be added using the $args associative array.
  */
 function format_rss_channel($title, $link, $description, $items, $langcode = NULL, $args = array()) {
-  $langcode = $langcode ? $langcode : drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode;
+  $langcode = $langcode ? $langcode : language_manager(LANGUAGE_TYPE_CONTENT)->langcode;
 
   $output = "<channel>\n";
   $output .= ' <title>' . check_plain($title) . "</title>\n";
@@ -1899,7 +1899,7 @@ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NUL
   }
 
   if (empty($langcode)) {
-    $langcode = drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode;
+    $langcode = language_manager(LANGUAGE_TYPE_INTERFACE)->langcode;
   }
 
   switch ($type) {
@@ -2075,7 +2075,7 @@ function _format_date_callback(array $matches = NULL, $new_langcode = NULL) {
  *   - 'language': An optional language object. If the path being linked to is
  *     internal to the site, $options['language'] is used to look up the alias
  *     for the URL. If $options['language'] is omitted, the language will be
- *     obtained from drupal_container()->get(LANGUAGE_TYPE_URL).
+ *     obtained from language_manager(LANGUAGE_TYPE_URL).
  *   - 'https': Whether this URL should point to a secure location. If not
  *     defined, the current scheme is used, so the user stays on http or https
  *     respectively. TRUE enforces HTTPS and FALSE enforces HTTP, but HTTPS can
@@ -2324,7 +2324,7 @@ function l($text, $path, array $options = array()) {
 
   // Append active class.
   if (($path == current_path() || ($path == '<front>' && drupal_is_front_page())) &&
-      (empty($options['language']) || $options['language']->langcode == drupal_container()->get(LANGUAGE_TYPE_URL)->langcode)) {
+      (empty($options['language']) || $options['language']->langcode == language_manager(LANGUAGE_TYPE_URL)->langcode)) {
     $options['attributes']['class'][] = 'active';
   }
 
@@ -4914,9 +4914,9 @@ function _drupal_bootstrap_code() {
 }
 
 /**
- * Temporary BC function for scripts not using HttpKernel.
+ * Temporary BC function for scripts not using DrupalKernel.
  *
- * HttpKernel skips this and replicates it via event listeners.
+ * DrupalKernel skips this and replicates it via event listeners.
  *
  * @see Drupal\Core\EventSubscriber\PathSubscriber;
  * @see Drupal\Core\EventSubscriber\LegacyRequestSubscriber;
@@ -6012,7 +6012,7 @@ function drupal_render_cid_parts($granularity = NULL) {
   // part.
   if (language_multilingual()) {
     foreach (language_types_get_configurable() as $language_type) {
-      $cid_parts[] = drupal_container()->get($language_type)->langcode;
+      $cid_parts[] = language_manager($language_type)->langcode;
     }
   }
 
diff --git a/core/includes/form.inc b/core/includes/form.inc
index 6a747b6..2610ac0 100644
--- a/core/includes/form.inc
+++ b/core/includes/form.inc
@@ -1267,7 +1267,7 @@ function drupal_redirect_form($form_state) {
         $function($form_state['redirect']);
       }
     }
-    drupal_goto(current_path(), array('query' => request()->query->all()));
+    drupal_goto(current_path(), array('query' => drupal_container()->get('request')->query->all()));
   }
 }
 
diff --git a/core/includes/gettext.inc b/core/includes/gettext.inc
new file mode 100644
index 0000000..ef9d25d
--- /dev/null
+++ b/core/includes/gettext.inc
@@ -0,0 +1,1131 @@
+<?php
+
+/**
+ * @file
+ * Gettext parsing and generating API.
+ *
+ * @todo Decouple these functions from Locale API and put to gettext_ namespace.
+ */
+
+/**
+ * @defgroup locale-api-import-export Translation import/export API.
+ * @{
+ * Functions to import and export translations.
+ *
+ * These functions provide the ability to import translations from
+ * external files and to export translations and translation templates.
+ */
+
+/**
+ * Parses Gettext Portable Object information and inserts it into the database.
+ *
+ * @param $file
+ *   Drupal file object corresponding to the PO file to import.
+ * @param $langcode
+ *   Language code.
+ * @param $overwrite_options
+ *   An associative array indicating what data should be overwritten, if any.
+ *   - not_customized: strings marked not customized should be overwritten.
+ *   - customized: strings marked customized should be overwritten.
+ * @param $customized
+ *   Whether the strings being imported should be saved as customized.
+ *   Use LOCALE_CUSTOMIZED or LOCALE_NOT_CUSTOMIZED. All strings in the file
+ *   will be saved with this customization flag.
+ */
+function _locale_import_po($file, $langcode, $overwrite_options, $customized = LOCALE_NOT_CUSTOMIZED) {
+  // Try to allocate enough time to parse and import the data.
+  drupal_set_time_limit(240);
+
+  // Check if we have the language already in the database.
+  if (!language_load($langcode)) {
+    drupal_set_message(t('The language selected for import is not supported.'), 'error');
+    return FALSE;
+  }
+
+  // Get strings from file (returns on failure after a partial import, or on success)
+  $status = _locale_import_read_po('db-store', $file, $overwrite_options, $langcode, $customized);
+  if ($status === FALSE) {
+    // Error messages are set in _locale_import_read_po().
+    return FALSE;
+  }
+
+  // Get status information on import process.
+  list($header_done, $additions, $updates, $deletes, $skips) = _locale_import_one_string('db-report');
+
+  if (!$header_done) {
+    drupal_set_message(t('The translation file %filename appears to have a missing or malformed header.', array('%filename' => $file->filename)), 'error');
+  }
+
+  // Clear cache and force refresh of JavaScript translations.
+  _locale_invalidate_js($langcode);
+  cache()->deletePrefix('locale:');
+
+  // Rebuild the menu, strings may have changed.
+  menu_router_rebuild();
+
+  drupal_set_message(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => $additions, '%update' => $updates, '%delete' => $deletes)));
+  watchdog('locale', 'Imported %file into %locale: %number new strings added, %update updated and %delete removed.', array('%file' => $file->filename, '%locale' => $langcode, '%number' => $additions, '%update' => $updates, '%delete' => $deletes));
+  if ($skips) {
+    if (module_exists('dblog')) {
+      $skip_message = format_plural($skips, 'A translation string was skipped because of disallowed or malformed HTML. <a href="@url">See the log</a> for details.', '@count translation strings were skipped because of disallowed or malformed HTML. <a href="@url">See the log</a> for details.', array('@url' => url('admin/reports/dblog')));
+    }
+    else {
+      $skip_message = format_plural($skips, 'A translation string was skipped because of disallowed or malformed HTML. See the log for details.', '@count translation strings were skipped because of disallowed or malformed HTML. See the log for details.');
+    }
+    drupal_set_message($skip_message, 'error');
+    watchdog('locale', '@count disallowed HTML string(s) in %file', array('@count' => $skips, '%file' => $file->uri), WATCHDOG_WARNING);
+  }
+  return TRUE;
+}
+
+/**
+ * Parses a Gettext Portable Object file into an array.
+ *
+ * @param $op
+ *   Storage operation type: db-store or mem-store.
+ * @param $file
+ *   Drupal file object corresponding to the PO file to import.
+ * @param $overwrite_options
+ *   An associative array indicating what data should be overwritten, if any.
+ *   - not_customized: not customized strings should be overwritten.
+ *   - customized: customized strings should be overwritten.
+ * @param $lang
+ *   Language code.
+ * @param $customized
+ *   Whether the strings being imported should be saved as customized.
+ *   Use LOCALE_CUSTOMIZED or LOCALE_NOT_CUSTOMIZED.
+ */
+function _locale_import_read_po($op, $file, $overwrite_options = NULL, $lang = NULL, $customized = LOCALE_NOT_CUSTOMIZED) {
+
+  // The file will get closed by PHP on returning from this function.
+  $fd = fopen($file->uri, 'rb');
+  if (!$fd) {
+    _locale_import_message('The translation import failed because the file %filename could not be read.', $file);
+    return FALSE;
+  }
+
+  /*
+   * The parser context. Can be:
+   *  - 'COMMENT' (#)
+   *  - 'MSGID' (msgid)
+   *  - 'MSGID_PLURAL' (msgid_plural)
+   *  - 'MSGCTXT' (msgctxt)
+   *  - 'MSGSTR' (msgstr or msgstr[])
+   *  - 'MSGSTR_ARR' (msgstr_arg)
+   */
+  $context = 'COMMENT';
+
+  // Current entry being read.
+  $current = array();
+
+  // Current plurality for 'msgstr[]'.
+  $plural = 0;
+
+  // Current line.
+  $lineno = 0;
+
+  while (!feof($fd)) {
+    // A line should not be longer than 10 * 1024.
+    $line = fgets($fd, 10 * 1024);
+
+    if ($lineno == 0) {
+      // The first line might come with a UTF-8 BOM, which should be removed.
+      $line = str_replace("\xEF\xBB\xBF", '', $line);
+    }
+
+    $lineno++;
+
+    // Trim away the linefeed.
+    $line = trim(strtr($line, array("\\\n" => "")));
+
+    if (!strncmp('#', $line, 1)) {
+      // Lines starting with '#' are comments.
+
+      if ($context == 'COMMENT') {
+        // Already in comment token, insert the comment.
+        $current['#'][] = substr($line, 1);
+      }
+      elseif (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) {
+        // We are currently in string token, close it out.
+        _locale_import_one_string($op, $current, $overwrite_options, $lang, $file, $customized);
+
+        // Start a new entry for the comment.
+        $current         = array();
+        $current['#'][]  = substr($line, 1);
+
+        $context = 'COMMENT';
+      }
+      else {
+        // A comment following any other token is a syntax error.
+        _locale_import_message('The translation file %filename contains an error: "msgstr" was expected but not found on line %line.', $file, $lineno);
+        return FALSE;
+      }
+    }
+    elseif (!strncmp('msgid_plural', $line, 12)) {
+      // A plural form for the current message.
+
+      if ($context != 'MSGID') {
+        // A plural form cannot be added to anything else but the id directly.
+        _locale_import_message('The translation file %filename contains an error: "msgid_plural" was expected but not found on line %line.', $file, $lineno);
+        return FALSE;
+      }
+
+      // Remove 'msgid_plural' and trim away whitespace.
+      $line = trim(substr($line, 12));
+      // At this point, $line should now contain only the plural form.
+
+      $quoted = _locale_import_parse_quoted($line);
+      if ($quoted === FALSE) {
+        // The plural form must be wrapped in quotes.
+        _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
+        return FALSE;
+      }
+
+      // Append the plural form to the current entry.
+      $current['msgid'] .= LOCALE_PLURAL_DELIMITER . $quoted;
+
+      $context = 'MSGID_PLURAL';
+    }
+    elseif (!strncmp('msgid', $line, 5)) {
+      // Starting a new message.
+
+      if (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) {
+        // We are currently in a message string, close it out.
+        _locale_import_one_string($op, $current, $overwrite_options, $lang, $file, $customized);
+
+        // Start a new context for the id.
+        $current = array();
+      }
+      elseif ($context == 'MSGID') {
+        // We are currently already in the context, meaning we passed an id with no data.
+        _locale_import_message('The translation file %filename contains an error: "msgid" is unexpected on line %line.', $file, $lineno);
+        return FALSE;
+      }
+
+      // Remove 'msgid' and trim away whitespace.
+      $line = trim(substr($line, 5));
+      // At this point, $line should now contain only the message id.
+
+      $quoted = _locale_import_parse_quoted($line);
+      if ($quoted === FALSE) {
+        // The message id must be wrapped in quotes.
+        _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
+        return FALSE;
+      }
+
+      $current['msgid'] = $quoted;
+      $context = 'MSGID';
+    }
+    elseif (!strncmp('msgctxt', $line, 7)) {
+      // Starting a new context.
+
+      if (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) {
+        // We are currently in a message, start a new one.
+        _locale_import_one_string($op, $current, $overwrite_options, $lang, $file, $customized);
+        $current = array();
+      }
+      elseif (!empty($current['msgctxt'])) {
+        // A context cannot apply to another context.
+        _locale_import_message('The translation file %filename contains an error: "msgctxt" is unexpected on line %line.', $file, $lineno);
+        return FALSE;
+      }
+
+      // Remove 'msgctxt' and trim away whitespaces.
+      $line = trim(substr($line, 7));
+      // At this point, $line should now contain the context.
+
+      $quoted = _locale_import_parse_quoted($line);
+      if ($quoted === FALSE) {
+        // The context string must be quoted.
+        _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
+        return FALSE;
+      }
+
+      $current['msgctxt'] = $quoted;
+
+      $context = 'MSGCTXT';
+    }
+    elseif (!strncmp('msgstr[', $line, 7)) {
+      // A message string for a specific plurality.
+
+      if (($context != 'MSGID') && ($context != 'MSGCTXT') && ($context != 'MSGID_PLURAL') && ($context != 'MSGSTR_ARR')) {
+        // Message strings must come after msgid, msgxtxt, msgid_plural, or other msgstr[] entries.
+        _locale_import_message('The translation file %filename contains an error: "msgstr[]" is unexpected on line %line.', $file, $lineno);
+        return FALSE;
+      }
+
+      // Ensure the plurality is terminated.
+      if (strpos($line, ']') === FALSE) {
+        _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
+        return FALSE;
+      }
+
+      // Extract the plurality.
+      $frombracket = strstr($line, '[');
+      $plural = substr($frombracket, 1, strpos($frombracket, ']') - 1);
+
+      // Skip to the next whitespace and trim away any further whitespace, bringing $line to the message data.
+      $line = trim(strstr($line, " "));
+
+      $quoted = _locale_import_parse_quoted($line);
+      if ($quoted === FALSE) {
+        // The string must be quoted.
+        _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
+        return FALSE;
+      }
+
+      $current['msgstr'][$plural] = $quoted;
+
+      $context = 'MSGSTR_ARR';
+    }
+    elseif (!strncmp("msgstr", $line, 6)) {
+      // A string for the an id or context.
+
+      if (($context != 'MSGID') && ($context != 'MSGCTXT')) {
+        // Strings are only valid within an id or context scope.
+        _locale_import_message('The translation file %filename contains an error: "msgstr" is unexpected on line %line.', $file, $lineno);
+        return FALSE;
+      }
+
+      // Remove 'msgstr' and trim away away whitespaces.
+      $line = trim(substr($line, 6));
+      // At this point, $line should now contain the message.
+
+      $quoted = _locale_import_parse_quoted($line);
+      if ($quoted === FALSE) {
+        // The string must be quoted.
+        _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
+        return FALSE;
+      }
+
+      $current['msgstr'] = $quoted;
+
+      $context = 'MSGSTR';
+    }
+    elseif ($line != '') {
+      // Anything that is not a token may be a continuation of a previous token.
+
+      $quoted = _locale_import_parse_quoted($line);
+      if ($quoted === FALSE) {
+        // The string must be quoted.
+        _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno);
+        return FALSE;
+      }
+
+      // Append the string to the current context.
+      if (($context == 'MSGID') || ($context == 'MSGID_PLURAL')) {
+        $current['msgid'] .= $quoted;
+      }
+      elseif ($context == 'MSGCTXT') {
+        $current['msgctxt'] .= $quoted;
+      }
+      elseif ($context == 'MSGSTR') {
+        $current['msgstr'] .= $quoted;
+      }
+      elseif ($context == 'MSGSTR_ARR') {
+        $current['msgstr'][$plural] .= $quoted;
+      }
+      else {
+        // No valid context to append to.
+        _locale_import_message('The translation file %filename contains an error: there is an unexpected string on line %line.', $file, $lineno);
+        return FALSE;
+      }
+    }
+  }
+
+  // End of PO file, closed out the last entry.
+  if (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) {
+    _locale_import_one_string($op, $current, $overwrite_options, $lang, $file, $customized);
+  }
+  elseif ($context != 'COMMENT') {
+    _locale_import_message('The translation file %filename ended unexpectedly at line %line.', $file, $lineno);
+    return FALSE;
+  }
+}
+
+/**
+ * Sets an error message if an error occurred during locale file parsing.
+ *
+ * @param $message
+ *   The message to be translated.
+ * @param $file
+ *   Drupal file object corresponding to the PO file to import.
+ * @param $lineno
+ *   An optional line number argument.
+ */
+function _locale_import_message($message, $file, $lineno = NULL) {
+  $vars = array('%filename' => $file->filename);
+  if (isset($lineno)) {
+    $vars['%line'] = $lineno;
+  }
+  $t = get_t();
+  drupal_set_message($t($message, $vars), 'error');
+}
+
+/**
+ * Performs the specified operation for one string.
+ *
+ * @param $op
+ *   Operation to perform: 'db-store', 'db-report', 'mem-store' or 'mem-report'.
+ * @param $value
+ *   Details of the string stored.
+ * @param $overwrite_options
+ *   An associative array indicating what data should be overwritten, if any.
+ *   - not_customized: not customized strings should be overwritten.
+ *   - customized: customized strings should be overwritten.
+ * @param $lang
+ *   Language to store the string in.
+ * @param $file
+ *   Object representation of file being imported, only required when op is
+ *   'db-store'.
+ * @param $customized
+ *   Whether the strings being imported should be saved as customized.
+ *   Use LOCALE_CUSTOMIZED or LOCALE_NOT_CUSTOMIZED.
+ */
+function _locale_import_one_string($op, $value = NULL, $overwrite_options = NULL, $lang = NULL, $file = NULL, $customized = LOCALE_NOT_CUSTOMIZED) {
+  $report = &drupal_static(__FUNCTION__, array('additions' => 0, 'updates' => 0, 'deletes' => 0, 'skips' => 0));
+  $header_done = &drupal_static(__FUNCTION__ . ':header_done', FALSE);
+  $strings = &drupal_static(__FUNCTION__ . ':strings', array());
+
+  switch ($op) {
+    // Return stored strings
+    case 'mem-report':
+      return $strings;
+
+    // Store string in memory (only supports single strings)
+    case 'mem-store':
+      $strings[isset($value['msgctxt']) ? $value['msgctxt'] : ''][$value['msgid']] = $value['msgstr'];
+      return;
+
+    // Called at end of import to inform the user
+    case 'db-report':
+      return array($header_done, $report['additions'], $report['updates'], $report['deletes'], $report['skips']);
+
+    // Store the string we got in the database.
+    case 'db-store':
+
+      if ($value['msgid'] == '') {
+        // If 'msgid' is empty, it means we got values for the header of the
+        // file as per the structure of the Gettext format.
+        $locale_plurals = variable_get('locale_translation_plurals', array());
+        if (array_sum($overwrite_options) || empty($locale_plurals[$lang]['plurals'])) {
+          // Since we only need to parse the header if we ought to update the
+          // plural formula, only run this if we don't need to keep existing
+          // data untouched or if we don't have an existing plural formula.
+          $header = _locale_import_parse_header($value['msgstr']);
+
+          // Get and store the plural formula if available.
+          if (isset($header["Plural-Forms"]) && $p = _locale_import_parse_plural_forms($header["Plural-Forms"], $file->uri)) {
+            list($nplurals, $formula) = $p;
+            $locale_plurals[$lang] = array(
+              'plurals' => $nplurals,
+              'formula' => $formula,
+            );
+            variable_set('locale_translation_plurals', $locale_plurals);
+          }
+        }
+        $header_done = TRUE;
+      }
+
+      else {
+        // Found a string to store, clean up and prepare the data.
+        $comments = _locale_import_shorten_comments(empty($value['#']) ? array() : $value['#']);
+
+        if (is_array($value['msgstr'])) {
+          // Sort plural variants by their form index.
+          ksort($value['msgstr']);
+          // Serialize plural variants in one string by LOCALE_PLURAL_DELIMITER.
+          $value['msgstr'] = implode(LOCALE_PLURAL_DELIMITER, $value['msgstr']);
+        }
+
+        _locale_import_one_string_db(
+          $report,
+          $lang,
+          isset($value['msgctxt']) ? $value['msgctxt'] : '',
+          $value['msgid'],
+          $value['msgstr'],
+          $comments,
+          $overwrite_options,
+          $customized
+        );
+      }
+  } // end of db-store operation
+}
+
+/**
+ * Imports one string into the database.
+ *
+ * @param $report
+ *   Report array summarizing the number of changes done in the form:
+ *   array(inserts, updates, deletes).
+ * @param $langcode
+ *   Language code to import string into.
+ * @param $context
+ *   The context of this string.
+ * @param $source
+ *   Source string.
+ * @param $translation
+ *   Translation to language specified in $langcode.
+ * @param $location
+ *   Location value to save with source string.
+ * @param $overwrite_options
+ *   An associative array indicating what data should be overwritten, if any.
+ *   - not_customized: not customized strings should be overwritten.
+ *   - customized: customized strings should be overwritten.
+ * @param $customized
+ *   (optional) Whether the strings being imported should be saved as customized.
+ *   Use LOCALE_CUSTOMIZED or LOCALE_NOT_CUSTOMIZED.
+ *
+ * @return
+ *   The string ID of the existing string modified or the new string added.
+ */
+function _locale_import_one_string_db(&$report, $langcode, $context, $source, $translation, $location, $overwrite_options, $customized = LOCALE_NOT_CUSTOMIZED) {
+
+  // Initialize overwrite options if not set.
+  $overwrite_options += array(
+    'not_customized' => FALSE,
+    'customized' => FALSE,
+  );
+
+  // Look up the source string and any existing translation.
+  $string = db_query("SELECT s.lid, t.customized FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.source = :source AND s.context = :context", array(
+    ':source' => $source,
+    ':context' => $context,
+    ':language' => $langcode,
+    ))
+    ->fetchObject();
+
+  if (!empty($translation)) {
+    // Skip this string unless it passes a check for dangerous code.
+    if (!locale_string_is_safe($translation)) {
+      watchdog('locale', 'Import of string "%string" was skipped because of disallowed or malformed HTML.', array('%string' => $translation), WATCHDOG_ERROR);
+      $report['skips']++;
+      return 0;
+    }
+    elseif (isset($string->lid)) {
+      // We have this source string saved already.
+      db_update('locales_source')
+        ->fields(array(
+          'location' => $location,
+        ))
+        ->condition('lid', $string->lid)
+        ->execute();
+
+      if (!isset($string->customized)) {
+        // No translation in this language.
+        db_insert('locales_target')
+          ->fields(array(
+            'lid' => $string->lid,
+            'language' => $langcode,
+            'translation' => $translation,
+            'customized' => $customized,
+          ))
+          ->execute();
+
+        $report['additions']++;
+      }
+      elseif ($overwrite_options[$string->customized ? 'customized' : 'not_customized']) {
+        // Translation exists, only overwrite if instructed.
+        db_update('locales_target')
+          ->fields(array(
+            'translation' => $translation,
+            'customized' => $customized,
+          ))
+          ->condition('language', $langcode)
+          ->condition('lid', $string->lid)
+          ->execute();
+
+        $report['updates']++;
+      }
+      return $string->lid;
+    }
+    else {
+      // No such source string in the database yet.
+      $lid = db_insert('locales_source')
+        ->fields(array(
+          'location' => $location,
+          'source' => $source,
+          'context' => (string) $context,
+        ))
+        ->execute();
+
+      db_insert('locales_target')
+        ->fields(array(
+           'lid' => $lid,
+           'language' => $langcode,
+           'translation' => $translation,
+           'customized' => $customized,
+        ))
+        ->execute();
+
+      $report['additions']++;
+      return $lid;
+    }
+  }
+  elseif (isset($string->lid) && isset($string->customized) && $overwrite_options[$string->customized ? 'customized' : 'not_customized']) {
+    // Empty translation, remove existing if instructed.
+    db_delete('locales_target')
+      ->condition('language', $langcode)
+      ->condition('lid', $string->lid)
+      ->execute();
+
+    $report['deletes']++;
+    return $string->lid;
+  }
+}
+
+/**
+ * Parses a Gettext Portable Object file header.
+ *
+ * @param $header
+ *   A string containing the complete header.
+ *
+ * @return
+ *   An associative array of key-value pairs.
+ */
+function _locale_import_parse_header($header) {
+  $header_parsed = array();
+  $lines = array_map('trim', explode("\n", $header));
+  foreach ($lines as $line) {
+    if ($line) {
+      list($tag, $contents) = explode(":", $line, 2);
+      $header_parsed[trim($tag)] = trim($contents);
+    }
+  }
+  return $header_parsed;
+}
+
+/**
+ * Parses a Plural-Forms entry from a Gettext Portable Object file header.
+ *
+ * @param $pluralforms
+ *   A string containing the Plural-Forms entry.
+ * @param $filepath
+ *   A string containing the filepath.
+ *
+ * @return
+ *   An array containing the number of plurals and a
+ *   formula in PHP for computing the plural form.
+ */
+function _locale_import_parse_plural_forms($pluralforms, $filepath) {
+  // First, delete all whitespace
+  $pluralforms = strtr($pluralforms, array(" " => "", "\t" => ""));
+
+  // Select the parts that define nplurals and plural
+  $nplurals = strstr($pluralforms, "nplurals=");
+  if (strpos($nplurals, ";")) {
+    $nplurals = substr($nplurals, 9, strpos($nplurals, ";") - 9);
+  }
+  else {
+    return FALSE;
+  }
+  $plural = strstr($pluralforms, "plural=");
+  if (strpos($plural, ";")) {
+    $plural = substr($plural, 7, strpos($plural, ";") - 7);
+  }
+  else {
+    return FALSE;
+  }
+
+  // Get PHP version of the plural formula
+  $plural = _locale_import_parse_arithmetic($plural);
+
+  if ($plural !== FALSE) {
+    return array($nplurals, $plural);
+  }
+  else {
+    drupal_set_message(t('The translation file %filepath contains an error: the plural formula could not be parsed.', array('%filepath' => $filepath)), 'error');
+    return FALSE;
+  }
+}
+
+/**
+ * Parses and sanitizes an arithmetic formula into a PHP expression.
+ *
+ * While parsing, we ensure, that the operators have the right
+ * precedence and associativity.
+ *
+ * @param $string
+ *   A string containing the arithmetic formula.
+ *
+ * @return
+ *   The PHP version of the formula.
+ */
+function _locale_import_parse_arithmetic($string) {
+  // Operator precedence table
+  $precedence = array("(" => -1, ")" => -1, "?" => 1, ":" => 1, "||" => 3, "&&" => 4, "==" => 5, "!=" => 5, "<" => 6, ">" => 6, "<=" => 6, ">=" => 6, "+" => 7, "-" => 7, "*" => 8, "/" => 8, "%" => 8);
+  // Right associativity
+  $right_associativity = array("?" => 1, ":" => 1);
+
+  $tokens = _locale_import_tokenize_formula($string);
+
+  // Parse by converting into infix notation then back into postfix
+  // Operator stack - holds math operators and symbols
+  $operator_stack = array();
+  // Element Stack - holds data to be operated on
+  $element_stack = array();
+
+  foreach ($tokens as $token) {
+    $current_token = $token;
+
+    // Numbers and the $n variable are simply pushed into $element_stack
+    if (is_numeric($token)) {
+      $element_stack[] = $current_token;
+    }
+    elseif ($current_token == "n") {
+      $element_stack[] = '$n';
+    }
+    elseif ($current_token == "(") {
+      $operator_stack[] = $current_token;
+    }
+    elseif ($current_token == ")") {
+      $topop = array_pop($operator_stack);
+      while (isset($topop) && ($topop != "(")) {
+        $element_stack[] = $topop;
+        $topop = array_pop($operator_stack);
+      }
+    }
+    elseif (!empty($precedence[$current_token])) {
+      // If it's an operator, then pop from $operator_stack into $element_stack until the
+      // precedence in $operator_stack is less than current, then push into $operator_stack
+      $topop = array_pop($operator_stack);
+      while (isset($topop) && ($precedence[$topop] >= $precedence[$current_token]) && !(($precedence[$topop] == $precedence[$current_token]) && !empty($right_associativity[$topop]) && !empty($right_associativity[$current_token]))) {
+        $element_stack[] = $topop;
+        $topop = array_pop($operator_stack);
+      }
+      if ($topop) {
+        $operator_stack[] = $topop;   // Return element to top
+      }
+      $operator_stack[] = $current_token;      // Parentheses are not needed
+    }
+    else {
+      return FALSE;
+    }
+  }
+
+  // Flush operator stack
+  $topop = array_pop($operator_stack);
+  while ($topop != NULL) {
+    $element_stack[] = $topop;
+    $topop = array_pop($operator_stack);
+  }
+
+  // Now extract formula from stack
+  $previous_size = count($element_stack) + 1;
+  while (count($element_stack) < $previous_size) {
+    $previous_size = count($element_stack);
+    for ($i = 2; $i < count($element_stack); $i++) {
+      $op = $element_stack[$i];
+      if (!empty($precedence[$op])) {
+        $f = "";
+        if ($op == ":") {
+          $f = $element_stack[$i - 2] . "):" . $element_stack[$i - 1] . ")";
+        }
+        elseif ($op == "?") {
+          $f = "(" . $element_stack[$i - 2] . "?(" . $element_stack[$i - 1];
+        }
+        else {
+          $f = "(" . $element_stack[$i - 2] . $op . $element_stack[$i - 1] . ")";
+        }
+        array_splice($element_stack, $i - 2, 3, $f);
+        break;
+      }
+    }
+  }
+
+  // If only one element is left, the number of operators is appropriate
+  if (count($element_stack) == 1) {
+    return $element_stack[0];
+  }
+  else {
+    return FALSE;
+  }
+}
+
+/**
+ * Provides backward-compatible formula parsing for token_get_all().
+ *
+ * @param $string
+ *   A string containing the arithmetic formula.
+ *
+ * @return
+ *   The PHP version of the formula.
+ */
+function _locale_import_tokenize_formula($formula) {
+  $formula = str_replace(" ", "", $formula);
+  $tokens = array();
+  for ($i = 0; $i < strlen($formula); $i++) {
+    if (is_numeric($formula[$i])) {
+      $num = $formula[$i];
+      $j = $i + 1;
+      while ($j < strlen($formula) && is_numeric($formula[$j])) {
+        $num .= $formula[$j];
+        $j++;
+      }
+      $i = $j - 1;
+      $tokens[] = $num;
+    }
+    elseif ($pos = strpos(" =<>!&|", $formula[$i])) { // We won't have a space
+      $next = $formula[$i + 1];
+      switch ($pos) {
+        case 1:
+        case 2:
+        case 3:
+        case 4:
+          if ($next == '=') {
+            $tokens[] = $formula[$i] . '=';
+            $i++;
+          }
+          else {
+            $tokens[] = $formula[$i];
+          }
+          break;
+        case 5:
+          if ($next == '&') {
+            $tokens[] = '&&';
+            $i++;
+          }
+          else {
+            $tokens[] = $formula[$i];
+          }
+          break;
+        case 6:
+          if ($next == '|') {
+            $tokens[] = '||';
+            $i++;
+          }
+          else {
+            $tokens[] = $formula[$i];
+          }
+          break;
+      }
+    }
+    else {
+      $tokens[] = $formula[$i];
+    }
+  }
+  return $tokens;
+}
+
+/**
+ * Generates a short, one-string version of the passed comment array.
+ *
+ * @param $comment
+ *   An array of strings containing a comment.
+ *
+ * @return
+ *   Short one-string version of the comment.
+ */
+function _locale_import_shorten_comments($comment) {
+  $comm = '';
+  while (count($comment)) {
+    $test = $comm . substr(array_shift($comment), 1) . ', ';
+    if (strlen($comm) < 130) {
+      $comm = $test;
+    }
+    else {
+      break;
+    }
+  }
+  return trim(substr($comm, 0, -2));
+}
+
+/**
+ * Parses a string in quotes.
+ *
+ * @param $string
+ *   A string specified with enclosing quotes.
+ *
+ * @return
+ *   The string parsed from inside the quotes.
+ */
+function _locale_import_parse_quoted($string) {
+  if (substr($string, 0, 1) != substr($string, -1, 1)) {
+    return FALSE;   // Start and end quotes must be the same
+  }
+  $quote = substr($string, 0, 1);
+  $string = substr($string, 1, -1);
+  if ($quote == '"') {        // Double quotes: strip slashes
+    return stripcslashes($string);
+  }
+  elseif ($quote == "'") {  // Simple quote: return as-is
+    return $string;
+  }
+  else {
+    return FALSE;             // Unrecognized quote
+  }
+}
+
+/**
+ * Generates a structured array of all translated strings for the language.
+ *
+ * @param $language
+ *   Language object to generate the output for, or NULL if generating
+ *   translation template.
+ * @param $options
+ *   (optional) An associative array specifying what to include in the output:
+ *   - customized: include customized strings (if TRUE)
+ *   - uncustomized: include non-customized string (if TRUE)
+ *   - untranslated: include untranslated source strings (if TRUE)
+ *   Ignored if $language is NULL.
+ *
+ * @return
+ *   An array of translated strings that can be used to generate an export.
+ */
+function _locale_export_get_strings($language = NULL, $options = array()) {
+
+  // Assume FALSE for all options if not provided by the API.
+  $options += array(
+    'customized' => FALSE,
+    'not_customized' => FALSE,
+    'not_translated' => FALSE,
+  );
+  if (array_sum($options) == 0) {
+    // If user asked to not include anything in the translation files,
+    // that would not make sense, so just fall back on providing a template.
+    $language = NULL;
+  }
+
+  // Build and execute query to collect source strings and translations.
+  $query = db_select('locales_source', 's');
+  if (!empty($language)) {
+    if ($options['not_translated']) {
+      // Left join to keep untranslated strings in.
+      $query->leftJoin('locales_target', 't', 's.lid = t.lid AND t.language = :language', array(':language' => $language->langcode));
+    }
+    else {
+      // Inner join to filter for only translations.
+      $query->innerJoin('locales_target', 't', 's.lid = t.lid AND t.language = :language', array(':language' => $language->langcode));
+    }
+    if ($options['customized']) {
+      if (!$options['not_customized']) {
+        // Filter for customized strings only.
+        $query->condition('t.customized', LOCALE_CUSTOMIZED);
+      }
+      // Else no filtering needed in this case.
+    }
+    else {
+      if ($options['not_customized']) {
+        // Filter for non-customized strings only.
+        $query->condition('t.customized', LOCALE_NOT_CUSTOMIZED);
+      }
+      else {
+        // Filter for strings without translation.
+        $query->isNull('t.translation');
+      }
+    }
+    $query->fields('t', array('translation'));
+  }
+  else {
+    $query->leftJoin('locales_target', 't', 's.lid = t.lid');
+  }
+  $query->fields('s', array('lid', 'source', 'context', 'location'));
+  $result = $query->execute();
+
+  // Structure results in an array with metainformation on the strings.
+  $strings = array();
+  foreach ($result as $child) {
+    $strings[$child->lid] = array(
+      'comment'     => $child->location,
+      'source'      => $child->source,
+      'context'     => $child->context,
+      'translation' => isset($child->translation) ? $child->translation : '',
+    );
+  }
+  return $strings;
+}
+
+/**
+ * Generates the PO(T) file contents for the given strings.
+ *
+ * @param $language
+ *   Language object to generate the output for, or NULL if generating
+ *   translation template.
+ * @param $strings
+ *   Array of strings to export. See _locale_export_get_strings()
+ *   on how it should be formatted.
+ * @param $header
+ *   The header portion to use for the output file. Defaults
+ *   are provided for PO and POT files.
+ */
+function _locale_export_po_generate($language = NULL, $strings = array(), $header = NULL) {
+  global $user;
+
+  $locale_plurals = variable_get('locale_translation_plurals', array());
+
+  if (!isset($header)) {
+    if (isset($language)) {
+      $header = '# ' . $language->name . ' translation of ' . config('system.site')->get('name') . "\n";
+      $header .= '# Generated by ' . $user->name . ' <' . $user->mail . ">\n";
+      $header .= "#\n";
+      $header .= "msgid \"\"\n";
+      $header .= "msgstr \"\"\n";
+      $header .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
+      $header .= "\"POT-Creation-Date: " . date("Y-m-d H:iO") . "\\n\"\n";
+      $header .= "\"PO-Revision-Date: " . date("Y-m-d H:iO") . "\\n\"\n";
+      $header .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
+      $header .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
+      $header .= "\"MIME-Version: 1.0\\n\"\n";
+      $header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
+      $header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
+      if (!empty($locale_plurals[$language->langcode]['formula'])) {
+        $header .= "\"Plural-Forms: nplurals=" . $locale_plurals[$language->langcode]['plurals'] . "; plural=" . strtr($locale_plurals[$language->langcode]['formula'], array('$' => '')) . ";\\n\"\n";
+        // Remember number of plural variants to optimize the export.
+        $nplurals = $locale_plurals[$language->langcode]['plurals'];
+      }
+      else {
+        // Remember we did not have a plural number for the export.
+        $nplurals = 0;
+      }
+    }
+    else {
+      $header = "# LANGUAGE translation of PROJECT\n";
+      $header .= "# Copyright (c) YEAR NAME <EMAIL@ADDRESS>\n";
+      $header .= "#\n";
+      $header .= "msgid \"\"\n";
+      $header .= "msgstr \"\"\n";
+      $header .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
+      $header .= "\"POT-Creation-Date: " . date("Y-m-d H:iO") . "\\n\"\n";
+      $header .= "\"PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\\n\"\n";
+      $header .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
+      $header .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
+      $header .= "\"MIME-Version: 1.0\\n\"\n";
+      $header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
+      $header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
+      $header .= "\"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\\n\"\n";
+    }
+  }
+
+  $output = $header . "\n";
+
+  foreach ($strings as $lid => $string) {
+    if ($string['comment']) {
+      $output .= '#: ' . $string['comment'] . "\n";
+    }
+    if (!empty($string['context'])) {
+      $output .= 'msgctxt ' . _locale_export_string($string['context']);
+    }
+    if (strpos($string['source'], LOCALE_PLURAL_DELIMITER) !== FALSE) {
+      // Export plural string.
+      $export_array = explode(LOCALE_PLURAL_DELIMITER, $string['source']);
+      $output .= 'msgid ' . _locale_export_string($export_array[0]);
+      $output .= 'msgid_plural ' . _locale_export_string($export_array[1]);
+      if (isset($language)) {
+        $export_array = explode(LOCALE_PLURAL_DELIMITER, $string['translation']);
+        for ($i = 0; $i < $nplurals; $i++) {
+          if (isset($export_array[$i])) {
+            $output .= 'msgstr[' . $i . '] ' . _locale_export_string($export_array[$i]);
+          }
+          else {
+            $output .= 'msgstr[' . $i . '] ""' . "\n";
+          }
+        }
+      }
+      else {
+        $output .= 'msgstr[0] ""' . "\n";
+        $output .= 'msgstr[1] ""' . "\n";
+      }
+    }
+    else {
+      $output .= 'msgid ' . _locale_export_string($string['source']);
+      $output .= 'msgstr ' . _locale_export_string($string['translation']);
+    }
+    $output .= "\n";
+  }
+  return $output;
+}
+
+/**
+ * Writes a generated PO or POT file to the output.
+ *
+ * @param $language
+ *   Language object to generate the output for, or NULL if generating
+ *   translation template.
+ * @param $output
+ *   The PO(T) file to output as a string. See _locale_export_generate_po()
+ *   on how it can be generated.
+ */
+function _locale_export_po($language = NULL, $output = NULL) {
+  // Log the export event.
+  if (isset($language)) {
+    $filename = $language->langcode . '.po';
+    watchdog('locale', 'Exported %locale translation file: %filename.', array('%locale' => $language->name, '%filename' => $filename));
+  }
+  else {
+    $filename = 'drupal.pot';
+    watchdog('locale', 'Exported translation file: %filename.', array('%filename' => $filename));
+  }
+  // Download the file for the client.
+  header("Content-Disposition: attachment; filename=$filename");
+  header("Content-Type: text/plain; charset=utf-8");
+  print $output;
+  drupal_exit();
+}
+
+/**
+ * Prints a string on multiple lines.
+ */
+function _locale_export_string($str) {
+  $stri = addcslashes($str, "\0..\37\\\"");
+  $parts = array();
+
+  // Cut text into several lines
+  while ($stri != "") {
+    $i = strpos($stri, "\\n");
+    if ($i === FALSE) {
+      $curstr = $stri;
+      $stri = "";
+    }
+    else {
+      $curstr = substr($stri, 0, $i + 2);
+      $stri = substr($stri, $i + 2);
+    }
+    $curparts = explode("\n", _locale_export_wrap($curstr, 70));
+    $parts = array_merge($parts, $curparts);
+  }
+
+  // Multiline string
+  if (count($parts) > 1) {
+    return "\"\"\n\"" . implode("\"\n\"", $parts) . "\"\n";
+  }
+  // Single line string
+  elseif (count($parts) == 1) {
+    return "\"$parts[0]\"\n";
+  }
+  // No translation
+  else {
+    return "\"\"\n";
+  }
+}
+
+/**
+ * Wraps text for Portable Object (Template) files.
+ */
+function _locale_export_wrap($str, $len) {
+  $words = explode(' ', $str);
+  $return = array();
+
+  $cur = "";
+  $nstr = 1;
+  while (count($words)) {
+    $word = array_shift($words);
+    if ($nstr) {
+      $cur = $word;
+      $nstr = 0;
+    }
+    elseif (strlen("$cur $word") > $len) {
+      $return[] = $cur . " ";
+      $cur = $word;
+    }
+    else {
+      $cur = "$cur $word";
+    }
+  }
+  $return[] = $cur;
+
+  return implode("\n", $return);
+}
+
+/**
+ * @} End of "defgroup locale-api-import-export".
+ */
diff --git a/core/includes/install.core.inc b/core/includes/install.core.inc
index 889dbe2..1d181d4 100644
--- a/core/includes/install.core.inc
+++ b/core/includes/install.core.inc
@@ -1,5 +1,6 @@
 <?php
 
+use Drupal\Core\DrupalKernel;
 use Drupal\Core\Database\Database;
 use Drupal\Core\Database\Install\TaskException;
 
@@ -254,11 +255,6 @@ function install_begin_request(&$install_state) {
   // A request object from the HTTPFoundation to tell us about the request.
   $request = Request::createFromGlobals();
 
-  // Set the global $request object.  This is a temporary measure to
-  // keep legacy utility functions working.  It should be moved to a dependency
-  // injection container at some point.
-  request($request);
-
   // This must go after drupal_bootstrap(), which unsets globals!
   global $conf;
 
@@ -1416,6 +1412,8 @@ function install_bootstrap_full(&$install_state) {
   // Clear the module list that was overriden earlier in the process.
   // This will allow all freshly installed modules to be loaded.
   module_list_reset();
+  $kernel = new DrupalKernel('prod', FALSE);
+  $kernel->boot();
   drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 }
 
diff --git a/core/includes/install.inc b/core/includes/install.inc
index d0a28bc..1150fce 100644
--- a/core/includes/install.inc
+++ b/core/includes/install.inc
@@ -1,7 +1,6 @@
 <?php
 
 use Drupal\Core\Database\Database;
-use Drupal\locale\Gettext;
 
 /**
  * Indicates that a module has not been installed yet.
@@ -701,7 +700,13 @@ function st($string, array $args = array(), array $options = array()) {
       // that multiple files end with the same extension, even if unlikely.
       $files = install_find_translation_files($install_state['parameters']['langcode']);
       if (!empty($files)) {
-        $strings = Gettext::filesToArray($install_state['parameters']['langcode'], $files);
+        // Include cross-dependent code from locale module and gettext.inc.
+        require_once DRUPAL_ROOT . '/core/modules/locale/locale.module';
+        require_once DRUPAL_ROOT . '/core/includes/gettext.inc';
+        foreach ($files as $file) {
+          _locale_import_read_po('mem-store', $file);
+        }
+        $strings = _locale_import_one_string('mem-report');
       }
     }
   }
diff --git a/core/includes/language.inc b/core/includes/language.inc
index 0892cc4..48ba3d6 100644
--- a/core/includes/language.inc
+++ b/core/includes/language.inc
@@ -110,7 +110,7 @@ const LANGUAGE_NEGOTIATION_DEFAULT = 'language-default';
  * @return
  *   The negotiated language object.
  */
-function language_types_initialize($type) {
+function language_types_initialize($type, $args = array()) {
   // Execute the language negotiation methods in the order they were set up and
   // return the first valid language found.
   $negotiation = variable_get("language_negotiation_$type", array());
@@ -120,6 +120,7 @@ function language_types_initialize($type) {
     if (isset($method['types']) && !in_array($type, $method['types'])) {
       continue;
     }
+    $method['args'] = $args;
     $language = language_negotiation_method_invoke($method_id, $method);
     if ($language) {
       // Remember the method ID used to detect the language.
@@ -452,7 +453,8 @@ function language_negotiation_method_invoke($method_id, $method = NULL) {
     // satisfied we can execute the callback.
     $cache = !isset($method['cache']) || $user->uid || $method['cache'] == variable_get('cache', 0);
     $callback = isset($method['callbacks']['negotiation']) ? $method['callbacks']['negotiation'] : FALSE;
-    $langcode = $cache && function_exists($callback) ? $callback($languages) : FALSE;
+    $args = isset($method['args']) ? $method['args'] : array();
+    $langcode = $cache && function_exists($callback) ? $callback($languages, $args) : FALSE;
     $results[$method_id] = isset($languages[$langcode]) ? $languages[$langcode] : FALSE;
   }
 
diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index 5677369..41fe852 100644
--- a/core/includes/menu.inc
+++ b/core/includes/menu.inc
@@ -1069,7 +1069,7 @@ function menu_tree_output($tree) {
  */
 function menu_tree_all_data($menu_name, $link = NULL, $max_depth = NULL) {
   $tree = &drupal_static(__FUNCTION__, array());
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   // Use $mlid as a flag for whether the data being loaded is for the whole tree.
   $mlid = isset($link['mlid']) ? $link['mlid'] : 0;
@@ -1180,7 +1180,7 @@ function menu_tree_get_path($menu_name) {
 function menu_tree_page_data($menu_name, $max_depth = NULL, $only_active_trail = FALSE) {
   $tree = &drupal_static(__FUNCTION__, array());
 
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   // Check if the active trail has been overridden for this menu tree.
   $active_path = menu_tree_get_path($menu_name);
@@ -1336,7 +1336,7 @@ function menu_build_tree($menu_name, array $parameters = array()) {
 function _menu_build_tree($menu_name, array $parameters = array()) {
   // Static cache of already built menu trees.
   $trees = &drupal_static(__FUNCTION__, array());
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   // Build the cache id; sort parents to prevent duplicate storage and remove
   // default parameter values.
diff --git a/core/includes/path.inc b/core/includes/path.inc
index 62a58a6..c387de5 100644
--- a/core/includes/path.inc
+++ b/core/includes/path.inc
@@ -82,7 +82,7 @@ function drupal_lookup_path($action, $path = '', $langcode = NULL) {
   // language. If we used a language different from the one conveyed by the
   // requested URL, we might end up being unable to check if there is a path
   // alias matching the URL path.
-  $langcode = $langcode ? $langcode : drupal_container()->get(LANGUAGE_TYPE_URL)->langcode;
+  $langcode = $langcode ? $langcode : language_manager(LANGUAGE_TYPE_URL)->langcode;
 
   if ($action == 'wipe') {
     $cache = array();
@@ -358,6 +358,9 @@ function drupal_match_path($path, $patterns) {
  * @see request_path()
  */
 function current_path() {
+  if (drupal_container()->has('request')) {
+    return drupal_container()->get('request')->attributes->get('system_path');
+  }
   return _current_path();
 }
 
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index 84e2ec7..9c4306a 100644
--- a/core/includes/theme.inc
+++ b/core/includes/theme.inc
@@ -1624,7 +1624,7 @@ function theme_link($variables) {
  *     http://www.w3.org/TR/WCAG-TECHS/H42.html for more information.
  */
 function theme_links($variables) {
-  $language_url = drupal_container()->get(LANGUAGE_TYPE_URL);
+  $language_url = language_manager(LANGUAGE_TYPE_URL);
 
   $links = $variables['links'];
   $attributes = $variables['attributes'];
@@ -2419,7 +2419,7 @@ function template_process(&$variables, $hook) {
  * @see html.tpl.php
  */
 function template_preprocess_html(&$variables) {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   // Compile a list of classes that are going to be applied to the body element.
   // This allows advanced theming based on context (home page, node of certain type, etc.).
@@ -2550,7 +2550,7 @@ function template_preprocess_html(&$variables) {
  * @see page.tpl.php
  */
 function template_preprocess_page(&$variables) {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
   $site_config = config('system.site');
 
   // Move some variables to the top level for themer convenience and template cleanliness.
@@ -2735,7 +2735,7 @@ function theme_get_suggestions($args, $base, $delimiter = '__') {
  */
 function template_preprocess_maintenance_page(&$variables) {
   global $theme;
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
   // Retrieve the theme data to list all available regions.
   $theme_data = list_themes();
   $regions = $theme_data[$theme]->info['regions'];
diff --git a/core/includes/update.inc b/core/includes/update.inc
index acfc0d5..ff56cb2 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -247,8 +247,10 @@ function update_prepare_d8_language() {
 
     // Update the 'language_default' system variable, if configured.
     $language_default = variable_get('language_default');
-    if (!empty($language_default) && isset($language_default->language)) {
-      $language_default->langcode = $language_default->language;
+    if (!empty($language_default) && (isset($language_default->langcode) || isset($language_default->language))) {
+      if (!isset($language_default->langcode)) {
+        $language_default->langcode = $language_default->language;
+      }
       unset($language_default->language);
       // In D8, the 'language_default' is not anymore an object, but an array,
       // so make sure that the new value that is saved into this variable is an
diff --git a/core/lib/Drupal/Component/Gettext/PoHeader.php b/core/lib/Drupal/Component/Gettext/PoHeader.php
deleted file mode 100644
index ae68abc..0000000
--- a/core/lib/Drupal/Component/Gettext/PoHeader.php
+++ /dev/null
@@ -1,418 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Component\Gettext\PoHeader
- */
-
-namespace Drupal\Component\Gettext;
-
-/**
- * Gettext PO header handler.
- *
- * Possible Gettext PO header elements are explained in
- * http://www.gnu.org/software/gettext/manual/gettext.html#Header-Entry,
- * but we only support a subset of these directly.
- *
- * Example header:
- *
- * "Project-Id-Version: Drupal core (7.11)\n"
- * "POT-Creation-Date: 2012-02-12 22:59+0000\n"
- * "PO-Revision-Date: YYYY-mm-DD HH:MM+ZZZZ\n"
- * "Language-Team: Catalan\n"
- * "MIME-Version: 1.0\n"
- * "Content-Type: text/plain; charset=utf-8\n"
- * "Content-Transfer-Encoding: 8bit\n"
- * "Plural-Forms: nplurals=2; plural=(n>1);\n"
- */
-class PoHeader {
-
-  /**
-   * Language code.
-   *
-   * @var string
-   */
-  private $_langcode;
-
-  /**
-   * Formula for the plural form.
-   *
-   * @var string
-   */
-  private $_pluralForms;
-
-  /**
-   * Author(s) of the file.
-   *
-   * @var string
-   */
-  private $_authors;
-
-  /**
-   * Date the po file got created.
-   *
-   * @var string
-   */
-  private $_po_date;
-
-  /**
-   * Human readable language name.
-   *
-   * @var string
-   */
-  private $_languageName;
-
-  /**
-   * Name of the project the translation belongs to.
-   *
-   * @var string
-   */
-  private $_projectName;
-
-  /**
-   * Constructor, creates a PoHeader with default values.
-   *
-   * @param string $langcode
-   *   Language code.
-   */
-  public function __construct($langcode = NULL) {
-    $this->_langcode = $langcode;
-    $this->_po_date = date("Y-m-d H:iO");
-    $this->_pluralForms = 'nplurals=2; plural=(n > 1);';
-  }
-
-  /**
-   * Get the plural form.
-   *
-   * @return string
-   *   Plural form component from the header, for example:
-   *   'nplurals=2; plural=(n > 1);'.
-   */
-  function getPluralForms() {
-    return $this->_pluralForms;
-  }
-
-  /**
-   * Set the human readable language name.
-   *
-   * @param string $languageName
-   *   Human readable language name.
-   */
-  function setLanguageName($languageName) {
-    $this->_languageName = $languageName;
-  }
-
-  /**
-   * Get the human readable language name.
-   *
-   * @return string
-   *   The human readable language name.
-   */
-  function getLanguageName() {
-    return $this->_languageName;
-  }
-
-  /**
-   * Set the project name.
-   *
-   * @param string $projectName
-   *   Human readable project name.
-   */
-  function setProjectName($projectName) {
-    $this->_projectName = $projectName;
-  }
-
-  /**
-   * Get the project name.
-   *
-   * @return string
-   *   The human readable project name.
-   */
-  function getProjectName() {
-    return $this->_projectName;
-  }
-
-  /**
-   * Populate internal values from a string.
-   *
-   * @param string $header
-   *   Full header string with key-value pairs.
-   */
-  public function setFromString($header) {
-    // Get an array of all header values for processing.
-    $values = $this->parseHeader($header);
-
-    // There is only one value relevant for our header implementation when
-    // reading, and that is the plural formula.
-    if (!empty($values['Plural-Forms'])) {
-      $this->_pluralForms = $values['Plural-Forms'];
-    }
-  }
-
-  /**
-   * Generate a Gettext PO formatted header string based on data set earlier.
-   */
-  public function __toString() {
-    $output = '';
-
-    $isTemplate = empty($this->_languageName);
-
-    $output .= '# ' . ($isTemplate ? 'LANGUAGE' : $this->_languageName) . ' translation of ' . ($isTemplate ? 'PROJECT' : $this->_projectName) . "\n";
-    if (!empty($this->_authors)) {
-      $output .= '# Generated by ' . implode("\n# ", $this->_authors) . "\n";
-    }
-    $output .= "#\n";
-
-    // Add the actual header information.
-    $output .= "msgid \"\"\n";
-    $output .= "msgstr \"\"\n";
-    $output .= "\"Project-Id-Version: PROJECT VERSION\\n\"\n";
-    $output .= "\"POT-Creation-Date: " . $this->_po_date . "\\n\"\n";
-    $output .= "\"PO-Revision-Date: " . $this->_po_date . "\\n\"\n";
-    $output .= "\"Last-Translator: NAME <EMAIL@ADDRESS>\\n\"\n";
-    $output .= "\"Language-Team: LANGUAGE <EMAIL@ADDRESS>\\n\"\n";
-    $output .= "\"MIME-Version: 1.0\\n\"\n";
-    $output .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
-    $output .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
-    $output .= "\"Plural-Forms: " . $this->_pluralForms . "\\n\"\n";
-    $output .= "\n";
-
-    return $output;
-  }
-
-  /**
-   * Parses a Plural-Forms entry from a Gettext Portable Object file header.
-   *
-   * @param string $pluralforms
-   *   The Plural-Forms entry value.
-   *
-   * @return
-   *   An array containing the number of plural forms and the converted version
-   *   of the formula that can be evaluated with PHP later.
-   */
-  function parsePluralForms($pluralforms) {
-    // First, delete all whitespace.
-    $pluralforms = strtr($pluralforms, array(" " => "", "\t" => ""));
-
-    // Select the parts that define nplurals and plural.
-    $nplurals = strstr($pluralforms, "nplurals=");
-    if (strpos($nplurals, ";")) {
-      // We want the string from the 10th char, because "nplurals=" length is 9.
-      $nplurals = substr($nplurals, 9, strpos($nplurals, ";") - 9);
-    }
-    else {
-      return FALSE;
-    }
-    $plural = strstr($pluralforms, "plural=");
-    if (strpos($plural, ";")) {
-      // We want the string from the 8th char, because "plural=" length is 7.
-      $plural = substr($plural, 7, strpos($plural, ";") - 7);
-    }
-    else {
-      return FALSE;
-    }
-
-    // Get PHP version of the plural formula.
-    $plural = $this->parseArithmetic($plural);
-
-    if ($plural !== FALSE) {
-      return array($nplurals, $plural);
-    }
-    else {
-      throw new Exception('The plural formula could not be parsed.');
-    }
-  }
-
-  /**
-   * Parses a Gettext Portable Object file header.
-   *
-   * @param string $header
-   *   A string containing the complete header.
-   *
-   * @return array
-   *   An associative array of key-value pairs.
-   */
-  private function parseHeader($header) {
-    $header_parsed = array();
-    $lines = array_map('trim', explode("\n", $header));
-    foreach ($lines as $line) {
-      if ($line) {
-        list($tag, $contents) = explode(":", $line, 2);
-        $header_parsed[trim($tag)] = trim($contents);
-      }
-    }
-    return $header_parsed;
-  }
-
-  /**
-   * Parses and sanitizes an arithmetic formula into a PHP expression.
-   *
-   * While parsing, we ensure, that the operators have the right
-   * precedence and associativity.
-   *
-   * @param string $string
-   *   A string containing the arithmetic formula.
-   *
-   * @return
-   *   A version of the formula to evaluate with PHP later.
-   */
-  private function parseArithmetic($string) {
-    // Operator precedence table.
-    $precedence = array("(" => -1, ")" => -1, "?" => 1, ":" => 1, "||" => 3, "&&" => 4, "==" => 5, "!=" => 5, "<" => 6, ">" => 6, "<=" => 6, ">=" => 6, "+" => 7, "-" => 7, "*" => 8, "/" => 8, "%" => 8);
-    // Right associativity.
-    $right_associativity = array("?" => 1, ":" => 1);
-
-    $tokens = $this->tokenizeFormula($string);
-
-    // Parse by converting into infix notation then back into postfix
-    // Operator stack - holds math operators and symbols.
-    $operator_stack = array();
-    // Element Stack - holds data to be operated on.
-    $element_stack = array();
-
-    foreach ($tokens as $token) {
-      $current_token = $token;
-
-      // Numbers and the $n variable are simply pushed into $element_stack.
-      if (is_numeric($token)) {
-        $element_stack[] = $current_token;
-      }
-      elseif ($current_token == "n") {
-        $element_stack[] = '$n';
-      }
-      elseif ($current_token == "(") {
-        $operator_stack[] = $current_token;
-      }
-      elseif ($current_token == ")") {
-        $topop = array_pop($operator_stack);
-        while (isset($topop) && ($topop != "(")) {
-          $element_stack[] = $topop;
-          $topop = array_pop($operator_stack);
-        }
-      }
-      elseif (!empty($precedence[$current_token])) {
-        // If it's an operator, then pop from $operator_stack into
-        // $element_stack until the precedence in $operator_stack is less
-        // than current, then push into $operator_stack.
-        $topop = array_pop($operator_stack);
-        while (isset($topop) && ($precedence[$topop] >= $precedence[$current_token]) && !(($precedence[$topop] == $precedence[$current_token]) && !empty($right_associativity[$topop]) && !empty($right_associativity[$current_token]))) {
-          $element_stack[] = $topop;
-          $topop = array_pop($operator_stack);
-        }
-        if ($topop) {
-          // Return element to top.
-          $operator_stack[] = $topop;
-        }
-        // Parentheses are not needed.
-        $operator_stack[] = $current_token;
-      }
-      else {
-        return FALSE;
-      }
-    }
-
-    // Flush operator stack.
-    $topop = array_pop($operator_stack);
-    while ($topop != NULL) {
-      $element_stack[] = $topop;
-      $topop = array_pop($operator_stack);
-    }
-
-    // Now extract formula from stack.
-    $previous_size = count($element_stack) + 1;
-    while (count($element_stack) < $previous_size) {
-      $previous_size = count($element_stack);
-      for ($i = 2; $i < count($element_stack); $i++) {
-        $op = $element_stack[$i];
-        if (!empty($precedence[$op])) {
-          $f = "";
-          if ($op == ":") {
-            $f = $element_stack[$i - 2] . "):" . $element_stack[$i - 1] . ")";
-          }
-          elseif ($op == "?") {
-            $f = "(" . $element_stack[$i - 2] . "?(" . $element_stack[$i - 1];
-          }
-          else {
-            $f = "(" . $element_stack[$i - 2] . $op . $element_stack[$i - 1] . ")";
-          }
-          array_splice($element_stack, $i - 2, 3, $f);
-          break;
-        }
-      }
-    }
-
-    // If only one element is left, the number of operators is appropriate.
-    if (count($element_stack) == 1) {
-      return $element_stack[0];
-    }
-    else {
-      return FALSE;
-    }
-  }
-
-  /**
-   * Tokenize the formula.
-   *
-   * @param string $formula
-   *   A string containing the arithmetic formula.
-   *
-   * @return array
-   *   List of arithmetic tokens identified in the formula.
-   */
-  private function tokenizeFormula($formula) {
-    $formula = str_replace(" ", "", $formula);
-    $tokens = array();
-    for ($i = 0; $i < strlen($formula); $i++) {
-      if (is_numeric($formula[$i])) {
-        $num = $formula[$i];
-        $j = $i + 1;
-        while ($j < strlen($formula) && is_numeric($formula[$j])) {
-          $num .= $formula[$j];
-          $j++;
-        }
-        $i = $j - 1;
-        $tokens[] = $num;
-      }
-      elseif ($pos = strpos(" =<>!&|", $formula[$i])) {
-        $next = $formula[$i + 1];
-        switch ($pos) {
-          case 1:
-          case 2:
-          case 3:
-          case 4:
-            if ($next == '=') {
-              $tokens[] = $formula[$i] . '=';
-              $i++;
-            }
-            else {
-              $tokens[] = $formula[$i];
-            }
-            break;
-          case 5:
-            if ($next == '&') {
-              $tokens[] = '&&';
-              $i++;
-            }
-            else {
-              $tokens[] = $formula[$i];
-            }
-            break;
-          case 6:
-            if ($next == '|') {
-              $tokens[] = '||';
-              $i++;
-            }
-            else {
-              $tokens[] = $formula[$i];
-            }
-            break;
-        }
-      }
-      else {
-        $tokens[] = $formula[$i];
-      }
-    }
-    return $tokens;
-  }
-
-}
diff --git a/core/lib/Drupal/Component/Gettext/PoItem.php b/core/lib/Drupal/Component/Gettext/PoItem.php
deleted file mode 100644
index 599a58a..0000000
--- a/core/lib/Drupal/Component/Gettext/PoItem.php
+++ /dev/null
@@ -1,287 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Component\Gettext\PoItem.
- */
-
-namespace Drupal\Component\Gettext;
-
-/**
- * PoItem handles one translation.
- *
- * @todo: This class contains some really old legacy code.
- * @see https://drupal.org/node/1637662
- */
-class PoItem {
-
-  /**
-   * The language code this translation is in.
-   *
-   * @car string
-   */
-  private $_langcode;
-
-  /**
-   * The context this translation belongs to.
-   *
-   * @var string
-   */
-  private $_context = '';
-
-  /**
-   * The source string or array of strings if it has plurals.
-   *
-   * @var string or array
-   * @see $_plural
-   */
-  private $_source;
-
-  /**
-   * Flag indicating if this translation has plurals.
-   *
-   * @var boolean
-   */
-  private $_plural;
-
-  /**
-   * The comment of this translation.
-   *
-   * @var string
-   */
-  private $_comment;
-
-  /**
-   * The translation string or array of strings if it has plurals.
-   *
-   * @var string or array
-   * @see $_plural
-   */
-  private $_translation;
-
-  /**
-   * Get the language code of the currently used language.
-   *
-   * @return string with langcode
-   */
-  function getLangcode() {
-    return $this->_langcode;
-  }
-
-  /**
-   * Set the language code of the current language.
-   *
-   * @param string $langcode
-   */
-  function setLangcode($langcode) {
-    $this->_langcode = $langcode;
-  }
-
-  /**
-   * Get the context this translation belongs to.
-   *
-   * @return string $context
-   */
-  function getContext() {
-    return $this->_context;
-  }
-
-  /**
-   * Set the context this translation belongs to.
-   *
-   * @param string $context
-   */
-  function setContext($context) {
-    $this->_context = $context;
-  }
-
-  /**
-   * Get the source string or the array of strings if the translation has
-   * plurals.
-   *
-   * @return string or array $translation
-   */
-  function getSource() {
-    return $this->_source;
-  }
-
-  /**
-   * Set the source string or the array of strings if the translation has
-   * plurals.
-   *
-   * @param string or array $source
-   */
-  function setSource($source) {
-    $this->_source = $source;
-  }
-
-  /**
-   * Get the translation string or the array of strings if the translation has
-   * plurals.
-   *
-   * @return string or array $translation
-   */
-  function getTranslation() {
-    return $this->_translation;
-  }
-
-  /**
-   * Set the translation string or the array of strings if the translation has
-   * plurals.
-   *
-   * @param string or array $translation
-   */
-  function setTranslation($translation) {
-    $this->_translation = $translation;
-  }
-
-  /**
-   * Set if the translation has plural values.
-   *
-   * @param boolean $plural
-   */
-  function setPlural($plural) {
-    $this->_plural = $plural;
-  }
-
-  /**
-   * Get if the translation has plural values.
-   *
-   * @return boolean $plural
-   */
-  function isPlural() {
-    return $this->_plural;
-  }
-
-  /**
-   * Get the comment of this translation.
-   *
-   * @return String $comment
-   */
-  function getComment() {
-    return $this->_comment;
-  }
-
-  /**
-   * Set the comment of this translation.
-   *
-   * @param String $comment
-   */
-  function setComment($comment) {
-    $this->_comment = $comment;
-  }
-
-  /**
-   * Create the PoItem from a structured array.
-   *
-   * @param array values
-   */
-  public function setFromArray(array $values = array()) {
-    if (isset($values['context'])) {
-      $this->setContext($values['context']);
-    }
-    if (isset($values['source'])) {
-      $this->setSource($values['source']);
-    }
-    if (isset($values['translation'])) {
-      $this->setTranslation($values['translation']);
-    }
-    if (isset($values['comment'])){
-      $this->setComment($values['comment']);
-    }
-    if (isset($this->_source) &&
-        strpos($this->_source, LOCALE_PLURAL_DELIMITER) !== FALSE) {
-      $this->setSource(explode(LOCALE_PLURAL_DELIMITER, $this->_source));
-      $this->setTranslation(explode(LOCALE_PLURAL_DELIMITER, $this->_translation));
-      $this->setPlural(count($this->_translation) > 1);
-    }
-  }
-
-  /**
-   * Output the PoItem as a string.
-   */
-  public function __toString() {
-    return $this->formatItem();
-  }
-
-  /**
-   * Format the POItem as a string.
-   */
-  private function formatItem() {
-    $output = '';
-
-    // Format string context.
-    if (!empty($this->_context)) {
-      $output .= 'msgctxt ' . $this->formatString($this->_context);
-    }
-
-    // Format translation.
-    if ($this->_plural) {
-      $output .= $this->formatPlural();
-    }
-    else {
-      $output .= $this->formatSingular();
-    }
-
-    // Add one empty line to separate the translations.
-    $output .= "\n";
-
-    return $output;
-  }
-
-  /**
-   * Formats a plural translation.
-   */
-  private function formatPlural() {
-    $output = '';
-
-    // Format source strings.
-    $output .= 'msgid ' . $this->formatString($this->_source[0]);
-    $output .= 'msgid_plural ' . $this->formatString($this->_source[1]);
-
-    foreach ($this->_translation as $i => $trans) {
-      if (isset($this->_translation[$i])) {
-        $output .= 'msgstr[' . $i . '] ' . $this->formatString($trans);
-      }
-      else {
-        $output .= 'msgstr[' . $i . '] ""' . "\n";
-      }
-    }
-
-    return $output;
-  }
-
-  /**
-   * Formats a singular translation.
-   */
-  private function formatSingular() {
-    $output = '';
-    $output .= 'msgid '. $this->formatString($this->_source);
-    $output .= 'msgstr '. (isset($this->_translation) ? $this->formatString($this->_translation) : '');
-    return $output;
-  }
-
-  /**
-   * Formats a string for output on multiple lines.
-   */
-  private function formatString($string) {
-    // Escape characters for processing.
-    $string = addcslashes($string, "\0..\37\\\"");
-
-    // Always include a line break after the explicit \n line breaks from
-    // the source string. Otherwise wrap at 70 chars to accommodate the extra
-    // format overhead too.
-    $parts = explode("\n", wordwrap(str_replace('\n', "\\n\n", $string), 70, " \n"));
-
-    // Multiline string should be exported starting with a "" and newline to
-    // have all lines aligned on the same column.
-    if (count($parts) > 1) {
-      return "\"\"\n\"" . implode("\"\n\"", $parts) . "\"\n";
-    }
-    // Single line strings are output on the same line.
-    else {
-      return "\"$parts[0]\"\n";
-    }
-  }
-
-}
diff --git a/core/lib/Drupal/Component/Gettext/PoMemoryWriter.php b/core/lib/Drupal/Component/Gettext/PoMemoryWriter.php
deleted file mode 100644
index e304451..0000000
--- a/core/lib/Drupal/Component/Gettext/PoMemoryWriter.php
+++ /dev/null
@@ -1,95 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Component\Gettext\PoMemoryWriter.
- */
-
-namespace Drupal\Component\Gettext;
-
-use Drupal\Component\Gettext\PoWriterInterface;
-use Drupal\Component\Gettext\PoHeader;
-use Drupal\Component\Gettext\PoItem;
-
-/**
- * Defines a Gettext PO memory writer, to be used by the installer.
- */
-class PoMemoryWriter implements PoWriterInterface {
-
-  /**
-   * Array to hold all PoItem elements.
-   *
-   * @var array
-   */
-  private $_items;
-
-  /**
-   * Constructor, initialize empty items.
-   */
-  function __construct() {
-    $this->_items = array();
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoWriterInterface::writeItem().
-   */
-  public function writeItem(PoItem $item) {
-    if (is_array($item->source)) {
-      $item->source = implode(LOCALE_PLURAL_DELIMITER, $item->source);
-      $item->translation = implode(LOCALE_PLURAL_DELIMITER, $item->translation);
-    }
-    $this->_items[isset($item->context) ? $item->context : ''][$item->source] = $item->translation;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoWriterInterface::writeItems().
-   */
-  public function writeItems(PoReaderInterface $reader, $count = -1) {
-    $forever = $count == -1;
-    while (($count-- > 0 || $forever) && ($item = $reader->readItem())) {
-      $this->writeItem($item);
-    }
-  }
-
-  /**
-   * Get all stored PoItem's.
-   *
-   * @return array PoItem
-   */
-  public function getData() {
-    return $this->_items;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface:setLangcode().
-   *
-   * Not implemented. Not relevant for the MemoryWriter.
-   */
-  function setLangcode($langcode) {
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface:getLangcode().
-   *
-   * Not implemented. Not relevant for the MemoryWriter.
-   */
-  function getLangcode() {
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface:getHeader().
-   *
-   * Not implemented. Not relevant for the MemoryWriter.
-   */
-  function getHeader() {
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface:setHeader().
-   *
-   * Not implemented. Not relevant for the MemoryWriter.
-   */
-  function setHeader(PoHeader $header) {
-  }
-
-}
diff --git a/core/lib/Drupal/Component/Gettext/PoMetadataInterface.php b/core/lib/Drupal/Component/Gettext/PoMetadataInterface.php
deleted file mode 100644
index f5bb3db..0000000
--- a/core/lib/Drupal/Component/Gettext/PoMetadataInterface.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Component\Gettext\PoMetadataInterface.
- */
-
-namespace Drupal\Component\Gettext;
-
-use Drupal\Component\Gettext\PoHeader;
-
-/**
- * Methods required for both reader and writer implementations.
- *
- * @see Drupal\Component\Gettext\PoReaderInterface
- * @see Drupal\Component\Gettext\PoWriterInterface
- */
-interface PoMetadataInterface {
-
-  /**
-   * Set language code.
-   *
-   * @param string $langcode
-   *   Language code string.
-   */
-  function setLangcode($langcode);
-
-  /**
-   * Get language code.
-   *
-   * @return string
-   *   Language code string.
-   */
-  function getLangcode();
-
-  /**
-   * Set header metadata.
-   *
-   * @param Drupal\Component\Gettext\PoHeader $header
-   *   Header object representing metadata in a PO header.
-   */
-  function setHeader(PoHeader $header);
-
-  /**
-   * Get header metadata.
-   *
-   * @return Drupal\Component\Gettext\PoHeader $header
-   *   Header instance representing metadata in a PO header.
-   */
-  function getHeader();
-}
diff --git a/core/lib/Drupal/Component/Gettext/PoReaderInterface.php b/core/lib/Drupal/Component/Gettext/PoReaderInterface.php
deleted file mode 100644
index e9c0125..0000000
--- a/core/lib/Drupal/Component/Gettext/PoReaderInterface.php
+++ /dev/null
@@ -1,24 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Component\Gettext\PoReaderInterface.
- */
-
-namespace Drupal\Component\Gettext;
-
-use Drupal\Component\Gettext\PoMetadataInterface;
-
-/**
- * Shared interface definition for all Gettext PO Readers.
- */
-interface PoReaderInterface extends PoMetadataInterface {
-
-  /**
-   * Reads and returns a PoItem (source/translation pair).
-   *
-   * @return Drupal\Component\Gettext\PoItem
-   *   Wrapper for item data instance.
-   */
-  function readItem();
-}
diff --git a/core/lib/Drupal/Component/Gettext/PoStreamInterface.php b/core/lib/Drupal/Component/Gettext/PoStreamInterface.php
deleted file mode 100644
index c9f9e34..0000000
--- a/core/lib/Drupal/Component/Gettext/PoStreamInterface.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Component\Gettext\PoStreamInterface.
- */
-
-namespace Drupal\Component\Gettext;
-
-/**
- * Common functions for file/stream based PO readers/writers.
- *
- * @see PoReaderInterface
- * @see PoWriterInterface
- */
-interface PoStreamInterface {
-
-  /**
-   * Open the stream. Set the URI for the stream earlier with setURI().
-   */
-  function open();
-
-  /**
-   * Close the stream.
-   */
-  function close();
-
-  /**
-   * Get the URI of the PO stream that is being read or written.
-   *
-   * @return
-   *   URI string for this stream.
-   */
-  function getURI();
-
-  /**
-   * Set the URI of the PO stream that is going to be read or written.
-   *
-   * @param $uri
-   *   URI string to set for this stream.
-   */
-  function setURI($uri);
-}
diff --git a/core/lib/Drupal/Component/Gettext/PoStreamReader.php b/core/lib/Drupal/Component/Gettext/PoStreamReader.php
deleted file mode 100644
index bd916a7..0000000
--- a/core/lib/Drupal/Component/Gettext/PoStreamReader.php
+++ /dev/null
@@ -1,589 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Component\Gettext\PoStreamReader.
- */
-
-namespace Drupal\Component\Gettext;
-
-use Drupal\Component\Gettext\PoReaderInterface;
-use Drupal\Component\Gettext\PoStreamInterface;
-use Drupal\Component\Gettext\PoHeader;
-
-/**
- * Implements Gettext PO stream reader.
- *
- * The PO file format parsing is implemented according to the documentation at
- * http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files
- */
-class PoStreamReader implements PoStreamInterface, PoReaderInterface {
-
-  /**
-   * Source line number of the stream being parsed.
-   *
-   * @var int
-   */
-  private $_line_number = 0;
-
-  /**
-   * Parser context for the stream reader state machine.
-   *
-   * Possible contexts are:
-   *  - 'COMMENT' (#)
-   *  - 'MSGID' (msgid)
-   *  - 'MSGID_PLURAL' (msgid_plural)
-   *  - 'MSGCTXT' (msgctxt)
-   *  - 'MSGSTR' (msgstr or msgstr[])
-   *  - 'MSGSTR_ARR' (msgstr_arg)
-   *
-   * @var string
-   */
-  private $_context = 'COMMENT';
-
-  /**
-   * Current entry being read. Incomplete.
-   *
-   * @var array
-   */
-  private $_current_item = array();
-
-  /**
-   * Current plural index for plural translations.
-   *
-   * @var int
-   */
-  private $_current_plural_index = 0;
-
-  /**
-   * URI of the PO stream that is being read.
-   *
-   * @var string
-   */
-  private $_uri = '';
-
-  /**
-   * Language code for the PO stream being read.
-   *
-   * @var string
-   */
-  private $_langcode = NULL;
-
-  /**
-   * Size of the current PO stream.
-   *
-   * @var int
-   */
-  private $_size;
-
-  /**
-   * File handle of the current PO stream.
-   *
-   * @var resource
-   */
-  private $_fd;
-
-  /**
-   * The PO stream header.
-   *
-   * @var Drupal\Component\Gettext\PoHeader
-   */
-  private $_header;
-
-  /**
-   * Object wrapper for the last read source/translation pair.
-   *
-   * @var Drupal\Component\Gettext\PoItem
-   */
-  private $_last_item;
-
-  /**
-   * Indicator of whether the stream reading is finished.
-   *
-   * @var boolean
-   */
-  private $_finished;
-
-  /**
-   * Array of translated error strings recorded on reading this stream so far.
-   *
-   * @var array
-   */
-  private $_errors;
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface::getLangcode().
-   */
-  public function getLangcode() {
-    return $this->_langcode;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface::setLangcode().
-   */
-  public function setLangcode($langcode) {
-    $this->_langcode = $langcode;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface::getHeader().
-   */
-  public function getHeader() {
-    return $this->_header;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface::setHeader().
-   *
-   * Not applicable to stream reading and therefore not implemented.
-   */
-  public function setHeader(PoHeader $header) {
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoStreamInterface::getURI().
-   */
-  public function getURI() {
-    return $this->_uri;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoStreamInterface::setURI().
-   */
-  public function setURI($uri) {
-    $this->_uri = $uri;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoStreamInterface::open().
-   *
-   * Opens the stream and reads the header. The stream is ready for reading
-   * items after.
-   *
-   * @throws Exception
-   *   If the URI is not yet set.
-   */
-  public function open() {
-    if (!empty($this->_uri)) {
-      $this->_fd = fopen($this->_uri, 'rb');
-      $this->_size = ftell($this->_fd);
-      $this->readHeader();
-    }
-    else {
-      throw new Exception('Cannot open stream without URI set.');
-    }
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoStreamInterface::close().
-   *
-   * @throws Exception
-   *   If the stream is not open.
-   */
-  public function close() {
-    if ($this->_fd) {
-      fclose($this->_fd);
-    }
-    else {
-      throw new Exception('Cannot close stream that is not open.');
-    }
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoReaderInterface::readItem().
-   */
-  public function readItem() {
-    // Clear out the last item.
-    $this->_last_item = NULL;
-
-    // Read until finished with the stream or a complete item was identified.
-    while (!$this->_finished && is_null($this->_last_item)) {
-      $this->readLine();
-    }
-
-    return $this->_last_item;
-  }
-
-  /**
-   * Read the header from the PO stream.
-   *
-   * The header is a special case PoItem, using the empty string as source and
-   * key-value pairs as translation. We just reuse the item reader logic to
-   * read the header.
-   */
-  private function readHeader() {
-    $item = $this->readItem();
-    $header = new PoHeader;
-    $header->setFromString(trim($item->getTranslation()));
-    $this->_header = $header;
-  }
-
-  /**
-   * Reads a line from the PO stream and stores data internally.
-   *
-   * Expands $this->_current_item based on new data for the current item. If
-   * this line ends the current item, it is saved with setItemFromArray() with
-   * data from $this->_current_item.
-   *
-   * An internal state machine is maintained in this reader using $this->_context
-   * as the reading state. PO items are inbetween COMMENT states (when items have
-   * at least one line or comment inbetween them or indicated by MSGSTR or
-   * MSGSTR_ARR followed immediately by an MSGID or MSGCTXT (when items closely
-   * follow each other).
-   *
-   * @return
-   *   FALSE if an error was logged, NULL otherwise. The errors are considered
-   *   non-blocking, so reading can continue, while the errors are collected
-   *   for later presentation.
-   */
-  private function readLine() {
-    // Read a line and set the stream finished indicator if it was not
-    // possible anymore.
-    $line = fgets($this->_fd);
-    $this->_finished = ($line === FALSE);
-
-    if (!$this->_finished) {
-
-      if ($this->_line_number == 0) {
-        // The first line might come with a UTF-8 BOM, which should be removed.
-        $line = str_replace("\xEF\xBB\xBF", '', $line);
-        // Current plurality for 'msgstr[]'.
-        $this->_current_plural_index = 0;
-      }
-
-      // Track the line number for error reporting.
-      $this->_line_number++;
-
-      // Initialize common values for error logging.
-      $log_vars = array(
-        '%uri' => $this->getURI(),
-        '%line' => $this->_line_number,
-      );
-      $t = get_t();
-
-      // Trim away the linefeed. \\n might appear at the end of the string if
-      // another line continuing the same string follows. We can remove that.
-      $line = trim(strtr($line, array("\\\n" => "")));
-
-      if (!strncmp('#', $line, 1)) {
-        // Lines starting with '#' are comments.
-
-        if ($this->_context == 'COMMENT') {
-          // Already in comment context, add to current comment.
-          $this->_current_item['#'][] = substr($line, 1);
-        }
-        elseif (($this->_context == 'MSGSTR') || ($this->_context == 'MSGSTR_ARR')) {
-          // We are currently in string context, save current item.
-          $this->setItemFromArray($this->_current_item);
-
-          // Start a new entry for the comment.
-          $this->_current_item = array();
-          $this->_current_item['#'][] = substr($line, 1);
-
-          $this->_context = 'COMMENT';
-          return;
-        }
-        else {
-          // A comment following any other context is a syntax error.
-          $this->_errors[] = $t('The translation stream %uri contains an error: "msgstr" was expected but not found on line %line.', $log_vars);
-          return FALSE;
-        }
-        return;
-      }
-      elseif (!strncmp('msgid_plural', $line, 12)) {
-        // A plural form for the current source string.
-
-        if ($this->_context != 'MSGID') {
-          // A plural form can only be added to an msgid directly.
-          $this->_errors[] = $t('The translation stream %uri contains an error: "msgid_plural" was expected but not found on line %line.', $log_vars);
-          return FALSE;
-        }
-
-        // Remove 'msgid_plural' and trim away whitespace.
-        $line = trim(substr($line, 12));
-
-        // Only the plural source string is left, parse it.
-        $quoted = $this->parseQuoted($line);
-        if ($quoted === FALSE) {
-          // The plural form must be wrapped in quotes.
-          $this->_errors[] = $t('The translation stream %uri contains a syntax error on line %line.', $log_vars);
-          return FALSE;
-        }
-
-        // Append the plural source to the current entry.
-        if (is_string($this->_current_item['msgid'])) {
-          // The first value was stored as string. Now we know the context is
-          // plural, it is converted to array.
-          $this->_current_item['msgid'] = array($this->_current_item['msgid']);
-        }
-        $this->_current_item['msgid'][] = $quoted;
-
-        $this->_context = 'MSGID_PLURAL';
-        return;
-      }
-      elseif (!strncmp('msgid', $line, 5)) {
-        // Starting a new message.
-
-        if (($this->_context == 'MSGSTR') || ($this->_context == 'MSGSTR_ARR')) {
-          // We are currently in string context, save current item.
-          $this->setItemFromArray($this->_current_item);
-
-          // Start a new context for the msgid.
-          $this->_current_item = array();
-        }
-        elseif ($this->_context == 'MSGID') {
-          // We are currently already in the context, meaning we passed an id with no data.
-          $this->_errors[] = $t('The translation stream %uri contains an error: "msgid" is unexpected on line %line.', $log_vars);
-          return FALSE;
-        }
-
-        // Remove 'msgid' and trim away whitespace.
-        $line = trim(substr($line, 5));
-
-        // Only the message id string is left, parse it.
-        $quoted = $this->parseQuoted($line);
-        if ($quoted === FALSE) {
-          // The message id must be wrapped in quotes.
-          $this->_errors[] = $t('The translation stream %uri contains an error: invalid format for "msgid" on line %line.', $log_vars, $log_vars);
-          return FALSE;
-        }
-
-        $this->_current_item['msgid'] = $quoted;
-        $this->_context = 'MSGID';
-        return;
-      }
-      elseif (!strncmp('msgctxt', $line, 7)) {
-        // Starting a new context.
-
-        if (($this->_context == 'MSGSTR') || ($this->_context == 'MSGSTR_ARR')) {
-          // We are currently in string context, save current item.
-          $this->setItemFromArray($this->_current_item);
-          $this->_current_item = array();
-        }
-        elseif (!empty($this->_current_item['msgctxt'])) {
-          // A context cannot apply to another context.
-          $this->_errors[] = $t('The translation stream %uri contains an error: "msgctxt" is unexpected on line %line.', $log_vars);
-          return FALSE;
-        }
-
-        // Remove 'msgctxt' and trim away whitespaces.
-        $line = trim(substr($line, 7));
-
-        // Only the msgctxt string is left, parse it.
-        $quoted = $this->parseQuoted($line);
-        if ($quoted === FALSE) {
-          // The context string must be quoted.
-          $this->_errors[] = $t('The translation stream %uri contains an error: invalid format for "msgctxt" on line %line.', $log_vars);
-          return FALSE;
-        }
-
-        $this->_current_item['msgctxt'] = $quoted;
-
-        $this->_context = 'MSGCTXT';
-        return;
-      }
-      elseif (!strncmp('msgstr[', $line, 7)) {
-        // A message string for a specific plurality.
-
-        if (($this->_context != 'MSGID') &&
-            ($this->_context != 'MSGCTXT') &&
-            ($this->_context != 'MSGID_PLURAL') &&
-            ($this->_context != 'MSGSTR_ARR')) {
-          // Plural message strings must come after msgid, msgxtxt,
-          // msgid_plural, or other msgstr[] entries.
-          $this->_errors[] = $t('The translation stream %uri contains an error: "msgstr[]" is unexpected on line %line.', $log_vars);
-          return FALSE;
-        }
-
-        // Ensure the plurality is terminated.
-        if (strpos($line, ']') === FALSE) {
-          $this->_errors[] = $t('The translation stream %uri contains an error: invalid format for "msgstr[]" on line %line.', $log_vars);
-          return FALSE;
-        }
-
-        // Extract the plurality.
-        $frombracket = strstr($line, '[');
-        $this->_current_plural_index = substr($frombracket, 1, strpos($frombracket, ']') - 1);
-
-        // Skip to the next whitespace and trim away any further whitespace,
-        // bringing $line to the message text only.
-        $line = trim(strstr($line, " "));
-
-        $quoted = $this->parseQuoted($line);
-        if ($quoted === FALSE) {
-          // The string must be quoted.
-          $this->_errors[] = $t('The translation stream %uri contains an error: invalid format for "msgstr[]" on line %line.', $log_vars);
-          return FALSE;
-        }
-        if (!isset($this->_current_item['msgstr']) || !is_array($this->_current_item['msgstr'])) {
-          $this->_current_item['msgstr'] = array();
-        }
-
-        $this->_current_item['msgstr'][$this->_current_plural_index] = $quoted;
-
-        $this->_context = 'MSGSTR_ARR';
-        return;
-      }
-      elseif (!strncmp("msgstr", $line, 6)) {
-        // A string pair for an msgidid (with optional context).
-
-        if (($this->_context != 'MSGID') && ($this->_context != 'MSGCTXT')) {
-          // Strings are only valid within an id or context scope.
-          $this->_errors[] = $t('The translation stream %uri contains an error: "msgstr" is unexpected on line %line.', $log_vars);
-          return FALSE;
-        }
-
-        // Remove 'msgstr' and trim away away whitespaces.
-        $line = trim(substr($line, 6));
-
-        // Only the msgstr string is left, parse it.
-        $quoted = $this->parseQuoted($line);
-        if ($quoted === FALSE) {
-          // The string must be quoted.
-          $this->_errors[] = $t('The translation stream %uri contains an error: invalid format for "msgstr" on line %line.', $log_vars);
-          return FALSE;
-        }
-
-        $this->_current_item['msgstr'] = $quoted;
-
-        $this->_context = 'MSGSTR';
-        return;
-      }
-      elseif ($line != '') {
-        // Anything that is not a token may be a continuation of a previous token.
-
-        $quoted = $this->parseQuoted($line);
-        if ($quoted === FALSE) {
-          // This string must be quoted.
-          $this->_errors[] = $t('The translation stream %uri contains an error: string continuation expected on line %line.', $log_vars);
-          return FALSE;
-        }
-
-        // Append the string to the current item.
-        if (($this->_context == 'MSGID') || ($this->_context == 'MSGID_PLURAL')) {
-          if (is_array($this->_current_item['msgid'])) {
-            // Add string to last array element for plural sources.
-            $last_index = count($this->_current_item['msgid']) - 1;
-            $this->_current_item['msgid'][$last_index] .= $quoted;
-          }
-          else {
-            // Singular source, just append the string.
-            $this->_current_item['msgid'] .= $quoted;
-          }
-        }
-        elseif ($this->_context == 'MSGCTXT') {
-          // Multiline context name.
-          $this->_current_item['msgctxt'] .= $quoted;
-        }
-        elseif ($this->_context == 'MSGSTR') {
-          // Multiline translation string.
-          $this->_current_item['msgstr'] .= $quoted;
-        }
-        elseif ($this->_context == 'MSGSTR_ARR') {
-          // Multiline plural translation string.
-          $this->_current_item['msgstr'][$this->_current_plural_index] .= $quoted;
-        }
-        else {
-          // No valid context to append to.
-          $this->_errors[] = $t('The translation stream %uri contains an error: unexpected string on line %line.', $log_vars);
-          return FALSE;
-        }
-        return;
-      }
-    }
-
-    // Empty line read or EOF of PO stream, close out the last entry.
-    if (($this->_context == 'MSGSTR') || ($this->_context == 'MSGSTR_ARR')) {
-      $this->setItemFromArray($this->_current_item);
-      $this->_current_item = array();
-    }
-    elseif ($this->_context != 'COMMENT') {
-      $this->_errors[] = $t('The translation stream %uri ended unexpectedly at line %line.', $log_vars);
-      return FALSE;
-    }
-  }
-
-  /**
-   * Store the parsed values as a PoItem object.
-   */
-  public function setItemFromArray($value) {
-    $plural = FALSE;
-
-    $comments = '';
-    if (isset($value['#'])) {
-      $comments = $this->shortenComments($value['#']);
-    }
-
-    if (is_array($value['msgstr'])) {
-      // Sort plural variants by their form index.
-      ksort($value['msgstr']);
-      $plural = TRUE;
-    }
-
-    $item = new PoItem();
-    $item->setContext(isset($value['msgctxt']) ? $value['msgctxt'] : '');
-    $item->setSource($value['msgid']);
-    $item->setTranslation($value['msgstr']);
-    $item->setPlural($plural);
-    $item->setComment($comments);
-    $item->setLangcode($this->_langcode);
-
-    $this->_last_item = $item;
-
-    $this->_context = 'COMMENT';
-  }
-
-  /**
-   * Parses a string in quotes.
-   *
-   * @param $string
-   *   A string specified with enclosing quotes.
-   *
-   * @return
-   *   The string parsed from inside the quotes.
-   */
-  function parseQuoted($string) {
-    if (substr($string, 0, 1) != substr($string, -1, 1)) {
-      // Start and end quotes must be the same.
-      return FALSE;
-    }
-    $quote = substr($string, 0, 1);
-    $string = substr($string, 1, -1);
-    if ($quote == '"') {
-      // Double quotes: strip slashes.
-      return stripcslashes($string);
-    }
-    elseif ($quote == "'") {
-      // Simple quote: return as-is.
-      return $string;
-    }
-    else {
-      // Unrecognized quote.
-      return FALSE;
-    }
-  }
-
-  /**
-   * Generates a short, one-string version of the passed comment array.
-   *
-   * @param $comment
-   *   An array of strings containing a comment.
-   *
-   * @return
-   *   Short one-string version of the comment.
-   */
-  private function shortenComments($comment) {
-    $comm = '';
-    while (count($comment)) {
-      $test = $comm . substr(array_shift($comment), 1) . ', ';
-      if (strlen($comm) < 130) {
-        $comm = $test;
-      }
-      else {
-        break;
-      }
-    }
-    return trim(substr($comm, 0, -2));
-  }
-
-}
diff --git a/core/lib/Drupal/Component/Gettext/PoStreamWriter.php b/core/lib/Drupal/Component/Gettext/PoStreamWriter.php
deleted file mode 100644
index d066307..0000000
--- a/core/lib/Drupal/Component/Gettext/PoStreamWriter.php
+++ /dev/null
@@ -1,168 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Component\Gettext\PoStreamWriter.
- */
-
-namespace Drupal\Component\Gettext;
-
-use Drupal\Component\Gettext\PoHeader;
-use Drupal\Component\Gettext\PoItem;
-use Drupal\Component\Gettext\PoReaderInterface;
-use Drupal\Component\Gettext\PoWriterInterface;
-use Drupal\Component\Gettext\PoStreamInterface;
-
-/**
- * Defines a Gettext PO stream writer.
- */
-class PoStreamWriter implements PoWriterInterface, PoStreamInterface {
-
-  /**
-   * URI of the PO stream that is being written.
-   *
-   * @var string
-   */
-  private $_uri;
-
-  /**
-   * The Gettext PO header.
-   *
-   * @var Drupal\Component\Gettext\PoHeader
-   */
-  private $_header;
-
-  /**
-   * File handle of the current PO stream.
-   *
-   * @var resource
-   */
-  private $_fd;
-
-  /**
-   * Get the PO header of the current stream.
-   *
-   * @return Drupal\Component\Gettext\PoHeader
-   *   The Gettext PO header.
-   */
-  public function getHeader() {
-    return $this->_header;
-  }
-
-  /**
-   * Set the PO header for the current stream.
-   *
-   * @param Drupal\Component\Gettext\PoHeader $header
-   *   The Gettext PO header to set.
-   */
-  public function setHeader(PoHeader $header) {
-    $this->_header = $header;
-  }
-
-  /**
-   * Get the current language code used.
-   *
-   * @return string
-   *   The language code.
-   */
-  public function getLangcode() {
-    return $this->_langcode;
-  }
-
-  /**
-   * Set the language code.
-   *
-   * @param string $langcode
-   *   The language code.
-   */
-  public function setLangcode($langcode) {
-    $this->_langcode = $langcode;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoStreamInterface::open().
-   */
-  public function open() {
-    // Open in write mode. Will overwrite the stream if it already exists.
-    $this->_fd = fopen($this->getURI(), 'w');
-    // Write the header at the start.
-    $this->writeHeader();
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoStreamInterface::close().
-   *
-   * @throws Exception
-   *   If the stream is not open.
-   */
-  public function close() {
-    if ($this->_fd) {
-      fclose($this->_fd);
-    }
-    else {
-      throw new Exception('Cannot close stream that is not open.');
-    }
-  }
-
-  /**
-   * Write data to the stream.
-   *
-   * @param string $data
-   *   Piece of string to write to the stream. If the value is not directly a
-   *   string, casting will happen in writing.
-   *
-   * @throws Exception
-   *   If writing the data is not possible.
-   */
-  private function write($data) {
-    $result = fputs($this->_fd, $data);
-    if ($result === FALSE) {
-      throw new Exception('Unable to write data: ' . substr($data, 0, 20));
-    }
-  }
-
-  /**
-   * Write the PO header to the stream.
-   */
-  private function writeHeader() {
-    $this->write($this->_header);
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoWriterInterface::writeItem().
-   */
-  public function writeItem(PoItem $item) {
-    $this->write($item);
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoWriterInterface::writeItems().
-   */
-  public function writeItems(PoReaderInterface $reader, $count = -1) {
-    $forever = $count == -1;
-    while (($count-- > 0 || $forever) && ($item = $reader->readItem())) {
-      $this->writeItem($item);
-    }
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoStreamInterface::getURI().
-   *
-   * @throws Exception
-   *   If the URI is not set.
-   */
-  public function getURI() {
-    if (empty($this->_uri)) {
-      throw new Exception('No URI set.');
-    }
-    return $this->_uri;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoStreamInterface::setURI().
-   */
-  public function setURI($uri) {
-    $this->_uri = $uri;
-  }
-
-}
diff --git a/core/lib/Drupal/Component/Gettext/PoWriterInterface.php b/core/lib/Drupal/Component/Gettext/PoWriterInterface.php
deleted file mode 100644
index 2a2348f..0000000
--- a/core/lib/Drupal/Component/Gettext/PoWriterInterface.php
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\Component\Gettext\PoWriterInterface.
- */
-
-namespace Drupal\Component\Gettext;
-
-use Drupal\Component\Gettext\PoMetadataInterface;
-use Drupal\Component\Gettext\PoItem;
-
-/**
- * Shared interface definition for all Gettext PO Writers.
- */
-interface PoWriterInterface extends PoMetadataInterface {
-
-  /**
-   * Writes the given item.
-   *
-   * @param PoItem $item
-   *   One specific item to write.
-   */
-  function writeItem(PoItem $item);
-
-  /**
-   * Writes all or the given amount of items.
-   *
-   * @param PoReaderInterface $reader
-   *   Reader to read PoItems from.
-   * @param $count
-   *   Amount of items to read from $reader to write. If -1, all items are
-   *   read from $reader.
-   */
-  function writeItems(PoReaderInterface $reader, $count = -1);
-}
diff --git a/core/lib/Drupal/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
new file mode 100644
index 0000000..2c4f14a
--- /dev/null
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -0,0 +1,100 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\CoreBundle.
+ */
+
+namespace Drupal\Core;
+
+use Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Scope;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+use Symfony\Component\DependencyInjection\Compiler\PassConfig;
+
+/**
+ * Bundle class for mandatory core services.
+ *
+ * This is where Drupal core registers all of its services to the Dependency
+ * Injection Container. Modules wishing to register services to the container
+ * should extend Symfony's Bundle class directly, not this class.
+ */
+class CoreBundle extends Bundle
+{
+  public function build(ContainerBuilder $container) {
+
+    // Add a 'request' scope for services that depend on the Request object.
+    $container->addScope(new Scope('request'));
+
+    $container->setParameter('config.storage.info', array(
+      'Drupal\Core\Config\DatabaseStorage' => array(
+        'connection' => 'default',
+        'target' => 'default',
+        'read' => TRUE,
+        'write' => TRUE,
+      ),
+      'Drupal\Core\Config\FileStorage' => array(
+        'directory' => config_get_config_directory(),
+        'read' => TRUE,
+        'write' => FALSE,
+      ),
+    ));
+    $container->register('config.storage.dispatcher', 'Drupal\Core\Config\StorageDispatcher')
+      ->addArgument('%config.storage.info%');
+    $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory')
+      ->addArgument(new Reference('config.storage.dispatcher'));
+    $container->register('dispatcher', 'Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher')
+      ->addArgument(new Reference('service_container'));
+    $container->register('resolver', 'Symfony\Component\HttpKernel\Controller\ControllerResolver');
+    $container->register('http_kernel', 'Drupal\Core\HttpKernel')
+      ->addArgument(new Reference('dispatcher'))
+      ->addArgument(new Reference('service_container'))
+      ->addArgument(new Reference('resolver'));
+    $container->register('matcher', 'Drupal\Core\LegacyUrlMatcher');
+    $container->register('router_listener', 'Drupal\Core\EventSubscriber\RouterListener')
+      ->addArgument(new Reference('matcher'))
+      ->addTag('kernel.event_subscriber');
+    $container->register('content_negotiation', 'Drupal\Core\ContentNegotiation');
+    $container->register('view_subscriber', 'Drupal\Core\EventSubscriber\ViewSubscriber')
+      ->addArgument(new Reference('content_negotiation'))
+      ->addTag('kernel.event_subscriber');
+    $container->register('access_subscriber', 'Drupal\Core\EventSubscriber\AccessSubscriber')
+      ->addTag('kernel.event_subscriber');
+    $container->register('maintenance_mode_subscriber', 'Drupal\Core\EventSubscriber\MaintenanceModeSubscriber')
+      ->addTag('kernel.event_subscriber');
+    $container->register('path_subscriber', 'Drupal\Core\EventSubscriber\PathSubscriber')
+      ->addTag('kernel.event_subscriber');
+    $container->register('legacy_request_subscriber', 'Drupal\Core\EventSubscriber\LegacyRequestSubscriber')
+      ->addTag('kernel.event_subscriber');
+    $container->register('legacy_controller_subscriber', 'Drupal\Core\EventSubscriber\LegacyControllerSubscriber')
+      ->addTag('kernel.event_subscriber');
+    $container->register('finish_response_subscriber', 'Drupal\Core\EventSubscriber\FinishResponseSubscriber')
+      ->addTag('kernel.event_subscriber');
+    $container->register('request_close_subscriber', 'Drupal\Core\EventSubscriber\RequestCloseSubscriber')
+      ->addTag('kernel.event_subscriber');
+    $container->register('database', 'Drupal\Core\Database\Connection')
+      ->setFactoryClass('Drupal\Core\Database\Database')
+      ->setFactoryMethod('getConnection')
+      ->addArgument('default');
+    $container->register('database.slave', 'Drupal\Core\Database\Connection')
+      ->setFactoryClass('Drupal\Core\Database\Database')
+      ->setFactoryMethod('getConnection')
+      ->addArgument('slave');
+    $container->register('exception_listener', 'Symfony\Component\HttpKernel\EventListener\ExceptionListener')
+      ->addTag('kernel.event_subscriber')
+      ->addArgument(new Reference('service_container'))
+      ->setFactoryClass('Drupal\Core\ExceptionController')
+      ->setFactoryMethod('getExceptionListener');
+    $container->register('request', 'Symfony\Component\HttpFoundation\Request')
+      ->setSynthetic(TRUE);
+    $container->register('language_manager', 'Drupal\Core\Language\LanguageManager')
+      ->addArgument(new Reference('request'))
+      ->setScope('request');
+
+    // Add a compiler pass for registering event subscribers.
+    $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING);
+  }
+}
diff --git a/core/lib/Drupal/Core/DependencyInjection/BootstrapContainer.php b/core/lib/Drupal/Core/DependencyInjection/BootstrapContainer.php
new file mode 100644
index 0000000..865c8e8
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/BootstrapContainer.php
@@ -0,0 +1,55 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\DependencyInjection\BootstrapContainer.
+ */
+
+namespace Drupal\Core\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\Parameter;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
+
+/**
+ * This precompiled container will be used when a full bootstrap happens outside
+ * the scope of a normal page request.
+ */
+class BootstrapContainer extends Container
+{
+  private $config_dir;
+  public function __construct()
+  {
+    parent::__construct(new ParameterBag($this->getDefaultParameters()));
+    $this->config_dir = config_get_config_directory();
+  }
+  protected function getConfig_FactoryService()
+  {
+    return $this->services['config.factory'] = new \Drupal\Core\Config\ConfigFactory($this->get('config.storage.dispatcher'));
+  }
+  protected function getConfig_Storage_DispatcherService()
+  {
+    return $this->services['config.storage.dispatcher'] = new \Drupal\Core\Config\StorageDispatcher(array('Drupal\\Core\\Config\\DatabaseStorage' => array('connection' => 'default', 'target' => 'default', 'read' => true, 'write' => true), 'Drupal\\Core\\Config\\FileStorage' => array('directory' => $this->config_dir, 'read' => true, 'write' => false)));
+  }
+
+  protected function getDefaultParameters()
+  {
+    return array(
+      'config.storage.info' => array(
+        'Drupal\\Core\\Config\\DatabaseStorage' => array(
+          'connection' => 'default',
+          'target' => 'default',
+          'read' => true,
+          'write' => true,
+        ),
+        'Drupal\\Core\\Config\\FileStorage' => array(
+            'directory' => $this->config_dir,
+            'read' => true,
+            'write' => false,
+        ),
+      ),
+    );
+  }
+}
diff --git a/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php
new file mode 100644
index 0000000..55343dc
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php
@@ -0,0 +1,37 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass.
+ */
+
+namespace Drupal\Core\DependencyInjection\Compiler;
+
+use ReflectionClass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+
+class RegisterKernelListenersPass implements CompilerPassInterface
+{
+  public function process(ContainerBuilder $container)
+  {
+    if (!$container->hasDefinition('dispatcher')) {
+      return;
+    }
+
+    $definition = $container->getDefinition('dispatcher');
+
+    foreach ($container->findTaggedServiceIds('kernel.event_subscriber') as $id => $attributes) {
+
+      // We must assume that the class value has been correcly filled, even if the service is created by a factory
+      $class = $container->getDefinition($id)->getClass();
+
+      $refClass = new ReflectionClass($class);
+      $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface';
+      if (!$refClass->implementsInterface($interface)) {
+        throw new \InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface));
+      }
+      $definition->addMethodCall('addSubscriberService', array($id, $class));
+    }
+  }
+}
diff --git a/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php b/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php
index a82f5b6..dfccb74 100644
--- a/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php
+++ b/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php
@@ -7,113 +7,29 @@
 
 namespace Drupal\Core\DependencyInjection;
 
-use Drupal\Core\ContentNegotiation;
-use Drupal\Core\EventSubscriber\AccessSubscriber;
-use Drupal\Core\EventSubscriber\FinishResponseSubscriber;
-use Drupal\Core\EventSubscriber\LegacyControllerSubscriber;
-use Drupal\Core\EventSubscriber\LegacyRequestSubscriber;
-use Drupal\Core\EventSubscriber\MaintenanceModeSubscriber;
-use Drupal\Core\EventSubscriber\PathSubscriber;
-use Drupal\Core\EventSubscriber\RequestCloseSubscriber;
-use Drupal\Core\EventSubscriber\RouterListener;
-use Drupal\Core\EventSubscriber\ViewSubscriber;
-use Drupal\Core\ExceptionController;
-use Drupal\Core\LegacyUrlMatcher;
 use Symfony\Component\DependencyInjection\ContainerBuilder as BaseContainerBuilder;
-use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\EventDispatcher\EventDispatcher;
-use Symfony\Component\HttpKernel\EventListener\ExceptionListener;
+use Symfony\Component\DependencyInjection\Compiler\Compiler;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\PassConfig;
+use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
 
 /**
  * Drupal's dependency injection container.
  */
 class ContainerBuilder extends BaseContainerBuilder {
 
-  /**
-   * Registers the base Drupal services for the dependency injection container.
-   */
   public function __construct() {
     parent::__construct();
-
-    // An interface language always needs to be available for t() and other
-    // functions. This default is overridden by drupal_language_initialize()
-    // during language negotiation.
-    $this->register(LANGUAGE_TYPE_INTERFACE, 'Drupal\\Core\\Language\\Language');
-
-    // Register the default language content.
-    $this->register(LANGUAGE_TYPE_CONTENT, 'Drupal\\Core\\Language\\Language');
-
-    // Register configuration storage dispatcher.
-    $this->setParameter('config.storage.info', array(
-      'Drupal\Core\Config\DatabaseStorage' => array(
-        'connection' => 'default',
-        'target' => 'default',
-        'read' => TRUE,
-        'write' => TRUE,
-      ),
-      'Drupal\Core\Config\FileStorage' => array(
-        'directory' => config_get_config_directory(),
-        'read' => TRUE,
-        'write' => FALSE,
-      ),
-    ));
-    $this->register('config.storage.dispatcher', 'Drupal\Core\Config\StorageDispatcher')
-      ->addArgument('%config.storage.info%');
-
-    // Register configuration object factory.
-    $this->register('config.factory', 'Drupal\Core\Config\ConfigFactory')
-      ->addArgument(new Reference('config.storage.dispatcher'));
-
-    // Register the HTTP kernel services.
-    $this->register('dispatcher', 'Symfony\Component\EventDispatcher\EventDispatcher')
-      ->addArgument(new Reference('service_container'))
-      ->setFactoryClass('Drupal\Core\DependencyInjection\ContainerBuilder')
-      ->setFactoryMethod('getKernelEventDispatcher');
-    $this->register('resolver', 'Symfony\Component\HttpKernel\Controller\ControllerResolver');
-    $this->register('httpkernel', 'Symfony\Component\HttpKernel\HttpKernel')
-      ->addArgument(new Reference('dispatcher'))
-      ->addArgument(new Reference('resolver'));
+    $this->compiler = new Compiler();
   }
 
-  /**
-   * Creates an EventDispatcher for the HttpKernel. Factory method.
-   *
-   * @param Drupal\Core\DependencyInjection\ContainerBuilder $container
-   *   The dependency injection container that contains the HTTP kernel.
-   *
-   * @return Symfony\Component\EventDispatcher\EventDispatcher
-   *   An EventDispatcher with the default listeners attached to it.
-   */
-  public static function getKernelEventDispatcher($container) {
-    $dispatcher = new EventDispatcher();
-
-    $matcher = new LegacyUrlMatcher();
-    $dispatcher->addSubscriber(new RouterListener($matcher));
-
-    $negotiation = new ContentNegotiation();
-
-    // @todo Make this extensible rather than just hard coding some.
-    // @todo Add a subscriber to handle other things, too, like our Ajax
-    //   replacement system.
-    $dispatcher->addSubscriber(new ViewSubscriber($negotiation));
-    $dispatcher->addSubscriber(new AccessSubscriber());
-    $dispatcher->addSubscriber(new MaintenanceModeSubscriber());
-    $dispatcher->addSubscriber(new PathSubscriber());
-    $dispatcher->addSubscriber(new LegacyRequestSubscriber());
-    $dispatcher->addSubscriber(new LegacyControllerSubscriber());
-    $dispatcher->addSubscriber(new FinishResponseSubscriber());
-    $dispatcher->addSubscriber(new RequestCloseSubscriber());
-
-    // Some other form of error occured that wasn't handled by another kernel
-    // listener. That could mean that it's a method/mime-type/error combination
-    // that is not accounted for, or some other type of error. Either way, treat
-    // it as a server-level error and return an HTTP 500. By default, this will
-    // be an HTML-type response because that's a decent best guess if we don't
-    // know otherwise.
-    $exceptionController = new ExceptionController($negotiation);
-    $exceptionController->setContainer($container);
-    $dispatcher->addSubscriber(new ExceptionListener(array($exceptionController, 'execute')));
+  public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION) {
+    $this->compiler->addPass($pass, $type);
+  }
 
-    return $dispatcher;
+  public function compile() {
+    $this->compiler->compile($this);
+    $this->parameterBag->resolve();
   }
+
 }
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
new file mode 100644
index 0000000..0e1df6e
--- /dev/null
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -0,0 +1,89 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\DrupalKernel.
+ */
+
+namespace Drupal\Core;
+
+use Drupal\Core\CoreBundle;
+use Symfony\Component\HttpKernel\Kernel;
+use Drupal\Core\DependencyInjection\ContainerBuilder;
+use Symfony\Component\Config\Loader\LoaderInterface;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
+
+/**
+ * The DrupalKernel class is the core of Drupal itself.
+ */
+class DrupalKernel extends Kernel {
+
+  public function registerBundles() {
+    $bundles = array(
+      new CoreBundle(),
+    );
+
+    // TODO: Somehow remove the necessity of calling system_list() to find out which
+    // bundles exist.
+
+    $modules = array_keys(system_list('module_enabled'));
+    foreach ($modules as $module) {
+      $camelized = ContainerBuilder::camelize($module);
+      $class = "\Drupal\\{$module}\\{$camelized}Bundle";
+      if (class_exists($class)) {
+        $bundles[] = new $class();
+      }
+    }
+    return $bundles;
+  }
+
+
+  /**
+   * Initializes the service container.
+   */
+  protected function initializeContainer() {
+    // @todo We should be compiling the container and dumping to php so we don't
+    // have to recompile every time. There is a separate issue for this, see
+    // http://drupal.org/node/1668892.
+    $this->container = $this->buildContainer();
+    $this->container->set('kernel', $this);
+    drupal_container($this->container);
+  }
+
+  /**
+   * Builds the service container.
+   *
+   * @return ContainerBuilder The compiled service container
+   */
+  protected function buildContainer() {
+    $container = $this->getContainerBuilder();
+
+    foreach ($this->bundles as $bundle) {
+      $bundle->build($container);
+    }
+    $container->compile();
+    return $container;
+  }
+
+  /**
+   * Gets a new ContainerBuilder instance used to build the service container.
+   *
+   * @return ContainerBuilder
+   */
+  protected function getContainerBuilder() {
+    return new ContainerBuilder(new ParameterBag($this->getKernelParameters()));
+  }
+
+  /**
+   * Overrides and eliminates this method from the parent class. Do not use.
+   *
+   * This method is part of the KernelInterface interface, but takes an object
+   * implementing LoaderInterface as its only parameter. This is part of the
+   * Config compoment from Symfony, which is not provided by Drupal core.
+   *
+   * Modules wishing to provide an extension to this class which uses this
+   * method are responsible for ensuring the Config component exists.
+   */
+  public function registerContainerConfiguration(LoaderInterface $loader) {
+  }
+}
diff --git a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
index 6e23845..0dce966 100644
--- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
@@ -30,7 +30,7 @@ class FinishResponseSubscriber implements EventSubscriberInterface {
     $response->headers->set('X-UA-Compatible', 'IE=edge,chrome=1', false);
 
     // Set the Content-language header.
-    $response->headers->set('Content-language', drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode);
+    $response->headers->set('Content-language', language_manager(LANGUAGE_TYPE_INTERFACE)->langcode);
 
     // Because pages are highly dynamic, set the last-modified time to now
     // since the page is in fact being regenerated right now.
diff --git a/core/lib/Drupal/Core/EventSubscriber/PathListenerBase.php b/core/lib/Drupal/Core/EventSubscriber/PathListenerBase.php
index fd0a765..385798c 100644
--- a/core/lib/Drupal/Core/EventSubscriber/PathListenerBase.php
+++ b/core/lib/Drupal/Core/EventSubscriber/PathListenerBase.php
@@ -21,9 +21,5 @@ abstract class PathListenerBase {
 
   public function setPath(Request $request, $path) {
     $request->attributes->set('system_path', $path);
-
-    // @todo Remove this line once code has been refactored to use the request
-    //   object directly.
-    _current_path($path);
   }
 }
diff --git a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php
index 2e1bece..7688107 100644
--- a/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/PathSubscriber.php
@@ -69,9 +69,6 @@ class PathSubscriber extends PathListenerBase implements EventSubscriberInterfac
    *   The Event to process.
    */
   public function onKernelRequestLanguageResolve(GetResponseEvent $event) {
-    $request = $event->getRequest();
-    $path = $this->extractPath($request);
-
     // drupal_language_initialize() combines:
     // - Determination of language from $request information (e.g., path).
     // - Determination of language from other information (e.g., site default).
@@ -80,11 +77,7 @@ class PathSubscriber extends PathListenerBase implements EventSubscriberInterfac
     // @todo Decouple the above, but for now, invoke it and update the path
     //   prior to front page and alias resolution. When above is decoupled, also
     //   add 'langcode' (determined from $request only) to $request->attributes.
-    _current_path($path);
     drupal_language_initialize();
-    $path = _current_path();
-
-    $this->setPath($request, $path);
   }
 
   /**
diff --git a/core/lib/Drupal/Core/ExceptionController.php b/core/lib/Drupal/Core/ExceptionController.php
index 7f71e28..e302671 100644
--- a/core/lib/Drupal/Core/ExceptionController.php
+++ b/core/lib/Drupal/Core/ExceptionController.php
@@ -7,12 +7,14 @@
 
 namespace Drupal\Core;
 
+use Symfony\Component\DependencyInjection\Container;
 use Symfony\Component\DependencyInjection\ContainerAware;
 use Symfony\Component\HttpFoundation\Request;
 use Symfony\Component\HttpFoundation\Response;
 use Symfony\Component\HttpFoundation\JsonResponse;
-use Symfony\Component\HttpKernel\HttpKernel;
+use Drupal\Core\HttpKernel;
 use Symfony\Component\HttpKernel\Exception\FlattenException;
+use Symfony\Component\HttpKernel\EventListener\ExceptionListener;
 
 /**
  * This controller handles HTTP errors generated by the routing system.
@@ -27,6 +29,24 @@ class ExceptionController extends ContainerAware {
   protected $negotiation;
 
   /**
+   * Instantiates a new exception listener.
+   *
+   * Factory method for getting an Exception Listener. Since this needs to be
+   * instanciated with a controller callable, i.e. an ExceptionConroller object
+   * and the name of the method to call, we can't just register it to the DIC
+   * the regular way.
+   *
+   * @todo: This probably doesn't belong here, but I'm not sure where would be a better
+   * place to put it... in a class of its own?
+   */
+  public static function getExceptionListener(Container $container) {
+    $negotiation = $container->get('content_negotiation');
+    $exceptionController = new self($negotiation);
+    $exceptionController->setContainer($container);
+    return new ExceptionListener(array($exceptionController, 'execute'));
+  }
+
+  /**
    * Constructor.
    *
    * @param Drupal\Core\ContentNegotiation $negotiation
@@ -107,7 +127,7 @@ class ExceptionController extends ContainerAware {
       drupal_static_reset('menu_set_active_trail');
       menu_reset_static_cache();
 
-      $response = $this->container->get('httpkernel')->handle($subrequest, HttpKernel::SUB_REQUEST);
+      $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernel::SUB_REQUEST);
       $response->setStatusCode(403, 'Access denied');
     }
     else {
@@ -172,7 +192,7 @@ class ExceptionController extends ContainerAware {
       drupal_static_reset('menu_set_active_trail');
       menu_reset_static_cache();
 
-      $response = $this->container->get('httpkernel')->handle($subrequest, HttpKernel::SUB_REQUEST);
+      $response = $this->container->get('http_kernel')->handle($subrequest, HttpKernel::SUB_REQUEST);
       $response->setStatusCode(404, 'Not Found');
     }
     else {
diff --git a/core/lib/Drupal/Core/HttpKernel.php b/core/lib/Drupal/Core/HttpKernel.php
new file mode 100644
index 0000000..d8031f3
--- /dev/null
+++ b/core/lib/Drupal/Core/HttpKernel.php
@@ -0,0 +1,51 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\HttpKernel.
+ */
+
+namespace Drupal\Core;
+
+use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpKernel\HttpKernel as BaseHttpKernel;
+
+
+/**
+ * This HttpKernel is used to manage scope changes of the DI container.
+ */
+class HttpKernel extends BaseHttpKernel
+{
+    protected $container;
+
+    public function __construct(ContainerAwareEventDispatcher $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver)
+    {
+        parent::__construct($dispatcher, $controllerResolver);
+
+        $this->container = $container;
+    }
+
+    public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
+    {
+        $request->headers->set('X-Php-Ob-Level', ob_get_level());
+
+        $this->container->enterScope('request');
+        $this->container->set('request', $request, 'request');
+
+        try {
+            $response = parent::handle($request, $type, $catch);
+        } catch (\Exception $e) {
+            $this->container->leaveScope('request');
+
+            throw $e;
+        }
+
+        $this->container->leaveScope('request');
+
+        return $response;
+    }
+}
diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php
new file mode 100644
index 0000000..dec182d
--- /dev/null
+++ b/core/lib/Drupal/Core/Language/LanguageManager.php
@@ -0,0 +1,39 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Language\LanguageManager.
+ */
+
+namespace Drupal\Core\Language;
+
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * The LanguageManager service intializes the language types passing in the
+ * Request object, which can then be used for e.g. url-based language negotiation.
+ */
+class LanguageManager {
+
+  private $request;
+  private $languages;
+
+  public function __construct(Request $request = NULL) {
+    $this->request = $request;
+  }
+
+  public function getLanguage($type) {
+    if (isset($this->languages[$type])) {
+      return $this->languages[$type];
+    }
+
+    // @todo Objectify the language system so that we don't have to do this.
+    include_once DRUPAL_ROOT . '/core/includes/language.inc';
+    $this->languages[$type] = language_types_initialize($type, array('request' => $this->request));
+    return $this->languages[$type];
+  }
+
+  function reset() {
+    $this->languages = array();
+  }
+}
diff --git a/core/modules/aggregator/aggregator.admin.inc b/core/modules/aggregator/aggregator.admin.inc
index 7bb4c04..718e79c 100644
--- a/core/modules/aggregator/aggregator.admin.inc
+++ b/core/modules/aggregator/aggregator.admin.inc
@@ -412,7 +412,7 @@ function aggregator_admin_refresh_feed($feed) {
   // @todo CSRF tokens are validated in page callbacks rather than access
   //   callbacks, because access callbacks are also invoked during menu link
   //   generation. Add token support to routing: http://drupal.org/node/755584.
-  $token = request()->query->get('token');
+  $token = drupal_container()->get('request')->query->get('token');
   if (!isset($token) || !drupal_valid_token($token, 'aggregator/update/' . $feed->fid)) {
     throw new AccessDeniedHttpException();
   }
diff --git a/core/modules/aggregator/aggregator.pages.inc b/core/modules/aggregator/aggregator.pages.inc
index 78ca5bc..15b4633 100644
--- a/core/modules/aggregator/aggregator.pages.inc
+++ b/core/modules/aggregator/aggregator.pages.inc
@@ -403,16 +403,15 @@ function aggregator_page_categories() {
  */
 function aggregator_page_rss() {
   $result = NULL;
-  $rss_config = config('system.rss');
   // arg(2) is the passed cid, only select for that category.
   if (arg(2)) {
     $category = db_query('SELECT cid, title FROM {aggregator_category} WHERE cid = :cid', array(':cid' => arg(2)))->fetchObject();
-    $result = db_query_range('SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_category_item} c LEFT JOIN {aggregator_item} i ON c.iid = i.iid LEFT JOIN {aggregator_feed} f ON i.fid = f.fid WHERE cid = :cid ORDER BY timestamp DESC, i.iid DESC', 0, $rss_config->get('items.limit'), array(':cid' => $category->cid));
+    $result = db_query_range('SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_category_item} c LEFT JOIN {aggregator_item} i ON c.iid = i.iid LEFT JOIN {aggregator_feed} f ON i.fid = f.fid WHERE cid = :cid ORDER BY timestamp DESC, i.iid DESC', 0, config('system.rss-publishing')->get('feed_default_items'), array(':cid' => $category->cid));
   }
   // Or, get the default aggregator items.
   else {
     $category = NULL;
-    $result = db_query_range('SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_item} i INNER JOIN {aggregator_feed} f ON i.fid = f.fid ORDER BY i.timestamp DESC, i.iid DESC', 0, $rss_config->get('items.limit'));
+    $result = db_query_range('SELECT i.*, f.title AS ftitle, f.link AS flink FROM {aggregator_item} i INNER JOIN {aggregator_feed} f ON i.fid = f.fid ORDER BY i.timestamp DESC, i.iid DESC', 0, config('system.rss-publishing')->get('feed_default_items'));
   }
 
   $feeds = $result->fetchAll();
@@ -438,7 +437,7 @@ function theme_aggregator_page_rss($variables) {
   drupal_add_http_header('Content-Type', 'application/rss+xml; charset=utf-8');
 
   $items = '';
-  $feed_length = config('system.rss')->get('items.view_mode');
+  $feed_length = config('system.rss-publishing')->get('feed_item_length');
   foreach ($feeds as $feed) {
     switch ($feed_length) {
       case 'teaser':
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorRenderingTest.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorRenderingTest.php
index 557aef1..7a5b58e 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorRenderingTest.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorRenderingTest.php
@@ -83,8 +83,8 @@ class AggregatorRenderingTest extends AggregatorTestBase {
   public function testFeedPage() {
     // Increase the number of items published in the rss.xml feed so we have
     // enough articles to test paging.
-    $config = config('system.rss');
-    $config->set('items.limit', 30);
+    $config = config('system.rss-publishing');
+    $config->set('feed_default_items', 30);
     $config->save();
 
     // Create a feed with 30 items.
@@ -98,7 +98,7 @@ class AggregatorRenderingTest extends AggregatorTestBase {
     $this->assertTrue(!empty($elements), t('Individual source page contains a pager.'));
 
     // Reset the number of items in rss.xml to the default value.
-    $config->set('items.limit', 10);
+    $config->set('feed_default_items', 10);
     $config->save();
   }
 }
diff --git a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
index 6382341..9483170 100644
--- a/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
+++ b/core/modules/aggregator/lib/Drupal/aggregator/Tests/AggregatorTestBase.php
@@ -88,7 +88,7 @@ class AggregatorTestBase extends WebTestBase {
    */
   function getDefaultFeedItemCount() {
     // Our tests are based off of rss.xml, so let's find out how many elements should be related.
-    $feed_count = db_query_range('SELECT COUNT(*) FROM {node} n WHERE n.promote = 1 AND n.status = 1', 0, config('system.rss')->get('items.limit'))->fetchField();
+    $feed_count = db_query_range('SELECT COUNT(*) FROM {node} n WHERE n.promote = 1 AND n.status = 1', 0, config('system.rss-publishing')->get('feed_default_items'))->fetchField();
     return $feed_count > 10 ? 10 : $feed_count;
   }
 
diff --git a/core/modules/block/block.api.php b/core/modules/block/block.api.php
index 9fee858..bf166c9 100644
--- a/core/modules/block/block.api.php
+++ b/core/modules/block/block.api.php
@@ -329,7 +329,7 @@ function hook_block_view_MODULE_DELTA_alter(&$data, $block) {
  */
 function hook_block_list_alter(&$blocks) {
   global $theme_key;
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   // This example shows how to achieve language specific visibility setting for
   // blocks.
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 455f98f..8ff6308 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -880,7 +880,7 @@ function block_block_list_alter(&$blocks) {
       continue;
     }
     foreach ($block_langcodes[$block->module][$block->delta] as $language_type => $langcodes) {
-      if (isset($langcodes[drupal_container()->get($language_type)->langcode])) {
+      if (isset($langcodes[language_manager($language_type)->langcode])) {
         // Found a language type - langcode combination in the configuration
         // that is applicable to the current request.
         continue 2;
diff --git a/core/modules/book/book.module b/core/modules/book/book.module
index 40802a1..b3fdc25 100644
--- a/core/modules/book/book.module
+++ b/core/modules/book/book.module
@@ -1224,7 +1224,7 @@ function book_toc($bid, $depth_limit, $exclude = array()) {
  */
 function template_preprocess_book_export_html(&$variables) {
   global $base_url;
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   $variables['title'] = check_plain($variables['title']);
   $variables['base_url'] = $base_url;
diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module
index 0a7b261..446f493 100644
--- a/core/modules/comment/comment.module
+++ b/core/modules/comment/comment.module
@@ -504,12 +504,12 @@ function comment_permalink($cid) {
     $page = comment_get_display_page($comment->cid, $node->type);
 
     // @todo: Cleaner sub request handling.
-    $subrequest = Request::create('/node/' . $node->nid, 'GET', request()->query->all(), request()->cookies->all(), array(), request()->server->all());
+    $request = drupal_container()->get('request');
+    $subrequest = Request::create('/node/' . $node->nid, 'GET', $request->query->all(), $request->cookies->all(), array(), $request->server->all());
     $subrequest->query->set('page', $page);
     // @todo: Convert the pager to use the request object.
     $_GET['page'] = $page;
-    request($subrequest);
-    return drupal_container()->get('httpkernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST);
+    return drupal_container()->get('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST);
   }
   throw new NotFoundHttpException();
 }
@@ -528,7 +528,6 @@ function comment_get_recent($number = 10) {
   $query = db_select('comment', 'c');
   $query->innerJoin('node', 'n', 'n.nid = c.nid');
   $query->addTag('node_access');
-  $query->addMetaData('base_table', 'comment');
   $comments = $query
     ->fields('c')
     ->condition('c.status', COMMENT_PUBLISHED)
@@ -861,7 +860,6 @@ function comment_get_thread(Node $node, $mode, $comments_per_page) {
     ->condition('c.nid', $node->nid)
     ->addTag('node_access')
     ->addTag('comment_filter')
-    ->addMetaData('base_table', 'comment')
     ->addMetaData('node', $node)
     ->limit($comments_per_page);
 
@@ -871,7 +869,6 @@ function comment_get_thread(Node $node, $mode, $comments_per_page) {
     ->condition('c.nid', $node->nid)
     ->addTag('node_access')
     ->addTag('comment_filter')
-    ->addMetaData('base_table', 'comment')
     ->addMetaData('node', $node);
 
   if (!user_access('administer comments')) {
@@ -958,7 +955,7 @@ function comment_prepare_thread(&$comments) {
  */
 function comment_view(Comment $comment, Node $node, $view_mode = 'full', $langcode = NULL) {
   if (!isset($langcode)) {
-    $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode;
+    $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode;
   }
 
   // Populate $comment->content with a render() array.
@@ -1024,7 +1021,7 @@ function comment_view(Comment $comment, Node $node, $view_mode = 'full', $langco
  */
 function comment_build_content(Comment $comment, Node $node, $view_mode = 'full', $langcode = NULL) {
   if (!isset($langcode)) {
-    $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode;
+    $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode;
   }
 
   // Remove previously built content, if exists.
@@ -1682,7 +1679,7 @@ function comment_forms() {
  */
 function comment_form($form, &$form_state, Comment $comment) {
   global $user;
-  $language_content = drupal_container()->get(LANGUAGE_TYPE_CONTENT);
+  $language_content = language_manager(LANGUAGE_TYPE_CONTENT);
 
   // During initial form build, add the comment entity to the form state for
   // use during form building and processing. During a rebuild, use what is in
diff --git a/core/modules/comment/comment.pages.inc b/core/modules/comment/comment.pages.inc
index 3167bd7..ae50379 100644
--- a/core/modules/comment/comment.pages.inc
+++ b/core/modules/comment/comment.pages.inc
@@ -116,7 +116,7 @@ function comment_approve($cid) {
   // @todo CSRF tokens are validated in page callbacks rather than access
   //   callbacks, because access callbacks are also invoked during menu link
   //   generation. Add token support to routing: http://drupal.org/node/755584.
-  $token = request()->query->get('token');
+  $token = drupal_container()->get('request')->query->get('token');
   if (!isset($token) || !drupal_valid_token($token, "comment/$cid/approve")) {
     throw new AccessDeniedHttpException();
   }
diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php
index aea41ef..50a7b55 100644
--- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php
+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php
@@ -23,7 +23,7 @@ class CommentTokenReplaceTest extends CommentTestBase {
    * Creates a comment, then tests the tokens generated from it.
    */
   function testCommentTokenReplacement() {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
     $url_options = array(
       'absolute' => TRUE,
       'language' => $language_interface,
diff --git a/core/modules/contact/contact.pages.inc b/core/modules/contact/contact.pages.inc
index 7896ae5..661f1e0 100644
--- a/core/modules/contact/contact.pages.inc
+++ b/core/modules/contact/contact.pages.inc
@@ -130,7 +130,7 @@ function contact_site_form_validate($form, &$form_state) {
  */
 function contact_site_form_submit($form, &$form_state) {
   global $user;
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   $values = $form_state['values'];
   $values['sender'] = $user;
@@ -252,7 +252,7 @@ function contact_personal_form($form, &$form_state, $recipient) {
  */
 function contact_personal_form_submit($form, &$form_state) {
   global $user;
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   $values = $form_state['values'];
   $values['sender'] = $user;
diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module
index a66b1e8..1a45276 100644
--- a/core/modules/entity/entity.module
+++ b/core/modules/entity/entity.module
@@ -46,7 +46,7 @@ function entity_modules_disabled() {
  * @see hook_entity_info_alter()
  */
 function entity_get_info($entity_type = NULL) {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   // Use the advanced drupal_static() pattern, since this is called very often.
   static $drupal_static_fast;
diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc
index 5ec5ed9..0f04c56 100644
--- a/core/modules/field/field.info.inc
+++ b/core/modules/field/field.info.inc
@@ -67,7 +67,7 @@ function field_info_cache_clear() {
  * @see _field_info_collate_types_reset()
  */
 function _field_info_collate_types() {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   // Use the advanced drupal_static() pattern, since this is called very often.
   static $drupal_static_fast;
diff --git a/core/modules/field/field.multilingual.inc b/core/modules/field/field.multilingual.inc
index 17d385e..533c881 100644
--- a/core/modules/field/field.multilingual.inc
+++ b/core/modules/field/field.multilingual.inc
@@ -258,7 +258,7 @@ function field_valid_language($langcode, $default = TRUE) {
   if (in_array($langcode, $languages)) {
     return $langcode;
   }
-  return $default ? language_default()->langcode : drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode;
+  return $default ? language_default()->langcode : language_manager(LANGUAGE_TYPE_CONTENT)->langcode;
 }
 
 /**
diff --git a/core/modules/file/lib/Drupal/file/Tests/FileTokenReplaceTest.php b/core/modules/file/lib/Drupal/file/Tests/FileTokenReplaceTest.php
index 57e9a1e..c7df161 100644
--- a/core/modules/file/lib/Drupal/file/Tests/FileTokenReplaceTest.php
+++ b/core/modules/file/lib/Drupal/file/Tests/FileTokenReplaceTest.php
@@ -23,7 +23,7 @@ class FileTokenReplaceTest extends FileFieldTestBase {
    * Creates a file, then tests the tokens generated from it.
    */
   function testFileTokenReplacement() {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
     $url_options = array(
       'absolute' => TRUE,
       'language' => $language_interface,
diff --git a/core/modules/filter/filter.module b/core/modules/filter/filter.module
index 0e2f8d4..dc57eeb 100644
--- a/core/modules/filter/filter.module
+++ b/core/modules/filter/filter.module
@@ -399,7 +399,7 @@ function filter_modules_disabled($modules) {
  * @see filter_formats_reset()
  */
 function filter_formats($account = NULL) {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
   $formats = &drupal_static(__FUNCTION__, array());
 
   // All available formats are cached for performance.
diff --git a/core/modules/forum/forum.module b/core/modules/forum/forum.module
index f557c40..ca9bf7e 100644
--- a/core/modules/forum/forum.module
+++ b/core/modules/forum/forum.module
@@ -679,8 +679,7 @@ function forum_block_save($delta = '', $edit = array()) {
 function forum_block_view($delta = '') {
   $query = db_select('forum_index', 'f')
     ->fields('f')
-    ->addTag('node_access')
-    ->addMetaData('base_table', 'forum_index');
+    ->addTag('node_access');
   switch ($delta) {
     case 'active':
       $title = t('Active forum topics');
@@ -929,7 +928,6 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
   $query
     ->condition('f.tid', $tid)
     ->addTag('node_access')
-    ->addMetaData('base_table', 'forum_index')
     ->orderBy('f.sticky', 'DESC')
     ->orderByHeader($forum_topic_list_header)
     ->limit($forum_per_page);
@@ -938,7 +936,6 @@ function forum_get_topics($tid, $sortby, $forum_per_page) {
   $count_query->condition('f.tid', $tid);
   $count_query->addExpression('COUNT(*)');
   $count_query->addTag('node_access');
-  $count_query->addMetaData('base_table', 'forum_index');
 
   $query->setCountQuery($count_query);
   $result = $query->execute();
diff --git a/core/modules/forum/forums.tpl.php b/core/modules/forum/forums.tpl.php
index 6a0e02e..01919ab 100644
--- a/core/modules/forum/forums.tpl.php
+++ b/core/modules/forum/forums.tpl.php
@@ -12,6 +12,7 @@
  * - $forums_defined: A flag to indicate that the forums are configured.
  *
  * @see template_preprocess_forums()
+ * @see theme_forums()
  *
  * @ingroup themeable
  */
diff --git a/core/modules/forum/lib/Drupal/forum/Tests/ForumNodeAccessTest.php b/core/modules/forum/lib/Drupal/forum/Tests/ForumNodeAccessTest.php
deleted file mode 100644
index 5cf7071..0000000
--- a/core/modules/forum/lib/Drupal/forum/Tests/ForumNodeAccessTest.php
+++ /dev/null
@@ -1,100 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\forum\Tests\ForumNodeAccessTest.
- */
-
-namespace Drupal\forum\Tests;
-
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Tests forum block view for private node access.
- */
-class ForumNodeAccessTest extends WebTestBase {
-  protected $access_user;
-  protected $admin_user;
-  protected $no_access_user;
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Forum private node access test',
-      'description' => 'Tests forum block view for private node access',
-      'group' => 'Forum',
-    );
-  }
-
-  function setUp() {
-    parent::setUp(array('node', 'comment', 'forum', 'taxonomy', 'tracker', 'node_access_test', 'block'));
-    node_access_rebuild();
-    variable_set('node_access_test_private', TRUE);
-  }
-
-  /**
-   * Creates some users and creates a public node and a private node.
-   *
-   * Adds both active forum topics and new forum topics blocks to the sidebar.
-   * Tests to ensure private node/public node access is respected on blocks.
-   */
-  function testForumNodeAccess() {
-    // Create some users.
-    $access_user = $this->drupalCreateUser(array('node test view'));
-    $no_access_user = $this->drupalCreateUser();
-    $admin_user = $this->drupalCreateUser(array('access administration pages', 'administer modules', 'administer blocks', 'create forum content'));
-
-    $this->drupalLogin($admin_user);
-
-    // Create a private node.
-    $langcode = LANGUAGE_NOT_SPECIFIED;
-    $private_node_title = $this->randomName(20);
-    $edit = array(
-      'title' => $private_node_title,
-      "body[$langcode][0][value]" => $this->randomName(200),
-      'private' => TRUE,
-    );
-    $this->drupalPost('node/add/forum/1', $edit, t('Save'));
-    $private_node = $this->drupalGetNodeByTitle($private_node_title);
-    $this->assertTrue(!empty($private_node), 'New private forum node found in database.');
-
-    // Create a public node.
-    $public_node_title = $this->randomName(20);
-    $edit = array(
-      'title' => $public_node_title,
-      "body[$langcode][0][value]" => $this->randomName(200),
-    );
-    $this->drupalPost('node/add/forum/1', $edit, t('Save'));
-    $public_node = $this->drupalGetNodeByTitle($public_node_title);
-    $this->assertTrue(!empty($public_node), 'New public forum node found in database.');
-
-    // Enable the active forum block.
-    $edit = array();
-    $edit['blocks[forum_active][region]'] = 'sidebar_second';
-    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
-    $this->assertResponse(200);
-    $this->assertText(t('The block settings have been updated.'), 'Active forum topics forum block was enabled');
-
-    // Enable the new forum block.
-    $edit = array();
-    $edit['blocks[forum_new][region]'] = 'sidebar_second';
-    $this->drupalPost('admin/structure/block', $edit, t('Save blocks'));
-    $this->assertResponse(200);
-    $this->assertText(t('The block settings have been updated.'), '[New forum topics] Forum block was enabled');
-
-    // Test for $access_user.
-    $this->drupalLogin($access_user);
-    $this->drupalGet('/');
-
-    // Ensure private node and public node are found.
-    $this->assertText($private_node->title, 'Private node found in block by $access_user');
-    $this->assertText($public_node->title, 'Public node found in block by $access_user');
-
-    // Test for $no_access_user.
-    $this->drupalLogin($no_access_user);
-    $this->drupalGet('/');
-
-    // Ensure private node is not found but public is found.
-    $this->assertNoText($private_node->title, 'Private node not found in block by $no_access_user');
-    $this->assertText($public_node->title, 'Public node found in block by $no_access_user');
-  }
-}
diff --git a/core/modules/image/image.module b/core/modules/image/image.module
index aa05d04..ac12e54 100644
--- a/core/modules/image/image.module
+++ b/core/modules/image/image.module
@@ -965,7 +965,7 @@ function image_style_path($style_name, $uri) {
  * @see image_effect_definition_load()
  */
 function image_effect_definitions() {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   // hook_image_effect_info() includes translated strings, so each language is
   // cached separately.
diff --git a/core/modules/language/language.module b/core/modules/language/language.module
index 46ba812..ee166c0 100644
--- a/core/modules/language/language.module
+++ b/core/modules/language/language.module
@@ -243,7 +243,7 @@ function language_delete($langcode) {
  * and checks to see if a related right to left CSS file should be included.
  */
 function language_css_alter(&$css) {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   // If the current language is RTL, add the CSS file with the RTL overrides.
   if ($language_interface->direction == LANGUAGE_RTL) {
diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc
index 01c39a8..78f958b 100644
--- a/core/modules/language/language.negotiation.inc
+++ b/core/modules/language/language.negotiation.inc
@@ -52,7 +52,7 @@ const LANGUAGE_NEGOTIATION_URL_DOMAIN = 1;
  *   The current interface language code.
  */
 function language_from_interface() {
-  return drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode;
+  return language_manager(LANGUAGE_TYPE_INTERFACE)->langcode;
 }
 
 /**
@@ -200,7 +200,7 @@ function language_from_session($languages) {
  * @return
  *   A valid language code on success, FALSE otherwise.
  */
-function language_from_url($languages) {
+function language_from_url($languages, $args = array()) {
   $language_url = FALSE;
 
   if (!language_negotiation_method_enabled(LANGUAGE_NEGOTIATION_URL)) {
@@ -212,8 +212,22 @@ function language_from_url($languages) {
       // Language negotiation happens before the public function current_path()
       // is available.
       // @todo Refactor with Symfony's Request object.
-      list($language, $path) = language_url_split_prefix(_current_path(), $languages);
-      _current_path($path);
+      if (isset($args['request'])) {
+        $request = $args['request'];
+
+        $current_path = $request->attributes->get('system_path');
+        if (!isset($current_path)) {
+          $current_path = trim($request->getPathInfo(), '/');
+        }
+      }
+      else {
+        $current_path = _current_path();
+      }
+
+      list($language, $path) = language_url_split_prefix($current_path, $languages);
+      if ($request) {
+        $request->attributes->set('system_path', $path);
+      }
       if ($language !== FALSE) {
         $language_url = $language->langcode;
       }
@@ -278,7 +292,7 @@ function language_from_url($languages) {
  * @return
  *   A valid language code.
  */
-function language_url_fallback($language = NULL, $language_type = LANGUAGE_TYPE_INTERFACE) {
+function language_url_fallback($language = NULL, $args = array(), $language_type = LANGUAGE_TYPE_INTERFACE) {
   $default = language_default();
   $prefix = (variable_get('language_negotiation_url_part', LANGUAGE_NEGOTIATION_URL_PREFIX) == LANGUAGE_NEGOTIATION_URL_PREFIX);
 
@@ -291,7 +305,8 @@ function language_url_fallback($language = NULL, $language_type = LANGUAGE_TYPE_
     return $default->langcode;
   }
   else {
-    return drupal_container()->get($language_type)->langcode;
+    $langcode = language_manager($language_type)->langcode;
+    return $langcode;
   }
 }
 
@@ -321,7 +336,7 @@ function language_switcher_url($type, $path) {
  */
 function language_switcher_session($type, $path) {
   $param = variable_get('language_negotiation_session_param', 'language');
-  $language_query = isset($_SESSION[$param]) ? $_SESSION[$param] : drupal_container()->get($type)->langcode;
+  $language_query = isset($_SESSION[$param]) ? $_SESSION[$param] : language_manager($type)->langcode;
 
   $languages = language_list();
   $links = array();
@@ -364,7 +379,7 @@ function language_url_rewrite_url(&$path, &$options) {
 
   // Language can be passed as an option, or we go for current URL language.
   if (!isset($options['language'])) {
-    $language_url = drupal_container()->get(LANGUAGE_TYPE_URL);
+    $language_url = language_manager(LANGUAGE_TYPE_URL);
     $options['language'] = $language_url;
   }
   // We allow only enabled languages here.
diff --git a/core/modules/language/lib/Drupal/language/Tests/LanguageDependencyInjectionTest.php b/core/modules/language/lib/Drupal/language/Tests/LanguageDependencyInjectionTest.php
index fd4a865..bd940d3 100644
--- a/core/modules/language/lib/Drupal/language/Tests/LanguageDependencyInjectionTest.php
+++ b/core/modules/language/lib/Drupal/language/Tests/LanguageDependencyInjectionTest.php
@@ -26,9 +26,8 @@ class LanguageDependencyInjectionTest extends WebTestBase {
   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());
+    // Ensure we are building a new Language object for each test.
+    language_manager();
   }
 
 
@@ -42,7 +41,7 @@ class LanguageDependencyInjectionTest extends WebTestBase {
     drupal_language_initialize();
 
     $expected = language_default();
-    $result = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $result = language_manager(LANGUAGE_TYPE_INTERFACE);
     foreach ($expected as $property => $value) {
       $this->assertEqual($expected->$property, $result->$property, t('The dependency injected language object %prop property equals the new Language object %prop property.', array('%prop' => $property)));
     }
@@ -61,6 +60,7 @@ class LanguageDependencyInjectionTest extends WebTestBase {
       'name' => 'French',
       'direction' => 0,
       'weight' => 0,
+      'method_id' => 'language-default',
       'default' => TRUE,
     );
     variable_set('language_default', $new_language_default);
@@ -71,7 +71,7 @@ class LanguageDependencyInjectionTest extends WebTestBase {
     // The langauge system creates a Language object which contains the
     // same properties as the new default language object.
     $expected = new Language($new_language_default);
-    $result = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $result = language_manager(LANGUAGE_TYPE_INTERFACE);
     foreach ($expected as $property => $value) {
       $this->assertEqual($expected->$property, $result->$property, t('The dependency injected language object %prop property equals the default language object %prop property.', array('%prop' => $property)));
     }
diff --git a/core/modules/language/tests/language_test.module b/core/modules/language/tests/language_test.module
index 7829674..cc2e8ad 100644
--- a/core/modules/language/tests/language_test.module
+++ b/core/modules/language/tests/language_test.module
@@ -22,8 +22,8 @@ function language_test_boot() {
  */
 function language_test_init() {
   language_test_store_language_negotiation();
-  if (isset(drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode) && isset(drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->method_id)) {
-    drupal_set_message(t('Language negotiation method: @name', array('@name' => drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->method_id)));
+  if (isset(language_manager(LANGUAGE_TYPE_INTERFACE)->langcode) && isset(language_manager(LANGUAGE_TYPE_INTERFACE)->method_id)) {
+    drupal_set_message(t('Language negotiation method: @name', array('@name' => language_manager(LANGUAGE_TYPE_INTERFACE)->method_id)));
   }
 }
 
@@ -95,7 +95,7 @@ function language_test_language_negotiation_info_alter(array &$negotiation_info)
 function language_test_store_language_negotiation() {
   $last = array();
   foreach (language_types_get_all() as $type) {
-    $last[$type] = drupal_container()->get($type)->langcode;
+    $last[$type] = language_manager($type)->langcode;
   }
   variable_set('language_test_language_negotiation_last', $last);
 }
diff --git a/core/modules/locale/lib/Drupal/locale/Gettext.php b/core/modules/locale/lib/Drupal/locale/Gettext.php
deleted file mode 100644
index f3ba3b9..0000000
--- a/core/modules/locale/lib/Drupal/locale/Gettext.php
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\locale\Gettext.
- */
-
-namespace Drupal\locale;
-
-use Drupal\Component\Gettext\PoStreamReader;
-use Drupal\Component\Gettext\PoMemoryWriter;
-use Drupal\locale\PoDatabaseWriter;
-
-/**
- * Static class providing Drupal specific Gettext functionality.
- *
- * The operations are related to pumping data from a source to a destination,
- * for example:
- * - Remote files http://*.po to memory
- * - File public://*.po to database
- */
-class Gettext {
-
-  /**
-   * Reads the given Gettext PO files into a data structure.
-   *
-   * @param string $langcode
-   *   Language code string.
-   * @param array $files
-   *   List of file objects with uri properties pointing to read.
-   *
-   * @return array
-   *   Structured array as produced by a PoMemoryWriter.
-   *
-   * @see Drupal\Component\Gettext\PoMemoryWriter
-   */
-  static function filesToArray($langcode, array $files) {
-    $writer = new PoMemoryWriter();
-    $writer->setLangcode($langcode);
-    foreach ($files as $file) {
-      $reader = new PoStreamReader();
-      $reader->setURI($file->uri);
-      $reader->setLangcode($langcode);
-      $reader->open();
-      $writer->writeItems($reader, -1);
-    }
-    return $writer->getData();
-  }
-
-  /**
-   * Reads the given PO files into the database.
-   *
-   * @param stdClass $file
-   *   File object with an uri property pointing at the file's path.
-   * @param string $langcode
-   *   Language code string.
-   * @param array $overwrite_options
-   *   Overwrite options array as defined in Drupal\locale\PoDatabaseWriter.
-   * @param boolean $customized
-   *   Flag indicating whether the string imported from $file are customized
-   *   translations or come from a community source. Use LOCALE_CUSTOMIZED or
-   *   LOCALE_NOT_CUSTOMIZED.
-   *
-   * @return array
-   *   Report array as defined in Drupal\locale\PoDatabaseWriter.
-   *
-   * @see Drupal\locale\PoDatabaseWriter
-   */
-  static function fileToDatabase($file, $langcode, $overwrite_options, $customized = LOCALE_NOT_CUSTOMIZED) {
-    // Instantiate and initialize the stream reader for this file.
-    $reader = new PoStreamReader();
-    $reader->setLangcode($langcode);
-    $reader->setURI($file->uri);
-
-    try {
-      $reader->open();
-    }
-    catch (Exception $exception) {
-      throw $exception;
-    }
-
-    $header = $reader->getHeader();
-    if (!$header) {
-      throw new Exception('Missing or malformed header.');
-    }
-
-    // Initialize the database writer.
-    $writer = new PoDatabaseWriter();
-    $writer->setLangcode($langcode);
-    $options = array(
-      'overwrite_options' => $overwrite_options,
-      'customized' => $customized,
-    );
-    $writer->setOptions($options);
-    $writer->setHeader($header);
-
-    // Attempt to pipe all items from the file to the database.
-    try {
-      $writer->writeItems($reader, -1);
-    }
-    catch (Exception $exception) {
-      throw $exception;
-    }
-
-    // Report back with an array of status information.
-    return $writer->getReport();
-  }
-}
diff --git a/core/modules/locale/lib/Drupal/locale/PoDatabaseReader.php b/core/modules/locale/lib/Drupal/locale/PoDatabaseReader.php
deleted file mode 100644
index c0dfc2f..0000000
--- a/core/modules/locale/lib/Drupal/locale/PoDatabaseReader.php
+++ /dev/null
@@ -1,180 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\locale\PoDatabaseReader.
- */
-
-namespace Drupal\locale;
-
-use Drupal\Component\Gettext\PoHeader;
-use Drupal\Component\Gettext\PoItem;
-use Drupal\Component\Gettext\PoReaderInterface;
-
-/**
- * Gettext PO reader working with the locale module database.
- */
-class PoDatabaseReader implements PoReaderInterface {
-
-  /**
-   * An associative array indicating which type of strings should be read.
-   *
-   * Elements of the array:
-   *  - not_customized: boolean indicating if not customized strings should be
-   *    read.
-   *  - customized: boolean indicating if customized strings should be read.
-   *  - no_translated: boolean indicating if non-translated should be read.
-   *
-   * The three options define three distinct sets of strings, which combined
-   * cover all strings.
-   *
-   * @var array
-   */
-  private $_options;
-
-  /**
-   * Language code of the language being read from the database.
-   *
-   * @var string
-   */
-  private $_langcode;
-
-  /**
-   * Store the result of the query so it can be iterated later.
-   *
-   * @var resource
-   */
-  private $_result;
-
-  /**
-   * Constructor, initializes with default options.
-   */
-  function __construct() {
-    $this->setOptions(array());
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface::getLangcode().
-   */
-  public function getLangcode() {
-    return $this->_langcode;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface::setLangcode().
-   */
-  public function setLangcode($langcode) {
-    $this->_langcode = $langcode;
-  }
-
-  /**
-   * Get the options used by the reader.
-   */
-  function getOptions() {
-    return $this->_options;
-  }
-
-  /**
-   * Set the options for the current reader.
-   */
-  function setOptions(array $options) {
-    $options += array(
-      'customized' => FALSE,
-      'not_customized' => FALSE,
-      'not_translated' => FALSE,
-    );
-    $this->_options = $options;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface::getHeader().
-   */
-  function getHeader() {
-    return new PoHeader($this->getLangcode());
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface::setHeader().
-   *
-   * @throws Exception
-   *   Always, because you cannot set the PO header of a reader.
-   */
-  function setHeader(PoHeader $header) {
-    throw new Exception('You cannot set the PO header in a reader.');
-  }
-
-  /**
-   * Builds and executes a database query based on options set earlier.
-   */
-  private function buildQuery() {
-    $langcode = $this->_langcode;
-    $options = $this->_options;
-
-    if (array_sum($options) == 0) {
-      // If user asked to not include anything in the translation files,
-      // that would not make sense, so just fall back on providing a template.
-      $langcode = NULL;
-    }
-
-    // Build and execute query to collect source strings and translations.
-    $query = db_select('locales_source', 's');
-    if (!empty($langcode)) {
-      if ($options['not_translated']) {
-        // Left join to keep untranslated strings in.
-        $query->leftJoin('locales_target', 't', 's.lid = t.lid AND t.language = :language', array(':language' => $langcode));
-      }
-      else {
-        // Inner join to filter for only translations.
-        $query->innerJoin('locales_target', 't', 's.lid = t.lid AND t.language = :language', array(':language' => $langcode));
-      }
-      if ($options['customized']) {
-        if (!$options['not_customized']) {
-          // Filter for customized strings only.
-          $query->condition('t.customized', LOCALE_CUSTOMIZED);
-        }
-        // Else no filtering needed in this case.
-      }
-      else {
-        if ($options['not_customized']) {
-          // Filter for non-customized strings only.
-          $query->condition('t.customized', LOCALE_NOT_CUSTOMIZED);
-        }
-        else {
-          // Filter for strings without translation.
-          $query->isNull('t.translation');
-        }
-      }
-      $query->fields('t', array('translation'));
-    }
-    else {
-      $query->leftJoin('locales_target', 't', 's.lid = t.lid');
-    }
-    $query->fields('s', array('lid', 'source', 'context', 'location'));
-
-    $this->_result = $query->execute();
-  }
-
-  /**
-   * Get the database result resource for the given language and options.
-   */
-  private function getResult() {
-    if (!isset($this->_result)) {
-      $this->buildQuery();
-    }
-    return $this->_result;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoReaderInterface::readItem().
-   */
-  function readItem() {
-    $result = $this->getResult();
-    $values = $result->fetchAssoc();
-    if ($values) {
-      $poItem = new PoItem();
-      $poItem->setFromArray($values);
-      return $poItem;
-    }
-  }
-
-}
diff --git a/core/modules/locale/lib/Drupal/locale/PoDatabaseWriter.php b/core/modules/locale/lib/Drupal/locale/PoDatabaseWriter.php
deleted file mode 100644
index 33f05d9..0000000
--- a/core/modules/locale/lib/Drupal/locale/PoDatabaseWriter.php
+++ /dev/null
@@ -1,306 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\locale\PoDatabaseWriter.
- */
-
-namespace Drupal\locale;
-
-use Drupal\Component\Gettext\PoHeader;
-use Drupal\Component\Gettext\PoItem;
-use Drupal\Component\Gettext\PoReaderInterface;
-use Drupal\Component\Gettext\PoWriterInterface;
-
-/**
- * Gettext PO writer working with the locale module database.
- */
-class PoDatabaseWriter implements PoWriterInterface {
-
-  /**
-   * An associative array indicating what data should be overwritten, if any.
-   *
-   * Elements of the array:
-   * - override_options
-   *   - not_customized: boolean indicating that not customized strings should
-   *     be overwritten.
-   *   - customized: boolean indicating that customized strings should be
-   *     overwritten.
-   * - customized: the strings being imported should be saved as customized.
-   *     One of LOCALE_CUSTOMIZED or LOCALE_NOT_CUSTOMIZED.
-   *
-   * @var array
-   */
-  private $_options;
-
-  /**
-   * Language code of the language being written to the database.
-   *
-   * @var string
-   */
-  private $_langcode;
-
-  /**
-   * Header of the po file written to the database.
-   *
-   * @var Drupal\Component\Gettext\PoHeader
-   */
-  private $_header;
-
-  /**
-   * Associative array summarizing the number of changes done.
-   *
-   * Keys for the array:
-   *  - additions: number of source strings newly added
-   *  - updates: number of translations updated
-   *  - deletes: number of translations deleted
-   *  - skips: number of strings skipped due to disallowed HTML
-   *
-   * @var array
-   */
-  private $_report;
-
-  /**
-   * Constructor, initialize reporting array.
-   */
-  function __construct() {
-    $this->setReport();
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface::getLangcode().
-   */
-  public function getLangcode() {
-    return $this->_langcode;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface::setLangcode().
-   */
-  public function setLangcode($langcode) {
-    $this->_langcode = $langcode;
-  }
-
-  /**
-   * Get the report of the write operations.
-   */
-  public function getReport() {
-    return $this->_report;
-  }
-
-  /**
-   * Set the report array of write operations.
-   *
-   * @param array $report
-   *   Associative array with result information.
-   */
-  function setReport($report = array()) {
-    $report += array(
-      'additions' => 0,
-      'updates' => 0,
-      'deletes' => 0,
-      'skips' => 0,
-    );
-    $this->_report = $report;
-  }
-
-  /**
-   * Get the options used by the writer.
-   */
-  function getOptions() {
-    return $this->_options;
-  }
-
-  /**
-   * Set the options for the current writer.
-   */
-  function setOptions(array $options) {
-    if (!isset($options['overwrite_options'])) {
-      $options['overwrite_options'] = array();
-    }
-    $options['overwrite_options'] += array(
-      'not_customized' => FALSE,
-      'customized' => FALSE,
-    );
-    $options += array(
-      'customized' => LOCALE_NOT_CUSTOMIZED,
-    );
-    $this->_options = $options;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface::getHeader().
-   */
-  function getHeader() {
-    return $this->_header;
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoMetadataInterface::setHeader().
-   *
-   * Sets the header and configure Drupal accordingly.
-   *
-   * Before being able to process the given header we need to know in what
-   * context this database write is done. For this the options must be set.
-   *
-   * A langcode is required to set the current header's PluralForm.
-   *
-   * @param Drupal\Component\Gettext\PoHeader $header
-   *   Header metadata.
-   *
-   * @throws Exception
-   */
-  function setHeader(PoHeader $header) {
-    $this->_header = $header;
-    $locale_plurals = variable_get('locale_translation_plurals', array());
-
-    // Check for options.
-    $options = $this->getOptions();
-    if (empty($options)) {
-      throw new Exception("Options should be set before assigning a PoHeader.");
-    }
-    $overwrite_options = $options['overwrite_options'];
-
-    // Check for langcode.
-    $langcode = $this->_langcode;
-    if (empty($langcode)) {
-      throw new Exception("Langcode should be set before assigning a PoHeader.");
-    }
-
-    if (array_sum($overwrite_options) || empty($locale_plurals[$langcode]['plurals'])) {
-      // Get and store the plural formula if available.
-      $plural = $header->getPluralForms();
-      if (isset($plural) && $p = $header->parsePluralForms($plural)) {
-        list($nplurals, $formula) = $p;
-        $locale_plurals[$langcode] = array(
-          'plurals' => $nplurals,
-          'formula' => $formula,
-        );
-        variable_set('locale_translation_plurals', $locale_plurals);
-      }
-    }
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoWriterInterface::writeItem().
-   */
-  function writeItem(PoItem $item) {
-    if ($item->isPlural()) {
-      $item->setSource(join(LOCALE_PLURAL_DELIMITER, $item->getSource()));
-      $item->setTranslation(join(LOCALE_PLURAL_DELIMITER, $item->getTranslation()));
-    }
-    $this->importString($item);
-  }
-
-  /**
-   * Implements Drupal\Component\Gettext\PoWriterInterface::writeItems().
-   */
-  public function writeItems(PoReaderInterface $reader, $count = -1) {
-    $forever = $count == -1;
-    while (($count-- > 0 || $forever) && ($item = $reader->readItem())) {
-      $this->writeItem($item);
-    }
-  }
-
-  /**
-   * Imports one string into the database.
-   *
-   * @param Drupal\Component\Gettext\PoItem $item
-   *   The item being imported.
-   *
-   * @return int
-   *   The string ID of the existing string modified or the new string added.
-   */
-  private function importString(PoItem $item) {
-    // Initialize overwrite options if not set.
-    $this->_options['overwrite_options'] += array(
-      'not_customized' => FALSE,
-      'customized' => FALSE,
-    );
-    $overwrite_options = $this->_options['overwrite_options'];
-    $customized = $this->_options['customized'];
-
-    $context = $item->getContext();
-    $source = $item->getSource();
-    $translation = $item->getTranslation();
-
-
-    // Look up the source string and any existing translation.
-    $string = db_query("SELECT s.lid, t.customized FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.source = :source AND s.context = :context", array(
-      ':source' => $source,
-      ':context' => $context,
-      ':language' => $this->_langcode,
-        ))
-        ->fetchObject();
-
-    if (!empty($translation)) {
-      // Skip this string unless it passes a check for dangerous code.
-      if (!locale_string_is_safe($translation)) {
-        watchdog('locale', 'Import of string "%string" was skipped because of disallowed or malformed HTML.', array('%string' => $translation), WATCHDOG_ERROR);
-        $this->_report['skips']++;
-        return 0;
-      }
-      elseif (isset($string->lid)) {
-        if (!isset($string->customized)) {
-          // No translation in this language.
-          db_insert('locales_target')
-            ->fields(array(
-              'lid' => $string->lid,
-              'language' => $this->_langcode,
-              'translation' => $translation,
-              'customized' => $customized,
-            ))
-            ->execute();
-
-          $this->_report['additions']++;
-        }
-        elseif ($overwrite_options[$string->customized ? 'customized' : 'not_customized']) {
-          // Translation exists, only overwrite if instructed.
-          db_update('locales_target')
-            ->fields(array(
-              'translation' => $translation,
-              'customized' => $customized,
-            ))
-            ->condition('language', $this->_langcode)
-            ->condition('lid', $string->lid)
-            ->execute();
-
-          $this->_report['updates']++;
-        }
-        return $string->lid;
-      }
-      else {
-        // No such source string in the database yet.
-        $lid = db_insert('locales_source')
-          ->fields(array(
-            'source' => $source,
-            'context' => $context,
-          ))
-          ->execute();
-
-        db_insert('locales_target')
-          ->fields(array(
-            'lid' => $lid,
-            'language' => $this->_langcode,
-            'translation' => $translation,
-            'customized' => $customized,
-          ))
-          ->execute();
-
-        $this->_report['additions']++;
-        return $lid;
-      }
-    }
-    elseif (isset($string->lid) && isset($string->customized) && $overwrite_options[$string->customized ? 'customized' : 'not_customized']) {
-      // Empty translation, remove existing if instructed.
-      db_delete('locales_target')
-        ->condition('language', $this->_langcode)
-        ->condition('lid', $string->lid)
-        ->execute();
-
-      $this->_report['deletes']++;
-      return $string->lid;
-    }
-  }
-
-}
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleImportFunctionalTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleImportFunctionalTest.php
index 016082a..6fe77c2 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleImportFunctionalTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleImportFunctionalTest.php
@@ -197,7 +197,6 @@ class LocaleImportFunctionalTest extends WebTestBase {
     // Ensure the translation file was automatically imported when language was
     // added.
     $this->assertText(t('One translation file imported.'), t('Language file automatically imported.'));
-    $this->assertText(t('A translation string was skipped because of disallowed or malformed HTML'), t('Language file automatically imported.'));
 
     // Ensure strings were successfully imported.
     $search = array(
@@ -207,27 +206,6 @@ class LocaleImportFunctionalTest extends WebTestBase {
     );
     $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
     $this->assertNoText(t('No strings available.'), t('String successfully imported.'));
-
-    // Ensure multiline string was imported.
-    $search = array(
-      'string' => 'Source string for multiline translation',
-      'langcode' => $langcode,
-      'translation' => 'all',
-    );
-    $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
-    $this->assertText('Multiline translation string to make sure that import works with it.', t('String successfully imported.'));
-
-    // Ensure 'Allowed HTML source string' was imported but the translation for
-    // 'Another allowed HTML source string' was not because it contains invalid
-    // HTML.
-    $search = array(
-      'string' => 'HTML source string',
-      'langcode' => $langcode,
-      'translation' => 'all',
-    );
-    $this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
-    $this->assertText('Allowed HTML source string', t('String successfully imported.'));
-    $this->assertNoText('Another allowed HTML source string', t('String with disallowed translation not imported.'));
   }
 
   /**
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
index b63e8cd..c52f483 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
@@ -46,10 +46,12 @@ class LocaleUninstallTest extends WebTestBase {
       'default' => $this->langcode == 'fr',
     );
     language_save($language);
-
+    // Reset the language_manager so that the language interface object gets
+    // freshly initialized.
+    language_manager();
     // Check the UI language.
     drupal_language_initialize();
-    $this->assertEqual(drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode, $this->langcode, t('Current language: %lang', array('%lang' => drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode)));
+    $this->assertEqual(language_manager(LANGUAGE_TYPE_INTERFACE)->langcode, $this->langcode, t('Current language: %lang', array('%lang' => language_manager(LANGUAGE_TYPE_INTERFACE)->langcode)));
 
     // Enable multilingual workflow option for articles.
     variable_set('node_type_language_hidden_article',FALSE);
@@ -91,10 +93,12 @@ class LocaleUninstallTest extends WebTestBase {
 
     // Visit the front page.
     $this->drupalGet('');
-
+    // Reset the language_manager so that the language interface object gets
+    // freshly initialized.
+    language_manager();
     // Check the init language logic.
     drupal_language_initialize();
-    $this->assertEqual(drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode, 'en', t('Language after uninstall: %lang', array('%lang' => drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode)));
+    $this->assertEqual(language_manager(LANGUAGE_TYPE_INTERFACE)->langcode, 'en', t('Language after uninstall: %lang', array('%lang' => language_manager(LANGUAGE_TYPE_INTERFACE)->langcode)));
 
     // Check JavaScript files deletion.
     $this->assertTrue($result = !file_exists($js_file), t('JavaScript file deleted: %file', array('%file' => $result ? $js_file : t('found'))));
diff --git a/core/modules/locale/locale.bulk.inc b/core/modules/locale/locale.bulk.inc
index 8a9c2fe..f795f99 100644
--- a/core/modules/locale/locale.bulk.inc
+++ b/core/modules/locale/locale.bulk.inc
@@ -5,10 +5,7 @@
  * Mass import-export and batch import functionality for Gettext .po files.
  */
 
-use Drupal\Component\Gettext\PoStreamWriter;
-use Drupal\locale\Gettext;
-use Drupal\locale\PoDatabaseReader;
-
+include_once DRUPAL_ROOT . '/core/includes/gettext.inc';
 
 /**
  * User interface for the translation import screen.
@@ -110,39 +107,7 @@ function locale_translate_import_form_submit($form, &$form_state) {
     $customized = $form_state['values']['customized'] ? LOCALE_CUSTOMIZED : LOCALE_NOT_CUSTOMIZED;
 
     // Now import strings into the language
-    try {
-      // Try to allocate enough time to parse and import the data.
-      drupal_set_time_limit(240);
-
-      $report = GetText::fileToDatabase($file, $language->langcode, $form_state['values']['overwrite_options'], $customized);
-      $additions = $report['additions'];
-      $updates = $report['updates'];
-      $deletes = $report['deletes'];
-      $skips = $report['skips'];
-
-      menu_router_rebuild();
-      // Clear cache and force refresh of JavaScript translations.
-      _locale_invalidate_js($language->langcode);
-      cache()->deletePrefix('locale:');
-
-      drupal_set_message(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => $additions, '%update' => $updates, '%delete' => $deletes)));
-      watchdog('locale', 'Imported %file into %locale: %number new strings added, %update updated and %delete removed.', array('%file' => $file->filename, '%locale' => $language->langcode, '%number' => $additions, '%update' => $updates, '%delete' => $deletes));
-      if ($skips) {
-        if (module_exists('dblog')) {
-          $skip_message = format_plural($skips, 'A translation string was skipped because of disallowed or malformed HTML. <a href="@url">See the log</a> for details.', '@count translation strings were skipped because of disallowed or malformed HTML. <a href="@url">See the log</a> for details.', array('@url' => url('admin/reports/dblog')));
-        }
-        else {
-          $skip_message = format_plural($skips, 'A translation string was skipped because of disallowed or malformed HTML. See the log for details.', '@count translation strings were skipped because of disallowed or malformed HTML. See the log for details.');
-        }
-        drupal_set_message($skip_message, 'error');
-        watchdog('locale', '@count disallowed HTML string(s) in %file', array('@count' => $skips, '%file' => $file->uri), WATCHDOG_WARNING);
-      }
-      $variables = array('%filename' => $file->filename);
-      drupal_set_message(t('The translation import of %filename is done.', $variables));
-      watchdog('locale', 'The translation import of %filename is done.', $variables);
-
-    } catch (Exception $exc) {
-      drupal_set_message(print_r($exc, TRUE));
+    if ($return = _locale_import_po($file, $language->langcode, $form_state['values']['overwrite_options'], $customized) == FALSE) {
       $variables = array('%filename' => $file->filename);
       drupal_set_message(t('The translation import of %filename failed.', $variables), 'error');
       watchdog('locale', 'The translation import of %filename failed.', $variables, WATCHDOG_ERROR);
@@ -242,44 +207,7 @@ function locale_translate_export_form_submit($form, &$form_state) {
     $language = NULL;
   }
   $content_options = isset($form_state['values']['content_options']) ? $form_state['values']['content_options'] : array();
-  $reader = new PoDatabaseReader();
-  $languageName = '';
-  if ($language != NULL) {
-    $reader->setLangcode($language->langcode);
-    $reader->setOptions($content_options);
-    $languages = language_list();
-    $languageName = isset($languages[$language->langcode]) ? $languages[$language->langcode]->name : '';
-    $filename = $language->langcode .'.po';
-  }
-  else {
-    // Template required.
-    $filename = 'drupal.pot';
-  }
-
-  $item = $reader->readItem();
-  if (!empty($item)) {
-    $uri = tempnam('temporary://', 'po_');
-    $header = $reader->getHeader();
-    $header->setProjectName(variable_get('site_name', 'Drupal'));
-    $header->setLanguageName($languageName);
-
-    $writer = new PoStreamWriter;
-    $writer->setUri($uri);
-    $writer->setHeader($header);
-
-    $writer->open();
-    $writer->writeItem($item);
-    $writer->writeItems($reader);
-    $writer->close();
-
-    header("Content-Disposition: attachment; filename=$filename");
-    header("Content-Type: text/plain; charset=utf-8");
-    print file_get_contents($uri);
-    drupal_exit();
-  }
-  else {
-    drupal_set_message('Nothing to export.');
-  }
+  _locale_export_po($language, _locale_export_po_generate($language, _locale_export_get_strings($language, $content_options)));
 }
 
 /**
@@ -329,7 +257,7 @@ function locale_translate_batch_import_files($langcode = NULL, $finish_feedback
       ->fetchAllAssoc('uri');
     foreach ($result as $uri => $info) {
       if (isset($files[$uri]) && filemtime($uri) <= $info->timestamp) {
-        // The file is already imported and not changed since the last import.
+        // The file is already imported and it did not change since the import.
         // Remove it from file list and don't import it again.
         unset($files[$uri]);
       }
@@ -390,32 +318,22 @@ function locale_translate_batch_build($files, $finish_feedback = FALSE) {
 /**
  * Perform interface translation import as a batch step.
  *
- * The given filepath is matched against ending with '{langcode}.po'. When
- * matched the filepath is added to batch context.
- *
  * @param $filepath
  *   Path to a file to import.
- * @param $context
+ * @param $results
  *   Contains a list of files imported.
  */
 function locale_translate_batch_import($filepath, &$context) {
   // The filename is either {langcode}.po or {prefix}.{langcode}.po, so
   // we can extract the language code to use for the import from the end.
   if (preg_match('!(/|\.)([^\./]+)\.po$!', $filepath, $langcode)) {
-    $file = entity_create('file', array('filename' => drupal_basename($filepath), 'uri' => $filepath));
-    // We need only the last match
-    $langcode = array_pop($langcode);
-    try {
-      $report = GetText::fileToDatabase($file, $langcode, array(), LOCALE_NOT_CUSTOMIZED);
-      $file->langcode = $langcode;
-      $file->timestamp = filemtime($file->uri);
+    $file = locale_translate_file_create($filepath, $langcode[2]);
+    $success = _locale_import_read_po('db-store', $file, array(), $langcode[2]);
+    if ($success == NULL) {
+      $file->langcode = $langcode[2];
       locale_translate_update_file_history($file);
-      $context['results']['files'][$filepath] = $filepath;
-      $context['results']['stats'][$filepath] = $report;
-    } catch (Exception $exception) {
-      $context['results']['files'][$filepath] = $filepath;
-      $context['results']['failed_files'][$filepath] = $filepath;
     }
+    $context['results'][] = $filepath;
   }
 }
 
@@ -424,30 +342,7 @@ function locale_translate_batch_import($filepath, &$context) {
  */
 function locale_translate_batch_finished($success, $results) {
   if ($success) {
-    $additions = $updates = $deletes = $skips = 0;
-    drupal_set_message(format_plural(count($results['files']), 'One translation file imported.', '@count translation files imported.'));
-    $skipped_files = array();
-    foreach ($results['stats'] as $filepath => $report) {
-      $additions += $report['additions'];
-      $updates += $report['updates'];
-      $deletes += $report['deletes'];
-      $skips += $report['skips'];
-      if ($report['skips'] > 0) {
-        $skipped_files[] = $filepath;
-      }
-    }
-    drupal_set_message(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => $additions, '%update' => $updates, '%delete' => $deletes)));
-    watchdog('locale', 'The translation was succesfully imported. %number new strings added, %update updated and %delete removed.', array('%number' => $additions, '%update' => $updates, '%delete' => $deletes));
-    if ($skips) {
-      if (module_exists('dblog')) {
-        $skip_message = format_plural($skips, 'A translation string was skipped because of disallowed or malformed HTML. <a href="@url">See the log</a> for details.', '@count translation strings were skipped because of disallowed or malformed HTML. <a href="@url">See the log</a> for details.', array('@url' => url('admin/reports/dblog')));
-      }
-      else {
-        $skip_message = format_plural($skips, 'A translation string was skipped because of disallowed or malformed HTML. See the log for details.', '@count translation strings were skipped because of disallowed or malformed HTML. See the log for details.');
-      }
-      drupal_set_message($skip_message, 'error');
-      watchdog('locale', '@count disallowed HTML string(s) in files: @files.', array('@count' => $skips, '@files' => implode(',', $skipped_files)), WATCHDOG_WARNING);
-    }
+    drupal_set_message(format_plural(count($results), 'One translation file imported.', '@count translation files imported.'));
   }
 }
 
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index ce20b59..92b8c1e 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -232,7 +232,7 @@ function locale_language_delete($language) {
  *   Language code to use for the lookup.
  */
 function locale($string = NULL, $context = NULL, $langcode = NULL) {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   // Use the advanced drupal_static() pattern, since this is called very often.
   static $drupal_static_fast;
@@ -280,7 +280,7 @@ function locale_reset() {
  *   plural formula.
  */
 function locale_get_plural($count, $langcode = NULL) {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   // Used to locally cache the plural formulas for all languages.
   $plural_formulas = &drupal_static(__FUNCTION__, array());
@@ -366,7 +366,7 @@ function locale_system_update($components) {
  * file if necessary, and adds it to the page.
  */
 function locale_js_alter(&$javascript) {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   $dir = 'public://' . variable_get('locale_js_directory', 'languages');
   $parsed = variable_get('javascript_parsed', array());
@@ -426,7 +426,7 @@ function locale_js_alter(&$javascript) {
  */
 function locale_library_info_alter(&$libraries, $module) {
   if ($module == 'system' && isset($libraries['jquery.ui.datepicker'])) {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
     // locale.datepicker.js should be added in the JS_LIBRARY group, so that
     // this attach behavior will execute early. JS_LIBRARY is the default for
     // hook_library_info_alter(), thus does not have to be specified explicitly.
@@ -572,7 +572,7 @@ function locale_form_system_file_system_settings_alter(&$form, $form_state) {
  */
 function locale_preprocess_node(&$variables) {
   if ($variables['langcode'] != LANGUAGE_NOT_SPECIFIED) {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
     $node_language = language_load($variables['langcode']);
     if ($node_language->langcode != $language_interface->langcode) {
@@ -771,7 +771,7 @@ function _locale_invalidate_js($langcode = NULL) {
  */
 function _locale_rebuild_js($langcode = NULL) {
   if (!isset($langcode)) {
-    $language = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language = language_manager(LANGUAGE_TYPE_INTERFACE);
   }
   else {
     // Get information about the locale.
diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc
index b91d3a4..25f45fc 100644
--- a/core/modules/locale/locale.pages.inc
+++ b/core/modules/locale/locale.pages.inc
@@ -103,7 +103,7 @@ function locale_translate_filters() {
   }
 
   // Pick the current interface language code for the filter.
-  $default_langcode = drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode;
+  $default_langcode = language_manager(LANGUAGE_TYPE_INTERFACE)->langcode;
   if (!isset($language_options[$default_langcode])) {
     $available_langcodes = array_keys($language_options);
     $default_langcode = array_shift($available_langcodes);
diff --git a/core/modules/locale/tests/test.xx.po b/core/modules/locale/tests/test.xx.po
index e2db1d3..659a6e3 100644
--- a/core/modules/locale/tests/test.xx.po
+++ b/core/modules/locale/tests/test.xx.po
@@ -26,15 +26,3 @@ msgstr "samedi"
 
 msgid "Sunday"
 msgstr "dimanche"
-
-msgid "Allowed HTML source string"
-msgstr "<strong>Allowed HTML translation string</strong>"
-
-msgid "Another allowed HTML source string"
-msgstr "<script>Disallowed HTML translation string</script>"
-
-msgid "Source string for multiline translation"
-msgstr ""
-"Multiline translation string "
-"to make sure that "
-"import works with it."
diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php
index 9d98550..3eeaf26 100644
--- a/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php
+++ b/core/modules/node/lib/Drupal/node/Tests/NodeTokenReplaceTest.php
@@ -23,7 +23,7 @@ class NodeTokenReplaceTest extends NodeTestBase {
    * Creates a node, then tests the tokens generated from it.
    */
   function testNodeTokenReplacement() {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
     $url_options = array(
       'absolute' => TRUE,
       'language' => $language_interface,
diff --git a/core/modules/node/node.module b/core/modules/node/node.module
index 52b1471..b583b29 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -646,7 +646,7 @@ function node_field_extra_fields() {
 function node_type_get_default_langcode($node_type) {
   $default_value = variable_get('node_type_language_default_' . $node_type, 'site_default');
 
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   if ($default_value == LANGUAGE_NOT_SPECIFIED) {
     return LANGUAGE_NOT_SPECIFIED;
@@ -736,7 +736,7 @@ function node_type_update_nodes($old_type, $type) {
  *   type object by $type->disabled being set to TRUE.
  */
 function _node_types_build($rebuild = FALSE) {
-  $cid = 'node_types:' . drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode;
+  $cid = 'node_types:' . language_manager(LANGUAGE_TYPE_INTERFACE)->langcode;
 
   if (!$rebuild) {
     $_node_types = &drupal_static(__FUNCTION__);
@@ -1179,7 +1179,7 @@ function node_revision_delete($revision_id) {
  */
 function node_view(Node $node, $view_mode = 'full', $langcode = NULL) {
   if (!isset($langcode)) {
-    $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode;
+    $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode;
   }
 
   // Populate $node->content with a render() array.
@@ -1240,7 +1240,7 @@ function node_view(Node $node, $view_mode = 'full', $langcode = NULL) {
  */
 function node_build_content(Node $node, $view_mode = 'full', $langcode = NULL) {
   if (!isset($langcode)) {
-    $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode;
+    $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode;
   }
 
   // Remove previously built content, if exists.
@@ -2445,8 +2445,7 @@ function node_block_list_alter(&$blocks) {
  */
 function node_feed($nids = FALSE, $channel = array()) {
   global $base_url;
-  $language_content = drupal_container()->get(LANGUAGE_TYPE_CONTENT);
-  $rss_config = config('system.rss');
+  $language_content = language_manager(LANGUAGE_TYPE_CONTENT);
 
   if ($nids === FALSE) {
     $nids = db_select('node', 'n')
@@ -2454,13 +2453,13 @@ function node_feed($nids = FALSE, $channel = array()) {
       ->condition('n.promote', 1)
       ->condition('n.status', 1)
       ->orderBy('n.created', 'DESC')
-      ->range(0, $rss_config->get('items.limit'))
+      ->range(0, config('system.rss-publishing')->get('feed_default_items'))
       ->addTag('node_access')
       ->execute()
       ->fetchCol();
   }
 
-  $item_length = $rss_config->get('items.view_mode');
+  $item_length = config('system.rss-publishing')->get('feed_item_length');
   $namespaces = array('xmlns:dc' => 'http://purl.org/dc/elements/1.1/');
   $teaser = ($item_length == 'teaser');
 
@@ -2500,7 +2499,7 @@ function node_feed($nids = FALSE, $channel = array()) {
     'version'     => '2.0',
     'title'       => config('system.site')->get('name'),
     'link'        => $base_url,
-    'description' => $rss_config->get('channel.description'),
+    'description' => config('system.rss-publishing')->get('feed_description'),
     'language'    => $language_content->langcode
   );
   $channel_extras = array_diff_key($channel, $channel_defaults);
@@ -3258,9 +3257,10 @@ function _node_query_node_access_alter($query, $type) {
 
   $tables = $query->getTables();
   $base_table = $query->getMetaData('base_table');
-  // If the base table is not given, default to node if present.
+  // If no base table is specified explicitly, search for one.
   if (!$base_table) {
-    foreach ($tables as $table_info) {
+    $fallback = '';
+    foreach ($tables as $alias => $table_info) {
       if (!($table_info instanceof SelectInterface)) {
         $table = $table_info['table'];
         // If the node table is in the query, it wins immediately.
@@ -3268,11 +3268,38 @@ function _node_query_node_access_alter($query, $type) {
           $base_table = $table;
           break;
         }
+        // Check whether the table has a foreign key to node.nid. If it does,
+        // do not run this check again as we found a base table and only node
+        // can triumph that.
+        if (!$base_table) {
+          // The schema is cached.
+          $schema = drupal_get_schema($table);
+          if (isset($schema['fields']['nid'])) {
+            if (isset($schema['foreign keys'])) {
+              foreach ($schema['foreign keys'] as $relation) {
+                if ($relation['table'] === 'node' && $relation['columns'] === array('nid' => 'nid')) {
+                  $base_table = $table;
+                }
+              }
+            }
+            else {
+              // At least it's a nid. A table with a field called nid is very
+              // very likely to be a node.nid in a node access query.
+              $fallback = $table;
+            }
+          }
+        }
       }
     }
-    // Bail out if the base table is missing.
+    // If there is nothing else, use the fallback.
     if (!$base_table) {
-      throw new Exception(t('Query tagged for node access but there is no node table, specify the base_table using meta data.'));
+      if ($fallback) {
+        watchdog('security', 'Your node listing query is using @fallback as a base table in a query tagged for node access. This might not be secure and might not even work. Specify foreign keys in your schema to node.nid ', array('@fallback' => $fallback), WATCHDOG_WARNING);
+        $base_table = $fallback;
+      }
+      else {
+        throw new Exception(t('Query tagged for node access but there is no nid. Add foreign keys to node.nid in schema to fix.'));
+      }
     }
   }
 
diff --git a/core/modules/openid/openid.inc b/core/modules/openid/openid.inc
index d594dde..f6dc2a5 100644
--- a/core/modules/openid/openid.inc
+++ b/core/modules/openid/openid.inc
@@ -83,7 +83,7 @@ function openid_redirect_http($url, $message) {
  * Creates a js auto-submit redirect for (for the 2.x protocol)
  */
 function openid_redirect($url, $message) {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   $output = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">' . "\n";
   $output .= '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="' . $language_interface->langcode . '" lang="' . $language_interface->langcode . '">' . "\n";
diff --git a/core/modules/overlay/overlay.module b/core/modules/overlay/overlay.module
index e57ff5f..c4fc134 100644
--- a/core/modules/overlay/overlay.module
+++ b/core/modules/overlay/overlay.module
@@ -333,7 +333,7 @@ function overlay_user_dismiss_message() {
   // @todo CSRF tokens are validated in page callbacks rather than access
   //   callbacks, because access callbacks are also invoked during menu link
   //   generation. Add token support to routing: http://drupal.org/node/755584.
-  $token = request()->query->get('token');
+  $token = drupal_container()->get('request')->query->get('token');
   if (!isset($token) || !drupal_valid_token($token, 'overlay')) {
     throw new AccessDeniedHttpException();
   }
@@ -693,7 +693,7 @@ function overlay_overlay_child_initialize() {
   // it to the same content rendered in overlay_exit(), at the end of the page
   // request. This allows us to check if anything actually did change, and, if
   // so, trigger an immediate Ajax refresh of the parent window.
-  $token = request()->query->get('token');
+  $token = drupal_container()->get('request')->query->get('token');
   if (!empty($_POST) || isset($token)) {
     foreach (overlay_supplemental_regions() as $region) {
       overlay_store_rendered_content($region, overlay_render_region($region));
diff --git a/core/modules/poll/lib/Drupal/poll/Tests/PollTokenReplaceTest.php b/core/modules/poll/lib/Drupal/poll/Tests/PollTokenReplaceTest.php
index 3aaab13..56e0854 100644
--- a/core/modules/poll/lib/Drupal/poll/Tests/PollTokenReplaceTest.php
+++ b/core/modules/poll/lib/Drupal/poll/Tests/PollTokenReplaceTest.php
@@ -23,7 +23,7 @@ class PollTokenReplaceTest extends PollTestBase {
    * Creates a poll, then tests the tokens generated from it.
    */
   function testPollTokenReplacement() {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
     // Craete a poll with three choices.
     $title = $this->randomName();
diff --git a/core/modules/search/search.pages.inc b/core/modules/search/search.pages.inc
index c940223..9709737 100644
--- a/core/modules/search/search.pages.inc
+++ b/core/modules/search/search.pages.inc
@@ -104,7 +104,7 @@ function template_preprocess_search_results(&$variables) {
  * @see search-result.tpl.php
  */
 function template_preprocess_search_result(&$variables) {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   $result = $variables['result'];
   $variables['url'] = check_url($result['link']);
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
index 794054d..e5107e8 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -622,7 +622,7 @@ abstract class TestBase {
    */
   protected function prepareEnvironment() {
     global $user, $conf;
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
     // Backup current in-memory configuration.
     $this->originalConf = $conf;
@@ -690,7 +690,7 @@ abstract class TestBase {
    */
   protected function tearDown() {
     global $user, $conf;
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
     // In case a fatal error occurred that was not in the test process read the
     // log to pick up any fatal errors.
diff --git a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
index b006cdd..f7f4701 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/WebTestBase.php
@@ -579,7 +579,7 @@ abstract class WebTestBase extends TestBase {
    */
   protected function setUp() {
     global $user, $conf;
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
     // Create the database prefix for this test.
     $this->prepareDatabasePrefix();
diff --git a/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsTokenReplaceTest.php b/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsTokenReplaceTest.php
index 0cc6e41..fcfc21e 100644
--- a/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsTokenReplaceTest.php
+++ b/core/modules/statistics/lib/Drupal/statistics/Tests/StatisticsTokenReplaceTest.php
@@ -23,7 +23,7 @@ class StatisticsTokenReplaceTest extends StatisticsTestBase {
    * Creates a node, then tests the statistics tokens generated from it.
    */
   function testStatisticsTokenReplacement() {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
     // Create user and node.
     $user = $this->drupalCreateUser(array('create page content'));
diff --git a/core/modules/system/config/system.rss-publishing.yml b/core/modules/system/config/system.rss-publishing.yml
new file mode 100644
index 0000000..5662aad
--- /dev/null
+++ b/core/modules/system/config/system.rss-publishing.yml
@@ -0,0 +1,3 @@
+feed_description: ''
+feed_default_items: '10'
+feed_item_length: fulltext
diff --git a/core/modules/system/config/system.rss.yml b/core/modules/system/config/system.rss.yml
deleted file mode 100644
index 74b3228..0000000
--- a/core/modules/system/config/system.rss.yml
+++ /dev/null
@@ -1,5 +0,0 @@
-channel:
-    description: ''
-items:
-    limit: '10'
-    view_mode: fulltext
diff --git a/core/modules/system/language.api.php b/core/modules/system/language.api.php
index d18b273..8a13da3 100644
--- a/core/modules/system/language.api.php
+++ b/core/modules/system/language.api.php
@@ -26,7 +26,7 @@
 function hook_language_init() {
   global $conf;
 
-  switch (drupal_container()->get(LANGUAGE_TYPE_INTERFACE)->langcode) {
+  switch (language_manager(LANGUAGE_TYPE_INTERFACE)->langcode) {
     case 'it':
       $conf['system.site']['name'] = 'Il mio sito Drupal';
       break;
@@ -52,7 +52,7 @@ function hook_language_init() {
  *   The current path.
  */
 function hook_language_switch_links_alter(array &$links, $type, $path) {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   if ($type == LANGUAGE_TYPE_CONTENT && isset($links[$language_interface->langcode])) {
     foreach ($links[$language_interface->langcode] as $link) {
diff --git a/core/modules/system/lib/Drupal/system/Tests/Bundle/BundleTest.php b/core/modules/system/lib/Drupal/system/Tests/Bundle/BundleTest.php
new file mode 100644
index 0000000..fef908c
--- /dev/null
+++ b/core/modules/system/lib/Drupal/system/Tests/Bundle/BundleTest.php
@@ -0,0 +1,44 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\system\Tests\Bundle\BundleTest.
+ */
+
+namespace Drupal\system\Tests\Bundle;
+
+use Drupal\simpletest\WebTestBase;
+
+/**
+ * Test bundle registration to the DIC.
+ */
+class BundleTest extends WebTestBase {
+  public static function getInfo() {
+    return array(
+      'name' => 'Bundle Registration',
+      'description' => 'Tests bundle registration to the DIC.',
+      'group' => 'Bundle',
+    );
+  }
+
+  function setUp() {
+    parent::setUp('bundle_test');
+  }
+
+  /**
+   * Test that services provided by module bundles get registered to the DIC.
+   */
+  function testBundleRegistration() {
+    // The page callback at /bundle_test checks
+    // drupal_container()->has('bundle_test_class')
+    // and if this returns TRUE it outputs a message to this effect. We just
+    // need to check that the message appears on the page.
+    $this->drupalGet('bundle_test');
+    $this->assertText(t('The service with id bundle_test_class is available in the DIC'), t('The bundle_test_class service has been registered to the DIC'));
+    // The event subscriber method in the test class calls drupal_set_message with
+    // a message saying it has fired. This will fire on every page request so it
+    // should show up on the front page.
+    $this->drupalGet('');
+    $this->assertText(t('The bundle_test event subscriber fired!'), t('The bundle_test event subscriber fired'));
+  }
+}
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/CascadingStylesheetsTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/CascadingStylesheetsTest.php
index 397762b..8452c41 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/CascadingStylesheetsTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/CascadingStylesheetsTest.php
@@ -222,7 +222,7 @@ class CascadingStylesheetsTest extends WebTestBase {
    */
   function testAlter() {
     // Switch the language to a right to left language and add system.base.css.
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
     $language_interface->direction = LANGUAGE_RTL;
     $path = drupal_get_path('module', 'system');
     drupal_add_css($path . '/system.base.css');
diff --git a/core/modules/system/lib/Drupal/system/Tests/Common/FormatDateTest.php b/core/modules/system/lib/Drupal/system/Tests/Common/FormatDateTest.php
index 7a71d33..5bfb9b6 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Common/FormatDateTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Common/FormatDateTest.php
@@ -72,7 +72,7 @@ class FormatDateTest extends WebTestBase {
   function testFormatDate() {
     global $user;
 
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
     $timestamp = strtotime('2007-03-26T00:00:00+00:00');
     $this->assertIdentical(format_date($timestamp, 'custom', 'l, d-M-y H:i:s T', 'America/Los_Angeles', 'en'), 'Sunday, 25-Mar-07 17:00:00 PDT', t('Test all parameters.'));
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 d4eceba..ac1e611 100644
--- a/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/Mail/MailTest.php
@@ -41,7 +41,7 @@ class MailTest extends WebTestBase implements MailInterface {
    * Assert that the pluggable mail system is functional.
    */
   public function testPluggableFramework() {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
     // Use MailTestCase for sending a message.
     $message = drupal_mail('simpletest', 'mail_test', 'testing@example.com', $language_interface);
diff --git a/core/modules/system/lib/Drupal/system/Tests/System/TokenReplaceTest.php b/core/modules/system/lib/Drupal/system/Tests/System/TokenReplaceTest.php
index c329b96..9611f5e 100644
--- a/core/modules/system/lib/Drupal/system/Tests/System/TokenReplaceTest.php
+++ b/core/modules/system/lib/Drupal/system/Tests/System/TokenReplaceTest.php
@@ -30,7 +30,7 @@ class TokenReplaceTest extends WebTestBase {
     $node = $this->drupalCreateNode(array('uid' => $account->uid));
     $node->title = '<blink>Blinking Text</blink>';
     global $user;
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
     $source  = '[node:title]';         // Title of the node we passed in
     $source .= '[node:author:name]';   // Node author's name
@@ -75,7 +75,7 @@ class TokenReplaceTest extends WebTestBase {
    * Test whether token-replacement works in various contexts.
    */
   function testSystemTokenRecognition() {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
     // Generate prefixes and suffixes for the token context.
     $tests = array(
@@ -104,7 +104,7 @@ class TokenReplaceTest extends WebTestBase {
    * Tests the generation of all system site information tokens.
    */
   function testSystemSiteTokenReplacement() {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
     $url_options = array(
       'absolute' => TRUE,
       'language' => $language_interface,
@@ -147,7 +147,7 @@ class TokenReplaceTest extends WebTestBase {
    * Tests the generation of all system date tokens.
    */
   function testSystemDateTokenReplacement() {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
     // Set time to one hour before request.
     $date = REQUEST_TIME - 3600;
diff --git a/core/modules/system/system.admin.inc b/core/modules/system/system.admin.inc
index d956f05..dcd261c 100644
--- a/core/modules/system/system.admin.inc
+++ b/core/modules/system/system.admin.inc
@@ -1882,48 +1882,47 @@ function system_image_toolkit_settings() {
  * Form builder; Configure how the site handles RSS feeds.
  *
  * @ingroup forms
+ * @see system_settings_form()
  */
 function system_rss_feeds_settings($form, &$form_state) {
-  $rss_config = config('system.rss');
   $form['feed_description'] = array(
     '#type' => 'textarea',
     '#title' => t('Feed description'),
-    '#default_value' => $rss_config->get('channel.description'),
+    '#default_value' => config('system.rss-publishing')->get('feed_description'),
     '#description' => t('Description of your site, included in each feed.')
   );
   $form['feed_default_items'] = array(
     '#type' => 'select',
     '#title' => t('Number of items in each feed'),
-    '#default_value' => $rss_config->get('items.limit'),
+    '#default_value' => config('system.rss-publishing')->get('feed_default_items'),
     '#options' => drupal_map_assoc(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30)),
     '#description' => t('Default number of items to include in each feed.')
   );
   $form['feed_item_length'] = array(
     '#type' => 'select',
     '#title' => t('Feed content'),
-    '#default_value' => $rss_config->get('items.view_mode'),
-    '#options' => array(
-      'title' => t('Titles only'),
-      'teaser' => t('Titles plus teaser'),
-      'fulltext' => t('Full text'),
-    ),
+    '#default_value' => config('system.rss-publishing')->get('feed_item_length'),
+    '#options' => array('title' => t('Titles only'), 'teaser' => t('Titles plus teaser'), 'fulltext' => t('Full text')),
     '#description' => t('Global setting for the default display of content items in each feed.')
   );
+  $form['submit'] = array('#type' => 'submit', '#value' => t('Submit'));
 
-  return system_config_form($form, $form_state);
+  return $form;
 }
 
 /**
  * Form builder submit handler; Handle submission for RSS feeds settings.
  *
  * @ingroup forms
+ * @see system_settings_form()
  */
 function system_rss_feeds_settings_submit($form, &$form_state) {
-  config('system.rss')
-    ->set('channel.description', $form_state['values']['feed_description'])
-    ->set('items.limit', $form_state['values']['feed_default_items'])
-    ->set('items.view_mode', $form_state['values']['feed_item_length'])
-    ->save();
+  // Set the RSS publishing parameters.
+  $config = config('system.rss-publishing');
+  $config->set('feed_description', $form_state['values']['feed_description']);
+  $config->set('feed_default_items', $form_state['values']['feed_default_items']);
+  $config->set('feed_item_length', $form_state['values']['feed_item_length']);
+  $config->save();
 }
 
 /**
diff --git a/core/modules/system/system.api.php b/core/modules/system/system.api.php
index 3d2cae0..0dc087d 100644
--- a/core/modules/system/system.api.php
+++ b/core/modules/system/system.api.php
@@ -1896,7 +1896,7 @@ function hook_custom_theme() {
  */
 function hook_watchdog(array $log_entry) {
   global $base_url;
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   $severity_list = array(
     WATCHDOG_EMERGENCY     => t('Emergency'),
diff --git a/core/modules/system/system.install b/core/modules/system/system.install
index 91d5304..ee46319 100644
--- a/core/modules/system/system.install
+++ b/core/modules/system/system.install
@@ -1909,10 +1909,10 @@ function system_update_8009() {
  * @ingroup config_upgrade
  */
 function system_update_8010() {
-  update_variables_to_config('system.rss', array(
-    'feed_description' => 'channel.description',
-    'feed_default_items' => 'items.limit',
-    'feed_item_length' => 'items.view_mode',
+  update_variables_to_config('system.rss-publishing', array(
+    'feed_description' => 'feed_description',
+    'feed_default_items' => 'feed_default_items',
+    'feed_item_length' => 'feed_item_length',
   ));
 }
 
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index 14cc390..369a11f 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2067,7 +2067,7 @@ function system_filetransfer_info() {
 function system_init() {
   global $conf;
 
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
   // For each date type (e.g. long, short), get the localized date format
   // for the user's current language and override the default setting for it
   // in $conf. This should happen on all pages except the date and time formats
@@ -2200,7 +2200,8 @@ function system_add_module_assets() {
  * Implements hook_custom_theme().
  */
 function system_custom_theme() {
-  if ($request = request()) {
+  if (drupal_container()->has('request')) {
+    $request = drupal_container()->get('request');
     $path = $request->attributes->get('system_path');
     if (user_access('view the administration theme') && path_is_admin($path)) {
       return variable_get('admin_theme');
diff --git a/core/modules/system/tests/http.php b/core/modules/system/tests/http.php
index 9364685..91ad800 100644
--- a/core/modules/system/tests/http.php
+++ b/core/modules/system/tests/http.php
@@ -5,6 +5,7 @@
  * Fake an HTTP request, for use during testing.
  */
 
+use Drupal\Core\DrupalKernel;
 use Symfony\Component\HttpFoundation\Request;
 
 // Set a global variable to indicate a mock HTTP request.
@@ -32,10 +33,10 @@ if (!drupal_valid_test_ua()) {
 
 // Continue with normal request handling.
 $request = Request::createFromGlobals();
-request($request);
 
 drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
 
-$kernel = drupal_container()->get('httpkernel');
+$kernel = new DrupalKernel('prod', FALSE);
+$kernel->boot();
 $response = $kernel->handle($request)->prepare($request)->send();
 $kernel->terminate($request, $response);
diff --git a/core/modules/system/tests/https.php b/core/modules/system/tests/https.php
index 11b7e13..f5f7ce7 100644
--- a/core/modules/system/tests/https.php
+++ b/core/modules/system/tests/https.php
@@ -5,6 +5,7 @@
  * Fake an https request, for use during testing.
  */
 
+use Drupal\Core\DrupalKernel;
 use Symfony\Component\HttpFoundation\Request;
 
 // Set a global variable to indicate a mock HTTPS request.
@@ -31,10 +32,10 @@ if (!drupal_valid_test_ua()) {
 
 // Continue with normal request handling.
 $request = Request::createFromGlobals();
-request($request);
 
 drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
 
-$kernel = drupal_container()->get('httpkernel');
+$kernel = new DrupalKernel('prod', FALSE);
+$kernel->boot();
 $response = $kernel->handle($request)->prepare($request)->send();
 $kernel->terminate($request, $response);
diff --git a/core/modules/system/tests/modules/bundle_test/bundle_test.info b/core/modules/system/tests/modules/bundle_test/bundle_test.info
new file mode 100644
index 0000000..ec79843
--- /dev/null
+++ b/core/modules/system/tests/modules/bundle_test/bundle_test.info
@@ -0,0 +1,6 @@
+name = "Bundle test"
+description = "Support module for bundle testing."
+package = Testing
+version = VERSION
+core = 8.x
+hidden = TRUE
diff --git a/core/modules/system/tests/modules/bundle_test/bundle_test.module b/core/modules/system/tests/modules/bundle_test/bundle_test.module
new file mode 100644
index 0000000..5f30b8f
--- /dev/null
+++ b/core/modules/system/tests/modules/bundle_test/bundle_test.module
@@ -0,0 +1,26 @@
+<?php
+
+/**
+ * Implements hook_menu().
+ */
+function bundle_test_menu() {
+  $items['bundle_test'] = array(
+    'type' => MENU_CALLBACK,
+    'title' => t('Bundle test callback'),
+    'page callback' => 'bundle_test_callback',
+    'access callback' => TRUE,
+  );
+  return $items;
+}
+
+/**
+ * Simple callback for testing that the bundle_test_class service exists in the
+ * DIC.
+ */
+function bundle_test_callback() {
+  if (drupal_container()->has('bundle_test_class')) {
+    return t('The service with id bundle_test_class is available in the DIC');
+  }
+  return t('Service not found');
+}
+
diff --git a/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/BundleTestBundle.php b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/BundleTestBundle.php
new file mode 100644
index 0000000..c124007
--- /dev/null
+++ b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/BundleTestBundle.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\bundle_test\BundleTestBundle.
+ */
+
+namespace Drupal\bundle_test;
+
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+/**
+ * Test bundle class.
+ */
+class BundleTestBundle extends Bundle
+{
+  public function build(ContainerBuilder $container) {
+    $container->register('bundle_test_class', 'Drupal\bundle_test\TestClass')
+      ->addTag('kernel.event_subscriber');
+  }
+}
diff --git a/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php
new file mode 100644
index 0000000..f58f9c9
--- /dev/null
+++ b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/TestClass.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\bundle_test\TestClass.
+ */
+
+namespace Drupal\bundle_test;
+
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+class TestClass implements EventSubscriberInterface {
+
+  /**
+   * A simple kernel listener method.
+   */
+  public function onKernelRequestTest(GetResponseEvent $event) {
+    drupal_set_message(t('The bundle_test event subscriber fired!'));
+  }
+
+  /**
+   * Registers methods as kernel listeners.
+   *
+   * @return array
+   *   An array of event listener definitions.
+   */
+  static function getSubscribedEvents() {
+    $events[KernelEvents::REQUEST][] = array('onKernelRequestTest', 100);
+    return $events;
+  }
+}
diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php
index 7539d96..6e2594f 100644
--- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php
+++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php
@@ -62,7 +62,7 @@ class TokenReplaceTest extends TaxonomyTestBase {
    * Creates some terms and a node, then tests the tokens generated from them.
    */
   function testTaxonomyTokenReplacement() {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
     // Create two taxonomy terms.
     $term1 = $this->createTerm($this->vocabulary);
diff --git a/core/modules/taxonomy/taxonomy.module b/core/modules/taxonomy/taxonomy.module
index 1086f19..608c7cc 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -228,7 +228,6 @@ function taxonomy_select_nodes($tid, $pager = TRUE, $limit = FALSE, $order = arr
   }
   $query = db_select('taxonomy_index', 't');
   $query->addTag('node_access');
-  $query->addMetaData('base_table', 'taxonomy_index');
   $query->condition('tid', $tid);
   if ($pager) {
     $count_query = clone $query;
@@ -585,7 +584,7 @@ function taxonomy_term_delete_multiple(array $tids) {
  */
 function taxonomy_term_view(Term $term, $view_mode = 'full', $langcode = NULL) {
   if (!isset($langcode)) {
-    $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode;
+    $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode;
   }
 
   field_attach_prepare_view('taxonomy_term', array($term->tid => $term), $view_mode, $langcode);
diff --git a/core/modules/taxonomy/taxonomy.pages.inc b/core/modules/taxonomy/taxonomy.pages.inc
index 7f4edfc..879d685 100644
--- a/core/modules/taxonomy/taxonomy.pages.inc
+++ b/core/modules/taxonomy/taxonomy.pages.inc
@@ -73,7 +73,7 @@ function taxonomy_term_feed(Term $term) {
   // Only display the description if we have a single term, to avoid clutter and confusion.
   // HTML will be removed from feed description.
   $channel['description'] = check_markup($term->description, $term->format, '', TRUE);
-  $nids = taxonomy_select_nodes($term->tid, FALSE, config('system.rss')->get('items.limit'));
+  $nids = taxonomy_select_nodes($term->tid, FALSE, config('system.rss-publishing')->get('feed_default_items'));
 
   node_feed($nids, $channel);
 }
diff --git a/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerNodeAccessTest.php b/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerNodeAccessTest.php
deleted file mode 100644
index cb74f02..0000000
--- a/core/modules/tracker/lib/Drupal/tracker/Tests/TrackerNodeAccessTest.php
+++ /dev/null
@@ -1,67 +0,0 @@
-<?php
-
-/**
- * @file
- * Definition of Drupal\tracker\Tests\TrackerNodeAccessTest.
- */
-
-namespace Drupal\tracker\Tests;
-
-use Drupal\simpletest\WebTestBase;
-
-/**
- * Tests for private node access on /tracker.
- */
-class TrackerNodeAccessTest extends WebTestBase {
-  protected $access_user;
-  protected $no_access_user;
-
-  public static function getInfo() {
-    return array(
-      'name' => 'Tracker Node Access Tests',
-      'description' => 'Tests for private node access on /tracker.',
-      'group' => 'Tracker',
-    );
-  }
-
-  public function setUp() {
-    parent::setUp(array('node', 'comment', 'tracker', 'node_access_test'));
-    node_access_rebuild();
-    variable_set('node_access_test_private', TRUE);
-  }
-
-
-  /**
-   * Ensure private node on /tracker is only visible to users with permission.
-   */
-  function testTrackerNodeAccess() {
-    // Create user with node test view permission.
-    $access_user = $this->drupalCreateUser(array('node test view'));
-
-    // Create user without node test view permission.
-    $no_access_user = $this->drupalCreateuser();
-
-    $this->drupalLogin($access_user);
-
-    // Create some nodes.
-    $private_node = $this->drupalCreateNode(array(
-      'title' => t('Private node test'),
-      'private'=> TRUE,
-    ));
-    $public_node = $this->drupalCreateNode(array(
-      'title' => t('Public node test'),
-      'private'=>FALSE,
-    ));
-
-    // User with access should see both nodes created.
-    $this->drupalGet('tracker');
-    $this->assertText($private_node->title, 'Private node is visible to user with private access.');
-    $this->assertText($public_node->title, 'Public node is visible to user with private access.');
-
-    // User without access should not see private node.
-    $this->drupalLogin($no_access_user);
-    $this->drupalGet('tracker');
-    $this->assertNoText($private_node->title, 'Private node is not visible to user without private access.');
-    $this->assertText($public_node->title, 'Public node is visible to user without private access.');
-  }
-}
diff --git a/core/modules/tracker/tracker.pages.inc b/core/modules/tracker/tracker.pages.inc
index f012264..a36bf13 100644
--- a/core/modules/tracker/tracker.pages.inc
+++ b/core/modules/tracker/tracker.pages.inc
@@ -39,7 +39,6 @@ function tracker_page($account = NULL, $set_title = FALSE) {
   // while keeping the correct order.
   $nodes = $query
     ->addTag('node_access')
-    ->addMetaData('base_table', 'tracker_node')
     ->fields('t', array('nid', 'changed'))
     ->condition('t.published', 1)
     ->orderBy('t.changed', 'DESC')
diff --git a/core/modules/user/lib/Drupal/user/Tests/UserTokenReplaceTest.php b/core/modules/user/lib/Drupal/user/Tests/UserTokenReplaceTest.php
index 5cd3cd3..f257118 100644
--- a/core/modules/user/lib/Drupal/user/Tests/UserTokenReplaceTest.php
+++ b/core/modules/user/lib/Drupal/user/Tests/UserTokenReplaceTest.php
@@ -25,7 +25,7 @@ class UserTokenReplaceTest extends WebTestBase {
    * Creates a user, then tests the tokens generated from it.
    */
   function testUserTokenReplacement() {
-    $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+    $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
     $url_options = array(
       'absolute' => TRUE,
       'language' => $language_interface,
diff --git a/core/modules/user/user.module b/core/modules/user/user.module
index 2250110..ddc1147 100644
--- a/core/modules/user/user.module
+++ b/core/modules/user/user.module
@@ -709,7 +709,7 @@ function user_user_view($account) {
  */
 function user_account_form(&$form, &$form_state) {
   global $user;
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   $account = $form['#user'];
   $register = ($form['#user']->uid > 0 ? FALSE : TRUE);
@@ -2368,7 +2368,7 @@ function user_view_page($account) {
  */
 function user_view($account, $view_mode = 'full', $langcode = NULL) {
   if (!isset($langcode)) {
-    $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode;
+    $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode;
   }
 
   // Retrieve all profile fields and attach to $account->content.
@@ -2404,7 +2404,7 @@ function user_view($account, $view_mode = 'full', $langcode = NULL) {
  */
 function user_build_content($account, $view_mode = 'full', $langcode = NULL) {
   if (!isset($langcode)) {
-    $langcode = drupal_container()->get(LANGUAGE_TYPE_CONTENT)->langcode;
+    $langcode = language_manager(LANGUAGE_TYPE_CONTENT)->langcode;
   }
 
   // Remove previously built content, if exists.
diff --git a/core/modules/user/user.pages.inc b/core/modules/user/user.pages.inc
index b568f66..783e3ff 100644
--- a/core/modules/user/user.pages.inc
+++ b/core/modules/user/user.pages.inc
@@ -77,7 +77,7 @@ function user_pass_validate($form, &$form_state) {
 }
 
 function user_pass_submit($form, &$form_state) {
-  $language_interface = drupal_container()->get(LANGUAGE_TYPE_INTERFACE);
+  $language_interface = language_manager(LANGUAGE_TYPE_INTERFACE);
 
   $account = $form_state['values']['account'];
   // Mail one time login URL and instructions using current language.
@@ -498,9 +498,9 @@ function user_page() {
   global $user;
   if ($user->uid) {
     // @todo: Cleaner sub request handling.
-    $subrequest = Request::create('/user/' . $user->uid, 'GET', request()->query->all(), request()->cookies->all(), array(), request()->server->all());
-    request($subrequest);
-    return drupal_container()->get('httpkernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST);
+    $request = drupal_container()->get('request');
+    $subrequest = Request::create('/user/' . $user->uid, 'GET', $request->query->all(), $request->cookies->all(), array(), $request->server->all());
+    return drupal_container()->get('http_kernel')->handle($subrequest, HttpKernelInterface::SUB_REQUEST);
   }
   else {
     return drupal_get_form('user_login');
diff --git a/core/update.php b/core/update.php
index 85c45c0..b685332 100644
--- a/core/update.php
+++ b/core/update.php
@@ -383,18 +383,10 @@ update_prepare_d8_bootstrap();
 // Determine if the current user has access to run update.php.
 drupal_bootstrap(DRUPAL_BOOTSTRAP_SESSION);
 
-
-// Ensure the default language is properly registered within the Dependency
-// Injection container during the upgrade process.
-$default = language_default();
-drupal_container()->register(LANGUAGE_TYPE_INTERFACE, 'Drupal\\Core\\Language\\Language')
-  ->addMethodCall('extend', array($default));
-
 // A request object from the HTTPFoundation to tell us about the request.
 // @todo These two lines were copied from index.php which has its own todo about
 // a change required here. Revisit this when that change has been made.
 $request = Request::createFromGlobals();
-request($request);
 
 // There can be conflicting 'op' parameters because both update and batch use
 // this parameter name. We need the 'op' coming from a POST request to trump
diff --git a/index.php b/index.php
index 7b99d10..15ce175 100644
--- a/index.php
+++ b/index.php
@@ -11,6 +11,7 @@
  * See COPYRIGHT.txt and LICENSE.txt files in the "core" directory.
  */
 
+use Drupal\Core\DrupalKernel;
 use Symfony\Component\HttpFoundation\Request;
 
 /**
@@ -24,11 +25,6 @@ drupal_bootstrap(DRUPAL_BOOTSTRAP_CONFIGURATION);
 // Create a request object from the HTTPFoundation.
 $request = Request::createFromGlobals();
 
-// Set the global $request object. This is a temporary measure to keep legacy
-// utility functions working. It should be moved to a dependency injection
-// container at some point.
-request($request);
-
 // Bootstrap all of Drupal's subsystems, but do not initialize anything that
 // depends on the fully resolved Drupal path, because path resolution happens
 // during the REQUEST event of the kernel.
@@ -36,6 +32,9 @@ request($request);
 // @see Drupal\Core\EventSubscriber\LegacyRequestSubscriber;
 drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
 
-$kernel = drupal_container()->get('httpkernel');
+$kernel = new DrupalKernel('prod', FALSE);
+$kernel->boot();
+
 $response = $kernel->handle($request)->prepare($request)->send();
+
 $kernel->terminate($request, $response);
