diff --git a/includes/language.inc b/includes/language.inc
index eb13eac..ab58382 100644
--- a/includes/language.inc
+++ b/includes/language.inc
@@ -84,6 +84,40 @@ function language_types_disable($types) {
 }
 
 /**
+ * Update the language type configuration.
+ *
+ * @param $defined_providers
+ *   (Optional) A list of defined language providers. Defaults to the
+ *   system-defined ones.
+ */
+function language_types_set($defined_providers = NULL) {
+  if (empty($defined_providers)) {
+    $defined_providers = language_negotiation_info();
+  }
+
+  foreach (language_types_info() as $type => $info) {
+    if (isset($info['fixed'])) {
+      $language_types[$type] = FALSE;
+      $negotiation = array();
+      foreach ($info['fixed'] as $weight => $id) {
+        if (isset($defined_providers[$id])) {
+          $negotiation[$id] = $defined_providers[$id];
+          $negotiation[$id]['weight'] = $weight;
+        }
+      }
+      language_negotiation_set($type, $negotiation);
+    }
+    else {
+      $language_types[$type] = TRUE;
+    }
+  }
+
+  // Save language types.
+  variable_set('language_types', $language_types);
+  drupal_static_reset('language_types');
+}
+
+/**
  * Check if a language provider is enabled.
  *
  * This has two possible behaviors:
@@ -173,6 +207,28 @@ function language_negotiation_get_switch_links($type, $path) {
   return $links;
 }
 
+/**
+ * Ensure that the enabled language providers are actually defined.
+ *
+ * @param $defined_providers
+ *   (Optional) A list of defined language providers. Defaults to the
+ *   system-defined ones.
+ */
+function language_negotiation_purge($defined_providers = NULL) {
+  if (empty($defined_providers)) {
+    $defined_providers = language_negotiation_info();
+  }
+
+  foreach (language_types_info() as $type => $type_info) {
+    $negotiation = variable_get("language_negotiation_$type", array());
+    foreach ($negotiation as $id => $provider) {
+      if (!isset($defined_providers[$id])) {
+        unset($defined_providers[$id]);
+      }
+    }
+    language_negotiation_set($type, $negotiation);
+  }
+}
 
 /**
  * Save a list of language providers.
diff --git a/modules/locale/locale.admin.inc b/modules/locale/locale.admin.inc
index de16133..7656753 100644
--- a/modules/locale/locale.admin.inc
+++ b/modules/locale/locale.admin.inc
@@ -658,7 +658,6 @@ function theme_locale_languages_configure_form($variables) {
  * Submit handler for language negotiation settings.
  */
 function locale_languages_configure_form_submit($form, &$form_state) {
-  $language_types = array();
   $configurable_types = $form['#language_types'];
 
   foreach ($configurable_types as $type) {
@@ -666,7 +665,6 @@ function locale_languages_configure_form_submit($form, &$form_state) {
     $enabled_providers = $form_state['values'][$type]['enabled'];
     $enabled_providers[LANGUAGE_NEGOTIATION_DEFAULT] = TRUE;
     $providers_weight = $form_state['values'][$type]['weight'];
-    $language_types[$type] = TRUE;
 
     foreach ($providers_weight as $id => $weight) {
       if ($enabled_providers[$id]) {
@@ -680,27 +678,11 @@ function locale_languages_configure_form_submit($form, &$form_state) {
     variable_set("locale_language_providers_weight_$type", $providers_weight);
   }
 
-  // Save non-configurable language types negotiation.
-  $language_types_info = language_types_info();
-  $defined_providers = $form['#language_providers'];
-  foreach ($language_types_info as $type => $info) {
-    if (isset($info['fixed'])) {
-      $language_types[$type] = FALSE;
-      $negotiation = array();
-      foreach ($info['fixed'] as $weight => $id) {
-        if (isset($defined_providers[$id])) {
-          $negotiation[$id] = $defined_providers[$id];
-          $negotiation[$id]['weight'] = $weight;
-        }
-      }
-      language_negotiation_set($type, $negotiation);
-    }
-  }
+  // Save non-configurable language types and the related language negotiation
+  // configuration.
+  language_types_set($form['#language_providers']);
 
-  // Save language types.
-  variable_set('language_types', $language_types);
-
-  $form_state['redirect'] = 'admin/config/regional/language';
+  $form_state['redirect'] = 'admin/config/regional/language/configure';
   drupal_set_message(t('Language negotiation configuration saved.'));
 }
 
diff --git a/modules/locale/locale.module b/modules/locale/locale.module
index c1cdd43..62ed06a 100644
--- a/modules/locale/locale.module
+++ b/modules/locale/locale.module
@@ -593,6 +593,22 @@ function locale_language_negotiation_info() {
   return $providers;
 }
 
+/**
+ * Implementation of hook_modules_enabled().
+ */
+function locale_modules_enabled($modules) {
+  include_once DRUPAL_ROOT . '/includes/language.inc';
+  language_types_set();
+  language_negotiation_purge();
+}
+
+/**
+ * Implementation of hook_modules_disabled().
+ */
+function locale_modules_disabled($modules) {
+  locale_modules_enabled($modules);
+}
+
 // ---------------------------------------------------------------------------------
 // Locale core functionality
 
@@ -928,7 +944,7 @@ function locale_block_info() {
   include_once DRUPAL_ROOT . '/includes/language.inc';
   $block = array();
   $info = language_types_info();
-  foreach (language_types_configurable() as $type) {
+  foreach (language_types_configurable(FALSE) as $type) {
     $block[$type] = array(
       'info' => t('Language switcher (@type)', array('@type' => $info[$type]['name'])),
       // Not worth caching.
diff --git a/modules/locale/locale.test b/modules/locale/locale.test
diff --git a/modules/locale/tests/locale_test.info b/modules/locale/tests/locale_test.info
diff --git a/modules/locale/tests/locale_test.module b/modules/locale/tests/locale_test.module
