diff --git a/core/includes/language.inc b/core/includes/language.inc
index 685a4d4..262ec19 100644
--- a/core/includes/language.inc
+++ b/core/includes/language.inc
@@ -350,7 +350,10 @@ function language_provider_invoke($provider_id, $provider = NULL) {
     $results[$provider_id] = isset($languages[$langcode]) ? $languages[$langcode] : FALSE;
   }
 
-  return $results[$provider_id];
+  // Since objects are resources we need to return a clone to prevent the
+  // provider cache to be unintentionally altered. The same providers might be
+  // used with different language types based on configuration.
+  return !empty($results[$provider_id]) ? clone($results[$provider_id]) : $results[$provider_id];
 }
 
 /**
@@ -381,15 +384,18 @@ function language_initialize($type) {
   // first valid language found.
   $negotiation = variable_get("language_negotiation_$type", array());
 
-  foreach ($negotiation as $id => $provider) {
-    $language = language_provider_invoke($id, $provider);
+  foreach ($negotiation as $provider_id => $provider) {
+    $language = language_provider_invoke($provider_id, $provider);
     if ($language) {
+      $language->provider = $provider_id;
       return $language;
     }
   }
 
   // If no other language was found use the default one.
-  return language_default();
+  $language = language_default();
+  $language->provider = LANGUAGE_NEGOTIATION_DEFAULT;
+  return $language;
 }
 
 /**
diff --git a/core/modules/locale/locale.test b/core/modules/locale/locale.test
index d6cd76a..ff448e6 100644
--- a/core/modules/locale/locale.test
+++ b/core/modules/locale/locale.test
@@ -2148,6 +2148,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
         'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LANGUAGE_NEGOTIATION_DEFAULT),
         'path' => 'admin/config',
         'expect' => $default_string,
+        'expected_provider' => LANGUAGE_NEGOTIATION_DEFAULT,
         'http_header' => $http_header_browser_fallback,
         'message' => 'URL (PATH) > DEFAULT: no language prefix, UI language is default and the browser language preference setting is not used.',
       ),
@@ -2156,6 +2157,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
         'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LANGUAGE_NEGOTIATION_DEFAULT),
         'path' => "$langcode/admin/config",
         'expect' => $language_string,
+        'expected_provider' => LOCALE_LANGUAGE_NEGOTIATION_URL,
         'http_header' => $http_header_browser_fallback,
         'message' => 'URL (PATH) > DEFAULT: with language prefix, UI language is switched based on path prefix',
       ),
@@ -2164,6 +2166,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
         'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LOCALE_LANGUAGE_NEGOTIATION_BROWSER),
         'path' => 'admin/config',
         'expect' => $language_browser_fallback_string,
+        'expected_provider' => LOCALE_LANGUAGE_NEGOTIATION_BROWSER,
         'http_header' => $http_header_browser_fallback,
         'message' => 'URL (PATH) > BROWSER: no language prefix, UI language is determined by browser language preference',
       ),
@@ -2172,6 +2175,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
         'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LOCALE_LANGUAGE_NEGOTIATION_BROWSER),
         'path' => "$langcode/admin/config",
         'expect' => $language_string,
+        'expected_provider' => LOCALE_LANGUAGE_NEGOTIATION_URL,
         'http_header' => $http_header_browser_fallback,
         'message' => 'URL (PATH) > BROWSER: with langage prefix, UI language is based on path prefix',
       ),
@@ -2180,6 +2184,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
         'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LOCALE_LANGUAGE_NEGOTIATION_BROWSER, LANGUAGE_NEGOTIATION_DEFAULT),
         'path' => 'admin/config',
         'expect' => $default_string,
+        'expected_provider' => LANGUAGE_NEGOTIATION_DEFAULT,
         'http_header' => $http_header_blah,
         'message' => 'URL (PATH) > BROWSER > DEFAULT: no language prefix and browser language preference set to unknown language should use default language',
       ),
@@ -2207,6 +2212,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
         'locale_language_negotiation_url_part' => LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN,
         'path' => 'admin/config',
         'expect' => $default_string,
+        'expected_provider' => LANGUAGE_NEGOTIATION_DEFAULT,
         'http_header' => $http_header_browser_fallback,
         'message' => 'URL (DOMAIN) > DEFAULT: default domain should get default language',
       ),
@@ -2218,6 +2224,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
         'locale_test_domain' => $language_domain,
         'path' => 'admin/config',
         'expect' => $language_string,
+        'expected_provider' => LOCALE_LANGUAGE_NEGOTIATION_URL,
         'http_header' => $http_header_browser_fallback,
         'message' => 'URL (DOMAIN) > DEFAULT: domain example.cn should switch to Chinese',
       ),
@@ -2241,6 +2248,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase {
     }
     $this->drupalGet($test['path'], array(), $test['http_header']);
     $this->assertText($test['expect'], $test['message']);
+    $this->assertText(t('Language negotiation provider: @name', array('@name' => $test['expected_provider'])));
   }
 
   /**
diff --git a/core/modules/locale/tests/locale_test.module b/core/modules/locale/tests/locale_test.module
index b29d665..e7c6c4c 100644
--- a/core/modules/locale/tests/locale_test.module
+++ b/core/modules/locale/tests/locale_test.module
@@ -22,6 +22,9 @@ function locale_test_boot() {
  */
 function locale_test_init() {
   locale_test_store_language_negotiation();
+  if (isset($GLOBALS['language']) && isset($GLOBALS['language']->provider)) {
+    drupal_set_message(t('Language negotiation provider: @name', array('@name' => $GLOBALS['language']->provider)));
+  }
 }
 
 /**
