diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc
index 18c6695..7daf311 100644
--- a/core/includes/bootstrap.inc
+++ b/core/includes/bootstrap.inc
@@ -4,7 +4,9 @@ use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Database\Database;
 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;
 
@@ -1455,7 +1457,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'] = '';
@@ -1610,29 +1612,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
@@ -2428,28 +2407,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.
@@ -2458,7 +2432,31 @@ function drupal_container(ContainerBuilder $reset = NULL) {
     $container = $reset;
   }
   elseif (!isset($container)) {
+    // Return a ContainerBuilder instance with the bare essentials needed for any
+    // full bootstrap regardless of whether there will be a DrupalKernel involved.
+    // This will get merged with the full Kernel-built Container on normal page
+    // requests.
     $container = new ContainerBuilder();
+    // Register configuration storage dispatcher.
+    $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%');
+
+    // Register configuration object factory.
+    $container->register('config.factory', 'Drupal\Core\Config\ConfigFactory')
+      ->addArgument(new Reference('config.storage.dispatcher'));
   }
   return $container;
 }
@@ -2606,34 +2604,71 @@ 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
+ *
+ * @param $type
+ *   The type of language object needed, e.g. LANGUAGE_TYPE_INTERFACE. Passing
+ *   NULL invokes a reset of the statically stored language type objects.
+ */
+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 e4e00d6..8a07482 100644
--- a/core/includes/common.inc
+++ b/core/includes/common.inc
@@ -1599,7 +1599,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";
@@ -1901,7 +1901,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) {
@@ -2077,7 +2077,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
@@ -2322,7 +2322,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';
   }
 
@@ -4913,9 +4913,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 0c9cd5d..7498ea5 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/install.core.inc b/core/includes/install.core.inc
index b6614a7..0481570 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,12 @@ 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();
+  // @todo The constructor parameters for the Kernel class are for environment,
+  // e.g. 'prod', 'dev', and a boolean indicating whether it is in debug mode.
+  // Drupal does not currently make use of either of these, though that may
+  // change with http://drupal.org/node/1537198.
+  $kernel = new DrupalKernel('prod', FALSE);
+  $kernel->boot();
   drupal_bootstrap(DRUPAL_BOOTSTRAP_FULL);
 }
 
diff --git a/core/includes/language.inc b/core/includes/language.inc
index 0892cc4..a243d2e 100644
--- a/core/includes/language.inc
+++ b/core/includes/language.inc
@@ -107,10 +107,13 @@ const LANGUAGE_NEGOTIATION_DEFAULT = 'language-default';
  * @param $type
  *   The language type key to find the language for.
  *
+ * @param $request
+ *   The HttpReqeust object representing the current request.
+ *
  * @return
  *   The negotiated language object.
  */
-function language_types_initialize($type) {
+function language_types_initialize($type, $request = NULL) {
   // 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,7 +123,7 @@ function language_types_initialize($type) {
     if (isset($method['types']) && !in_array($type, $method['types'])) {
       continue;
     }
-    $language = language_negotiation_method_invoke($method_id, $method);
+    $language = language_negotiation_method_invoke($method_id, $method, $request);
     if ($language) {
       // Remember the method ID used to detect the language.
       $language->method_id = $method_id;
@@ -428,10 +431,13 @@ function language_negotiation_info() {
  *   invoked (see hook_language_negotiation_info() for details). If not passed
  *   in, it will be loaded through language_negotiation_info().
  *
+ * @param $request
+ *   (optional) The HttpRequest object representing the current request.
+ *
  * @return
  *   A language object representing the language chosen by the method.
  */
-function language_negotiation_method_invoke($method_id, $method = NULL) {
+function language_negotiation_method_invoke($method_id, $method = NULL, $request = NULL) {
   $results = &drupal_static(__FUNCTION__);
 
   if (!isset($results[$method_id])) {
@@ -447,12 +453,11 @@ function language_negotiation_method_invoke($method_id, $method = NULL) {
     if (isset($method['file'])) {
       require_once DRUPAL_ROOT . '/' . $method['file'];
     }
-
     // If the language negotiation method has no cache preference or this is
     // 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;
+    $langcode = $cache && function_exists($callback) ? $callback($languages, $request) : FALSE;
     $results[$method_id] = isset($languages[$langcode]) ? $languages[$langcode] : FALSE;
   }
 
diff --git a/core/includes/menu.inc b/core/includes/menu.inc
index 3c42f59..0b62f51 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..6f28125 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();
@@ -213,8 +213,17 @@ function drupal_cache_system_paths() {
   // request to avoid writing to cache on every request.
   $cache = &drupal_static('drupal_lookup_path', array());
   if (empty($cache['system_paths']) && !empty($cache['map'])) {
+
+    // @todo Because we are not within the request scope at this time, we cannot
+    //   use current_path(), which would give us the system path to use as the
+    //   key. Instead we call _current_path(), which may give us the alias
+    //   instead. However, at lookup time the system path will be used as the
+    //   key, because it uses current_path(), and so it will be a cache miss.
+    //   There is a critical issue for fixing the path alias logic here:
+    //   http://drupal.org/node/1269742
+
     // Generate a cache ID (cid) specifically for this page.
-    $cid = current_path();
+    $cid = _current_path();
     // The static $map array used by drupal_lookup_path() includes all
     // system paths for the page request.
     if ($paths = current($cache['map'])) {
@@ -358,6 +367,14 @@ function drupal_match_path($path, $patterns) {
  * @see request_path()
  */
 function current_path() {
+  // @todo Remove the check for whether the request service exists and the
+  // fallback code below, once the path alias logic has been figured out in
+  // http://drupal.org/node/1269742.
+  if (drupal_container()->has('request')) {
+    return drupal_container()->get('request')->attributes->get('system_path');
+  }
+  // If we are outside the request scope, fall back to using the path stored in
+  // _current_path().
   return _current_path();
 }
 
diff --git a/core/includes/theme.inc b/core/includes/theme.inc
index d75fbd7..cf976bf 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'];
@@ -2395,7 +2395,7 @@ function _template_preprocess_default_variables() {
  * @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.).
@@ -2527,7 +2527,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.
@@ -2708,7 +2708,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 5aff2bc..0902036 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/Core/CoreBundle.php b/core/lib/Drupal/Core/CoreBundle.php
new file mode 100644
index 0000000..b0830a0
--- /dev/null
+++ b/core/lib/Drupal/Core/CoreBundle.php
@@ -0,0 +1,106 @@
+<?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) {
+
+    // The 'request' scope and service enable services to depend on the Request
+    // object and get reconstructed when the request object changes (e.g.,
+    // during a subrequest).
+    $container->addScope(new Scope('request'));
+    $container->register('request', 'Symfony\Component\HttpFoundation\Request')
+      ->setSynthetic(TRUE);
+
+    $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('language_manager', 'Drupal\Core\Language\LanguageManager')
+      ->addArgument(new Reference('request'))
+      ->setScope('request');
+
+    // @todo Replace below lines with the commented out block below it when it's
+    //   performant to do so: http://drupal.org/node/1706064.
+    $dispatcher = $container->get('dispatcher');
+    $matcher = new \Drupal\Core\LegacyUrlMatcher();
+    $content_negotation = new \Drupal\Core\ContentNegotiation();
+    $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\RouterListener($matcher));
+    $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\ViewSubscriber($content_negotation));
+    $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\AccessSubscriber());
+    $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\MaintenanceModeSubscriber());
+    $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\PathSubscriber());
+    $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\LegacyRequestSubscriber());
+    $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\LegacyControllerSubscriber());
+    $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\FinishResponseSubscriber());
+    $dispatcher->addSubscriber(new \Drupal\Core\EventSubscriber\RequestCloseSubscriber());
+    $container->set('content_negotiation', $content_negotation);
+    $dispatcher->addSubscriber(\Drupal\Core\ExceptionController::getExceptionListener($container));
+    /*
+    $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')
+      ->addArgument(new Reference('language_manager'))
+      ->setScope('request')
+      ->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');
+
+    // Add a compiler pass for registering event subscribers.
+    $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING);
+    */
+  }
+}
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..19388fa
--- /dev/null
+++ b/core/lib/Drupal/Core/DependencyInjection/Compiler/RegisterKernelListenersPass.php
@@ -0,0 +1,36 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\DependencyInjection\Compiler\RegisterKernelListenersPass.
+ */
+
+namespace Drupal\Core\DependencyInjection\Compiler;
+
+use InvalidArgumentException;
+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..0bc4d67 100644
--- a/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php
+++ b/core/lib/Drupal/Core/DependencyInjection/ContainerBuilder.php
@@ -7,113 +7,39 @@
 
 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\Container;
 
 /**
- * Drupal's dependency injection container.
+ * Drupal's dependency injection container builder.
+ *
+ * @todo Submit upstream patches to Symfony to not require these overrides.
  */
 class ContainerBuilder extends BaseContainerBuilder {
 
   /**
-   * Registers the base Drupal services for the dependency injection container.
+   * Overrides Symfony\Component\DependencyInjection\ContainerBuilder::addObjectResource().
+   *
+   * Drupal does not use Symfony's Config component, so we override
+   * addObjectResource() with an empty implementation to prevent errors during
+   * container compilation.
    */
-  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'));
+  public function addObjectResource($object) {
   }
 
   /**
-   * Creates an EventDispatcher for the HttpKernel. Factory method.
+   * Overrides Symfony\Component\DependencyInjection\ContainerBuilder::set().
    *
-   * @param Drupal\Core\DependencyInjection\ContainerBuilder $container
-   *   The dependency injection container that contains the HTTP kernel.
+   * Drupal's container builder can be used at runtime after compilation, so we
+   * override Symfony's ContainerBuilder's restriction on setting services in a
+   * frozen builder.
    *
-   * @return Symfony\Component\EventDispatcher\EventDispatcher
-   *   An EventDispatcher with the default listeners attached to it.
+   * @todo Restrict this to synthetic services only. Ideally, the upstream
+   *   ContainerBuilder class should be fixed to allow setting synthetic
+   *   services in a frozen builder.
    */
-  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')));
-
-    return $dispatcher;
+  public function set($id, $service, $scope = self::SCOPE_CONTAINER) {
+    Container::set($id, $service, $scope);
   }
+
 }
diff --git a/core/lib/Drupal/Core/DrupalKernel.php b/core/lib/Drupal/Core/DrupalKernel.php
new file mode 100644
index 0000000..869b504
--- /dev/null
+++ b/core/lib/Drupal/Core/DrupalKernel.php
@@ -0,0 +1,105 @@
+<?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.
+ *
+ * This class is responsible for building the Dependency Injection Container and
+ * also deals with the registration of bundles. It allows registered bundles to
+ * add their services to the container. Core provides the CoreBundle, which adds
+ * the services required for all core subsystems. Each module can then add its
+ * own bundle, i.e. a subclass of Symfony\Component\HttpKernel\Bundle, to
+ * register services to the container.
+ */
+class DrupalKernel extends Kernel {
+
+  /**
+   * Returns an array of available bundles.
+   */
+  public function registerBundles() {
+    $bundles = array(
+      new CoreBundle(),
+    );
+
+    // @todo Remove the necessity of calling system_list() to find out which
+    // bundles exist. See http://drupal.org/node/1331486
+    $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();
+
+    // Merge in the minimal bootstrap container.
+    if ($bootstrap_container = drupal_container()) {
+      $container->merge($bootstrap_container);
+    }
+    foreach ($this->bundles as $bundle) {
+      $bundle->build($container);
+    }
+
+    // @todo Compile the container: http://drupal.org/node/1706064.
+    //$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..d989e69 100644
--- a/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
+++ b/core/lib/Drupal/Core/EventSubscriber/FinishResponseSubscriber.php
@@ -30,7 +30,10 @@ 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);
+    // @todo Receive the LanguageManager object as a constructor argument when
+    //   the dependency injection container allows for it performantly:
+    //   http://drupal.org/node/1706064.
+    $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..1627021 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..c1f7c5b
--- /dev/null
+++ b/core/lib/Drupal/Core/HttpKernel.php
@@ -0,0 +1,242 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\HttpKernel.
+ *
+ * @todo This file is copied verbatim, with the exception of the namespace
+ * change and this commment block, from Symfony full stack's FrameworkBundle.
+ * Once the FrameworkBundle is available as a Composer package we should switch
+ * to pulling it via Composer.
+ */
+
+namespace Drupal\Core;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\HttpKernel\HttpKernel as BaseHttpKernel;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+
+/**
+ * This HttpKernel is used to manage scope changes of the DI container.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+class HttpKernel extends BaseHttpKernel
+{
+    protected $container;
+
+    private $esiSupport;
+
+    public function __construct(EventDispatcherInterface $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;
+    }
+
+    /**
+     * Forwards the request to another controller.
+     *
+     * @param string $controller The controller name (a string like BlogBundle:Post:index)
+     * @param array  $attributes An array of request attributes
+     * @param array  $query      An array of request query parameters
+     *
+     * @return Response A Response instance
+     */
+    public function forward($controller, array $attributes = array(), array $query = array())
+    {
+        $attributes['_controller'] = $controller;
+        $subRequest = $this->container->get('request')->duplicate($query, null, $attributes);
+
+        return $this->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
+    }
+
+    /**
+     * Renders a Controller and returns the Response content.
+     *
+     * Note that this method generates an esi:include tag only when both the standalone
+     * option is set to true and the request has ESI capability (@see Symfony\Component\HttpKernel\HttpCache\ESI).
+     *
+     * Available options:
+     *
+     *  * attributes: An array of request attributes (only when the first argument is a controller)
+     *  * query: An array of request query parameters (only when the first argument is a controller)
+     *  * ignore_errors: true to return an empty string in case of an error
+     *  * alt: an alternative controller to execute in case of an error (can be a controller, a URI, or an array with the controller, the attributes, and the query arguments)
+     *  * standalone: whether to generate an esi:include tag or not when ESI is supported
+     *  * comment: a comment to add when returning an esi:include tag
+     *
+     * @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI
+     * @param array  $options    An array of options
+     *
+     * @return string The Response content
+     */
+    public function render($controller, array $options = array())
+    {
+        $options = array_merge(array(
+            'attributes'    => array(),
+            'query'         => array(),
+            'ignore_errors' => !$this->container->getParameter('kernel.debug'),
+            'alt'           => array(),
+            'standalone'    => false,
+            'comment'       => '',
+        ), $options);
+
+        if (!is_array($options['alt'])) {
+            $options['alt'] = array($options['alt']);
+        }
+
+        if (null === $this->esiSupport) {
+            $this->esiSupport = $this->container->has('esi') && $this->container->get('esi')->hasSurrogateEsiCapability($this->container->get('request'));
+        }
+
+        if ($this->esiSupport && (true === $options['standalone'] || 'esi' === $options['standalone'])) {
+            $uri = $this->generateInternalUri($controller, $options['attributes'], $options['query']);
+
+            $alt = '';
+            if ($options['alt']) {
+                $alt = $this->generateInternalUri($options['alt'][0], isset($options['alt'][1]) ? $options['alt'][1] : array(), isset($options['alt'][2]) ? $options['alt'][2] : array());
+            }
+
+            return $this->container->get('esi')->renderIncludeTag($uri, $alt, $options['ignore_errors'], $options['comment']);
+        }
+
+        if ('js' === $options['standalone']) {
+            $uri = $this->generateInternalUri($controller, $options['attributes'], $options['query'], false);
+            $defaultContent = null;
+
+            if ($template = $this->container->getParameter('templating.hinclude.default_template')) {
+                $defaultContent = $this->container->get('templating')->render($template);
+            }
+
+            return $this->renderHIncludeTag($uri, $defaultContent);
+        }
+
+        $request = $this->container->get('request');
+
+        // controller or URI?
+        if (0 === strpos($controller, '/')) {
+            $subRequest = Request::create($request->getUriForPath($controller), 'get', array(), $request->cookies->all(), array(), $request->server->all());
+            if ($session = $request->getSession()) {
+                $subRequest->setSession($session);
+            }
+        } else {
+            $options['attributes']['_controller'] = $controller;
+
+            if (!isset($options['attributes']['_format'])) {
+                $options['attributes']['_format'] = $request->getRequestFormat();
+            }
+
+            $options['attributes']['_route'] = '_internal';
+            $subRequest = $request->duplicate($options['query'], null, $options['attributes']);
+            $subRequest->setMethod('GET');
+        }
+
+        $level = ob_get_level();
+        try {
+            $response = $this->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
+
+            if (!$response->isSuccessful()) {
+                throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $request->getUri(), $response->getStatusCode()));
+            }
+
+            if (!$response instanceof StreamedResponse) {
+                return $response->getContent();
+            }
+
+            $response->sendContent();
+        } catch (\Exception $e) {
+            if ($options['alt']) {
+                $alt = $options['alt'];
+                unset($options['alt']);
+                $options['attributes'] = isset($alt[1]) ? $alt[1] : array();
+                $options['query'] = isset($alt[2]) ? $alt[2] : array();
+
+                return $this->render($alt[0], $options);
+            }
+
+            if (!$options['ignore_errors']) {
+                throw $e;
+            }
+
+            // let's clean up the output buffers that were created by the sub-request
+            while (ob_get_level() > $level) {
+                ob_get_clean();
+            }
+        }
+    }
+
+    /**
+     * Generates an internal URI for a given controller.
+     *
+     * This method uses the "_internal" route, which should be available.
+     *
+     * @param string  $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI
+     * @param array   $attributes An array of request attributes
+     * @param array   $query      An array of request query parameters
+     * @param boolean $secure
+     *
+     * @return string An internal URI
+     */
+    public function generateInternalUri($controller, array $attributes = array(), array $query = array(), $secure = true)
+    {
+        if (0 === strpos($controller, '/')) {
+            return $controller;
+        }
+
+        $path = http_build_query($attributes, '', '&');
+        $uri = $this->container->get('router')->generate($secure ? '_internal' : '_internal_public', array(
+            'controller' => $controller,
+            'path'       => $path ?: 'none',
+            '_format'    => $this->container->get('request')->getRequestFormat(),
+        ));
+
+        if ($queryString = http_build_query($query, '', '&')) {
+            $uri .= '?'.$queryString;
+        }
+
+        return $uri;
+    }
+
+    /**
+     * Renders an HInclude tag.
+     *
+     * @param string $uri A URI
+     * @param string $defaultContent Default content
+     */
+    public function renderHIncludeTag($uri, $defaultContent = null)
+    {
+        return sprintf('<hx:include src="%s">%s</hx:include>', $uri, $defaultContent);
+    }
+
+    public function hasEsiSupport()
+    {
+        return $this->esiSupport;
+    }
+}
diff --git a/core/lib/Drupal/Core/Language/LanguageManager.php b/core/lib/Drupal/Core/Language/LanguageManager.php
new file mode 100644
index 0000000..7514b74
--- /dev/null
+++ b/core/lib/Drupal/Core/Language/LanguageManager.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\Core\Language\LanguageManager.
+ */
+
+namespace Drupal\Core\Language;
+
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * Class responsible for initializing each language type.
+ *
+ * This service is dependent on the 'request' service and can therefore pass the
+ * Request object to the code that deals with each particular language type.
+ * This means the Request can be used directly for things like 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, $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/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 db80556..6aa30d1 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 c3cf904..949f81c 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 dfa156d..14cdba5 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();
 }
@@ -958,7 +958,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 +1024,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 +1682,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 0866821..8962298 100644
--- a/core/modules/contact/contact.pages.inc
+++ b/core/modules/contact/contact.pages.inc
@@ -150,7 +150,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;
@@ -292,7 +292,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/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 f884778..da0365f 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..4e6cda8 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;
 }
 
 /**
@@ -197,10 +197,13 @@ function language_from_session($languages) {
  * @param $languages
  *   An array of valid language objects.
  *
+ * @param $request
+ *   The HttpRequest object representing the current request.
+ *
  * @return
  *   A valid language code on success, FALSE otherwise.
  */
-function language_from_url($languages) {
+function language_from_url($languages, $request) {
   $language_url = FALSE;
 
   if (!language_negotiation_method_enabled(LANGUAGE_NEGOTIATION_URL)) {
@@ -209,11 +212,17 @@ function language_from_url($languages) {
 
   switch (variable_get('language_negotiation_url_part', LANGUAGE_NEGOTIATION_URL_PREFIX)) {
     case LANGUAGE_NEGOTIATION_URL_PREFIX:
-      // 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);
+
+      $current_path = $request->attributes->get('system_path');
+      if (!isset($current_path)) {
+        $current_path = trim($request->getPathInfo(), '/');
+      }
+
+      list($language, $path) = language_url_split_prefix($current_path, $languages);
+      // Store the correct system path, i.e. minus the path prefix, in the
+      // request.
+      $request->attributes->set('system_path', $path);
+
       if ($language !== FALSE) {
         $language_url = $language->langcode;
       }
@@ -271,6 +280,10 @@ function language_from_url($languages) {
  *   (optional) An array of valid language objects. This is passed by
  *   language_negotiation_method_invoke() to every language method callback,
  *   but it is not actually needed here. Defaults to NULL.
+ *
+ * @param $request
+ *   (optional) The HttpRequest object representing the current request.
+ *
  * @param $language_type
  *   (optional) The language type to fall back to. Defaults to the interface
  *   language.
@@ -278,7 +291,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, $request = NULL, $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 +304,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 +335,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 +378,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/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.module b/core/modules/locale/locale.module
index cef0b57..ad5ad91 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/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 3d83cd4..5c0af5e 100644
--- a/core/modules/node/node.module
+++ b/core/modules/node/node.module
@@ -672,7 +672,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;
@@ -762,7 +762,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__);
@@ -1205,7 +1205,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.
@@ -1266,7 +1266,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.
@@ -2469,7 +2469,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);
+  $language_content = language_manager(LANGUAGE_TYPE_CONTENT);
   $rss_config = config('system.rss');
 
   if ($nids === FALSE) {
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 3a205f3..acfcc2c 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/path/lib/Drupal/path/Tests/PathAliasTest.php b/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php
index e0d7e7c..5444d2b 100644
--- a/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php
+++ b/core/modules/path/lib/Drupal/path/Tests/PathAliasTest.php
@@ -49,7 +49,9 @@ class PathAliasTest extends PathTestBase {
     // Visit the alias for the node and confirm a cache entry is created.
     cache('path')->flush();
     $this->drupalGet($edit['alias']);
-    $this->assertTrue(cache('path')->get($edit['source']), t('Cache entry was created.'));
+    // @todo The alias should actually have been cached with the system path as
+    // the key, see the todo in drupal_cache_system_paths() in path.inc.
+    $this->assertTrue(cache('path')->get($edit['alias']), t('Cache entry was created.'));
   }
 
   /**
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 2c93b67..9e24c2a 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 7f227c7..cccd011 100644
--- a/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
+++ b/core/modules/simpletest/lib/Drupal/simpletest/TestBase.php
@@ -680,7 +680,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;
@@ -748,7 +748,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 cc0916f..ae2626f 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/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 a78c4ce..a4e2917 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.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.module b/core/modules/system/system.module
index a530c30..1abfe95 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2068,7 +2068,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
@@ -2199,7 +2199,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..297e3c7 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,9 @@ 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);
 $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..369116d 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,9 @@ 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);
 $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..768a1b0
--- /dev/null
+++ b/core/modules/system/tests/modules/bundle_test/lib/Drupal/bundle_test/BundleTestBundle.php
@@ -0,0 +1,28 @@
+<?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');
+
+    // @todo Remove when the 'kernel.event_subscriber' tag above is made to
+    //   work: http://drupal.org/node/1706064.
+    $container->get('dispatcher')->addSubscriber($container->get('bundle_test_class'));
+  }
+}
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 8aa78df..88066b0 100644
--- a/core/modules/taxonomy/taxonomy.module
+++ b/core/modules/taxonomy/taxonomy.module
@@ -585,7 +585,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/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 e373062..afa9ab4 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);
@@ -2373,7 +2373,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.
@@ -2409,7 +2409,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..38177ab 100644
--- a/index.php
+++ b/index.php
@@ -11,31 +11,27 @@
  * See COPYRIGHT.txt and LICENSE.txt files in the "core" directory.
  */
 
+use Drupal\Core\DrupalKernel;
 use Symfony\Component\HttpFoundation\Request;
 
 /**
  * Root directory of Drupal installation.
  */
 define('DRUPAL_ROOT', getcwd());
-// Bootstrap the lowest level of what we need.
-require_once DRUPAL_ROOT . '/core/includes/bootstrap.inc';
-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.
 // @see Drupal\Core\EventSubscriber\PathSubscriber;
 // @see Drupal\Core\EventSubscriber\LegacyRequestSubscriber;
+require_once DRUPAL_ROOT . '/core/includes/bootstrap.inc';
 drupal_bootstrap(DRUPAL_BOOTSTRAP_CODE);
 
-$kernel = drupal_container()->get('httpkernel');
+// @todo Figure out how best to handle the Kernel constructor parameters.
+$kernel = new DrupalKernel('prod', FALSE);
+
+// Create a request object from the HTTPFoundation.
+$request = Request::createFromGlobals();
 $response = $kernel->handle($request)->prepare($request)->send();
+
 $kernel->terminate($request, $response);
