Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.340
diff -u -p -r1.340 bootstrap.inc
--- includes/bootstrap.inc	7 Jan 2010 04:54:18 -0000	1.340
+++ includes/bootstrap.inc	11 Jan 2010 03:00:45 -0000
@@ -202,6 +202,28 @@ define('LANGUAGE_TYPE_INTERFACE', 'langu
 define('LANGUAGE_TYPE_URL', 'language_url');
 
 /**
+ * No language negotiation. The default language is used.
+ */
+define('LANGUAGE_NEGOTIATION_NONE', 0);
+
+/**
+ * Path based negotiation with fallback to default language if no defined path
+ * prefix identified.
+ */
+define('LANGUAGE_NEGOTIATION_PATH_DEFAULT', 1);
+
+/**
+ * Path based negotiation with fallback if no defined path prefix identified.
+ */
+define('LANGUAGE_NEGOTIATION_PATH', 2);
+
+/**
+ * Domain based negotiation with fallback to default language if no language
+ * identified by domain.
+ */
+define('LANGUAGE_NEGOTIATION_DOMAIN', 3);
+
+/**
  * Language written left to right. Possible value of $language->direction.
  */
 define('LANGUAGE_LTR', 0);
Index: modules/locale/locale.admin.inc
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.admin.inc,v
retrieving revision 1.1
diff -u -p -r1.1 locale.admin.inc
--- modules/locale/locale.admin.inc	8 Jan 2010 13:32:43 -0000	1.1
+++ modules/locale/locale.admin.inc	12 Jan 2010 02:00:38 -0000
@@ -471,22 +471,28 @@ function locale_languages_delete_form_su
  */
 
 /**
- * Setting for language negotiation options
+ * Form builder for language negotiation options.
  */
-function locale_languages_configure_form() {
-  include_once DRUPAL_ROOT . '/includes/language.inc';
+function locale_languages_configure_form($form, &$form_state) {
 
-  $form = array(
-    '#submit' => array('locale_languages_configure_form_submit'),
-    '#theme' => 'locale_languages_configure_form',
-    '#language_types' => language_types_configurable(),
-    '#language_types_info' => language_types_info(),
-    '#language_providers' => language_negotiation_info(),
+  $form['language_negotiation'] = array(
+    '#title' => t('Language negotiation'),
+    '#type' => 'radios',
+    '#options' => array(
+      LANGUAGE_NEGOTIATION_NONE => t('None.'),
+      LANGUAGE_NEGOTIATION_PATH_DEFAULT => t('Path prefix only.'),
+      LANGUAGE_NEGOTIATION_PATH => t('Path prefix with language fallback.'),
+      LANGUAGE_NEGOTIATION_DOMAIN => t('Domain name only.')),
+    '#default_value' => variable_get('locale_language_negotiation', LANGUAGE_NEGOTIATION_NONE),
+    '#description' => t("Select the mechanism used to determine your site's presentation language. <strong>Modifying this setting may break all incoming URLs and should be used with caution in a production environment.</strong>")
   );
 
-  foreach ($form['#language_types'] as $type) {
-    _locale_languages_configure_form_language_table($form, $type);
-  }
+  $form['user_override'] = array(
+    '#title' => t('Use the user\'s language preferences for the interface language'),
+    '#type' => 'checkbox',
+    '#default_value' => variable_get('locale_language_negotiation_user_override', 0),
+    '#description' => '',
+  );
 
   $form['actions'] = array('#type' => 'container', '#attributes' => array('class' => array('form-actions')));
   $form['actions']['submit'] = array(
@@ -494,193 +500,101 @@ function locale_languages_configure_form
     '#value' => t('Save settings'),
   );
 
+  $form['#theme'] = 'system_settings_form';
+
   return $form;
 }
 
 /**
- * Helper function to build a language provider table.
+ * Validation handler for language negotiation settings.
  */
-function _locale_languages_configure_form_language_table(&$form, $type) {
-  $info = $form['#language_types_info'][$type];
-
-  $table_form = array(
-    '#title' => t('@type language', array('@type' => $info['name'])),
-    '#tree' => TRUE,
-    '#description' => $info['description'],
-    '#language_providers' => array(),
-    '#show_operations' => FALSE,
-    'weight' => array('#tree' => TRUE),
-    'enabled' => array('#tree' => TRUE),
-  );
-
-  $language_providers = $form['#language_providers'];
-  $enabled_providers = variable_get("locale_language_providers_enabled_$type", array());
-  $providers_weight = variable_get("locale_language_providers_weight_$type", array());
-
-  // Add missing data to the providers lists.
-  foreach ($language_providers as $id => $provider) {
-    if (!isset($providers_weight[$id])) {
-      $providers_weight[$id] = language_provider_weight($provider);
-    }
-    if (!isset($enabled_providers[$id])) {
-      $enabled_providers[$id] = FALSE;
-    }
-  }
-
-  // Order providers list by weight.
-  asort($providers_weight);
-
-  foreach ($providers_weight as $id => $weight) {
-    $enabled = $enabled_providers[$id];
-    $provider = $language_providers[$id];
-
-    // List the provider only if the current type is defined in its 'types' key.
-    // If it is not defined default to all the configurabe language types.
-    $types = array_flip(isset($provider['types']) ? $provider['types'] : $form['#language_types']);
-
-    if (isset($types[$type])) {
-      $table_form['#language_providers'][$id] = $provider;
-
-      $table_form['weight'][$id] = array(
-        '#type' => 'weight',
-        '#default_value' => $weight,
-        '#attributes' => array('class' => array("language-provider-weight-$type")),
-      );
-
-      $table_form['title'][$id] = array('#markup' => check_plain($provider['name']));
-
-      $table_form['enabled'][$id] = array('#type' => 'checkbox', '#default_value' => $enabled);
-      if ($id === LANGUAGE_NEGOTIATION_DEFAULT) {
-        $table_form['enabled'][$id]['#default_value'] = TRUE;
-        $table_form['enabled'][$id]['#attributes'] = array('disabled' => 'disabled');
-      }
-
-      $table_form['description'][$id] = array('#markup' => filter_xss_admin($provider['description']));
-
-      $config_op = array();
-      if (isset($provider['config'])) {
-        $config_op = array('#type' => 'link', '#title' => t('Configure'), '#href' => $provider['config']);
-        // If there is at least one operation enabled show the operation column.
-        $table_form['#show_operations'] = TRUE;
-      }
-      $table_form['operation'][$id] = $config_op;
-    }
+function locale_languages_configure_form_validate($form, &$form_state) {
+  if ($form_state['values']['user_override'] &&  $form_state['values']['language_negotiation'] == LANGUAGE_NEGOTIATION_NONE) {
+    form_set_error('user_override', t('User preference can not be used when language negotiation is set to none.'));
   }
-
-  $form[$type] = $table_form;
 }
 
 /**
- * Theme the language configure form.
- *
- * @ingroup themeable
+ * Submit handler for language negotiation settings.
  */
-function theme_locale_languages_configure_form($variables) {
-  $form = $variables['form'];
-  $output = '';
+function locale_languages_configure_form_submit($form, &$form_state) {
+  $negotiation = $form_state['values']['language_negotiation'];
+  $user_override = $form_state['values']['user_override'];
+  locale_language_negotiation_set($negotiation, $user_override);
+  drupal_set_message(t('Language negotiation configuration saved.'));
+}
 
-  foreach ($form['#language_types'] as $type) {
-    $rows = array();
-    $info = $form['#language_types_info'][$type];
-    $title = '<label>' . $form[$type]['#title'] . '</label>';
-    $description = '<div class="description">' . $form[$type]['#description'] . '</div>';
-
-    foreach ($form[$type]['title'] as $id => $element) {
-      // Do not take form control structures.
-      if (is_array($element) && element_child($id)) {
-        $row = array(
-          'data' => array(
-            '<strong>' . drupal_render($form[$type]['title'][$id]) . '</strong>',
-            drupal_render($form[$type]['description'][$id]),
-            drupal_render($form[$type]['enabled'][$id]),
-            drupal_render($form[$type]['weight'][$id]),
-          ),
-          'class' => array('draggable'),
-        );
-        if ($form[$type]['#show_operations']) {
-          $row['data'][] = drupal_render($form[$type]['operation'][$id]);
-        }
-        $rows[] = $row;
-      }
-    }
+/**
+ * Save the configuration corresponding to the given language negotiation mode.
+ *
+ * @param $mode
+ *   The language negotiation mode to be saved. Can be one of:
+ *   - LANGUAGE_NEGOTIATION_NONE
+ *   - LANGUAGE_NEGOTIATION_PATH_DEFAULT
+ *   - LANGUAGE_NEGOTIATION_PATH
+ *   - LANGUAGE_NEGOTIATION_DOMAIN
+ * @param $user_override
+ *   Optional. Specify if the user language preference should prevale over the
+ *   previously negotiated language.
+ */
+function locale_language_negotiation_set($mode, $user_override = FALSE) {
+  // Save the specified negotiation mode.
+  variable_set('locale_language_negotiation', $mode);
+  variable_set('locale_language_negotiation_user_override', $user_override);
 
-    $header = array(
-      array('data' => t('Detection method')),
-      array('data' => t('Description')),
-      array('data' => t('Enabled')),
-      array('data' => t('Weight')),
-    );
+  switch ($mode) {
+    case LANGUAGE_NEGOTIATION_NONE:
+      $negotiation = array();
+      break;
 
-    // If there is at least one operation enabled show the operation column.
-    if ($form[$type]['#show_operations']) {
-      $header[] = array('data' => t('Operations'));
-    }
+    case LANGUAGE_NEGOTIATION_PATH_DEFAULT:
+      variable_set('locale_language_negotiation_url_part', LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX);
+      $negotiation = array(
+        LOCALE_LANGUAGE_NEGOTIATION_URL
+      );
+      break;
 
-    $variables = array(
-      'header' => $header,
-      'rows' => $rows,
-      'attributes' => array('id' => "language-negotiation-providers-$type"),
-    );
-    $table  = theme('table', $variables);
-    $table .= drupal_render_children($form[$type]);
+    case LANGUAGE_NEGOTIATION_PATH:
+      variable_set('locale_language_negotiation_url_part', LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX);
+      $negotiation = array(
+        LOCALE_LANGUAGE_NEGOTIATION_URL,
+        LOCALE_LANGUAGE_NEGOTIATION_USER,
+        LOCALE_LANGUAGE_NEGOTIATION_BROWSER
+      );
+      break;
 
-    drupal_add_tabledrag("language-negotiation-providers-$type", 'order', 'sibling', "language-provider-weight-$type");
+    case LANGUAGE_NEGOTIATION_DOMAIN:
+      variable_set('locale_language_negotiation_url_part', LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN);
+      $negotiation = array(
+        LOCALE_LANGUAGE_NEGOTIATION_URL
+      );
+      break;
 
-    $output .= '<div class="form-item">' . $title . $description . $table . '</div>';
+    default:
+      // If no valid language negotiation mode was specified we have nothing
+      // more to save.
+      return;
   }
 
-  $output .= drupal_render_children($form);
-  return $output;
-}
-
-/**
- * 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) {
-    $negotiation = array();
-    $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]) {
-        $provider = $form[$type]['#language_providers'][$id];
-        $provider['weight'] = $weight;
-        $negotiation[$id] = $provider;
-      }
-    }
+  require_once DRUPAL_ROOT . '/includes/language.inc';
 
-    language_negotiation_set($type, $negotiation);
-    variable_set("locale_language_providers_enabled_$type", $enabled_providers);
-    variable_set("locale_language_providers_weight_$type", $providers_weight);
-  }
+  // Content language is determined by the given settings.
+  language_negotiation_set(LANGUAGE_TYPE_CONTENT, array_flip($negotiation));
 
-  // 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 $id) {
-        if (isset($defined_providers[$id])) {
-          $negotiation[$id] = $defined_providers[$id];
-        }
-      }
-      language_negotiation_set($type, $negotiation);
+  // Interface language is equal to content language unless overridden by user
+  // or session language providers. 
+  $negotiation = array();
+  if ($mode != LANGUAGE_NEGOTIATION_NONE) {
+    $negotiation[] = LOCALE_LANGUAGE_NEGOTIATION_SESSION;
+    // User language provider override must be explicitly set.
+    if ($user_override) {
+      $negotiation[] = LOCALE_LANGUAGE_NEGOTIATION_USER;
     }
   }
+  $negotiation[] = LOCALE_LANGUAGE_NEGOTIATION_CONTENT;
 
-  // Save language types.
-  variable_set('language_types', $language_types);
-
-  $form_state['redirect'] = 'admin/config/regional/language';
-  drupal_set_message(t('Language negotiation configuration saved.'));
+  language_negotiation_set(LANGUAGE_TYPE_INTERFACE, array_flip($negotiation));
+  language_negotiation_set(LANGUAGE_TYPE_URL, array(LOCALE_LANGUAGE_NEGOTIATION_URL => 0));
 }
 
 /**
Index: modules/locale/locale.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.install,v
retrieving revision 1.55
diff -u -p -r1.55 locale.install
--- modules/locale/locale.install	9 Jan 2010 22:07:56 -0000	1.55
+++ modules/locale/locale.install	12 Jan 2010 00:32:22 -0000
@@ -45,36 +45,11 @@ function locale_update_7000() {
  * Upgrade language negotiation settings.
  */
 function locale_update_7001() {
-  require_once DRUPAL_ROOT . '/includes/language.inc';
+  module_load_include('inc', 'locale', 'locale.admin');
 
-  switch (variable_get('language_negotiation', 0)) {
-    // LANGUAGE_NEGOTIATION_NONE.
-    case 0:
-      $negotiation = array();
-      break;
-
-    // LANGUAGE_NEGOTIATION_PATH_DEFAULT.
-    case 1:
-      $negotiation = array(LOCALE_LANGUAGE_NEGOTIATION_URL);
-      break;
-
-    // LANGUAGE_NEGOTIATION_PATH.
-    case 2:
-      $negotiation = array(LOCALE_LANGUAGE_NEGOTIATION_URL, LOCALE_LANGUAGE_NEGOTIATION_USER, LOCALE_LANGUAGE_NEGOTIATION_BROWSER);
-      break;
-
-    // LANGUAGE_NEGOTIATION_DOMAIN.
-    case 3:
-      variable_set('locale_language_negotiation_url_part', LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN);
-      $negotiation = array(LOCALE_LANGUAGE_NEGOTIATION_URL);
-      break;
-  }
-
-  // Save new language negotiation options: UI language is tied to content
-  // language as this was Drupal 6 behavior.
-  language_negotiation_set(LANGUAGE_TYPE_CONTENT, array_flip($negotiation));
-  language_negotiation_set(LANGUAGE_TYPE_INTERFACE, array(LOCALE_LANGUAGE_NEGOTIATION_CONTENT => 0));
-  language_negotiation_set(LANGUAGE_TYPE_URL, array(LOCALE_LANGUAGE_NEGOTIATION_URL => 0));
+  // Convert the current language negotiation options to the new format.
+  $negotiation = variable_get('language_negotiation', LANGUAGE_NEGOTIATION_NONE);
+  locale_language_negotiation_set($negotiation);
 
   // Unset the old language negotiation system variable.
   variable_del('language_negotiation');
@@ -107,6 +82,8 @@ function locale_uninstall() {
   variable_del('language_default');
   variable_del('language_count');
   variable_del('language_types');
+  variable_del('locale_language_negotiation');
+  variable_del('locale_language_negotiation_user_override');
   variable_del('locale_language_negotiation_url_part');
   variable_del('locale_language_negotiation_session_param');
   variable_del('language_content_type_default');
@@ -117,8 +94,6 @@ function locale_uninstall() {
 
   foreach (language_types() as $type) {
     variable_del("language_negotiation_$type");
-    variable_del("locale_language_providers_enabled_$type");
-    variable_del("locale_language_providers_weight_$type");
   }
 
   foreach (node_type_get_types() as $type => $content_type) {
@@ -129,7 +104,6 @@ function locale_uninstall() {
   // successive calls of t() might result in calling locale(), which in turn might
   // try to query the unexisting {locales_source} and {locales_target} tables.
   drupal_language_initialize();
-
 }
 
 /**
Index: modules/locale/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.module,v
retrieving revision 1.281
diff -u -p -r1.281 locale.module
--- modules/locale/locale.module	10 Jan 2010 19:06:47 -0000	1.281
+++ modules/locale/locale.module	12 Jan 2010 01:27:20 -0000
@@ -69,13 +69,17 @@ function locale_help($path, $arg) {
     case 'admin/config/regional/language/add':
       return '<p>' . t('Add all languages to be supported by your site. If your desired language is not available in the <em>Language name</em> drop-down, click <em>Custom language</em> and provide a language code and other details manually. When providing a language code manually, be sure to enter a standardized language code, since this code may be used by browsers to determine an appropriate display language.') . '</p>';
     case 'admin/config/regional/language/configure':
-      $output = '<p>' . t("Set which languages to use for content and for the administrative interface. Drag the detection methods into the order they should test for languages. The first method that gets a result will set the language for the relevant part of the site. <strong>Changing these settings may break all incoming URLs, use with caution in a production environment.</strong>") . '</p>';
-      return $output;
-    case 'admin/config/regional/language/configure/url':
-      $output = '<p>' . t('Determine the language by examining the URL. Example: "http://example.com/de/contact" sets language to German based on the use of "de" as the path prefix. "http://de.example.com/contact" sets presentation language to German based on the use of "http://de.example.com" in the domain.') . '</p>';
-      return $output;
-    case 'admin/config/regional/language/configure/session':
-      $output = '<p>' . t('Determine the language from a request/session parameter. Example: "http://example.com?language=de" sets language to German based on the use of "de" within the "language" parameter.') . '</p>';
+      // Language negotiation interface can be overridden, so we provide a means
+      // to override the help too.
+      $output = variable_get('language_negotiation_help');
+      if (empty($output)) {
+        $output = '<p>' . t("Language negotiation settings determine the site's presentation language. Available options include:") . '</p>';
+        $output .= '<ul><li>' . t('<strong>None.</strong> The default language is used for site presentation, though users may (optionally) select a preferred language on the <em>My Account</em> page. (User language preferences will be used for site e-mails, if available.)') . '</li>';
+        $output .= '<li>' . t('<strong>Path prefix only.</strong> The presentation language is determined by examining the path for a language code or other custom string that matches the path prefix (if any) specified for each language. If a suitable prefix is not identified, the default language is used. <em>Example: "example.com/de/contact" sets presentation language to German based on the use of "de" within the path.</em>') . '</li>';
+        $output .= '<li>' . t("<strong>Path prefix with language fallback.</strong> The presentation language is determined by examining the path for a language code or other custom string that matches the path prefix (if any) specified for each language. If a suitable prefix is not identified, the display language is determined by the user's language preferences from the <em>My Account</em> page, or by the browser's language settings. If a presentation language cannot be determined, the default language is used.") . '</li>';
+        $output .= '<li>' . t('<strong>Domain name only.</strong> The presentation language is determined by examining the domain used to access the site, and comparing it to the language domain (if any) specified for each language. If a match is not identified, the default language is used. <em>Example: "http://de.example.com/contact" sets presentation language to German based on the use of "http://de.example.com" in the domain.</em>') . '</li></ul>';
+        $output .= '<p>' . t('The path prefix or domain name for a language may be set by editing the <a href="@languages">available languages</a>. In the absence of an appropriate match, the site is displayed in the <a href="@languages">default language</a>.', array('@languages' => url('admin/settings/language'))) . '</p>';
+      }
       return $output;
     case 'admin/config/regional/translate':
       $output = '<p>' . t('This page provides an overview of available translatable strings. Drupal displays translatable strings in text groups; modules may define additional text groups containing other translatable strings. Because text groups provide a method of grouping related strings, they are often used to focus translation efforts on specific areas of the Drupal interface.') . '</p>';
@@ -334,8 +338,14 @@ function locale_language_selector_form(&
     '#weight' => 1,
   );
 
-  // Get language negotiation settings.
-  $mode = language_negotiation_get(LANGUAGE_TYPE_INTERFACE) != LANGUAGE_NEGOTIATION_DEFAULT;
+  // Get language negotiation settings: the user language preference is taken
+  // into if the user language provider is enabled. This can happen if the
+  // language negotiaion mode is set to path prefix with fallback or if the
+  // the user language provider has been explictly set.
+  $mode =
+    variable_get('locale_language_negotiation') == LANGUAGE_NEGOTIATION_PATH ||
+    language_negotiation_get(LANGUAGE_TYPE_INTERFACE, LOCALE_LANGUAGE_NEGOTIATION_USER);
+
   $form['locale']['language'] = array(
     '#type' => (count($names) <= 5 ? 'radios' : 'select'),
     '#title' => t('Language'),
@@ -440,9 +450,6 @@ function locale_theme() {
     'locale_languages_overview_form' => array(
       'render element' => 'form',
     ),
-    'locale_languages_configure_form' => array(
-      'render element' => 'form',
-    ),
     'locale_date_format_form' => array(
       'render element' => 'form',
     ),
Index: modules/locale/locale.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.test,v
retrieving revision 1.60
diff -u -p -r1.60 locale.test
--- modules/locale/locale.test	10 Jan 2010 22:56:51 -0000	1.60
+++ modules/locale/locale.test	12 Jan 2010 00:58:31 -0000
@@ -1012,13 +1012,11 @@ class LocaleUninstallFunctionalTest exte
 
     // Change language negotiation options.
     drupal_load('module', 'locale');
+    module_load_include('inc', 'locale', 'locale.admin');
     variable_set('language_types', drupal_language_types() + array('language_custom' => TRUE));
-    variable_set('language_negotiation_' . LANGUAGE_TYPE_INTERFACE, locale_language_negotiation_info());
-    variable_set('language_negotiation_' . LANGUAGE_TYPE_CONTENT, locale_language_negotiation_info());
-    variable_set('language_negotiation_' . LANGUAGE_TYPE_URL, locale_language_negotiation_info());
+    locale_language_negotiation_set(LANGUAGE_NEGOTIATION_PATH, TRUE);
 
-    // Change language providers settings.
-    variable_set('locale_language_negotiation_url_part', LOCALE_LANGUAGE_NEGOTIATION_URL_PREFIX);
+    // Change session language providers settings.
     variable_set('locale_language_negotiation_session_param', TRUE);
 
     // Uninstall Locale.
@@ -1048,7 +1046,11 @@ class LocaleUninstallFunctionalTest exte
     $this->assertTrue($language_negotiation, t('Content language negotiation: %setting', array('%setting' => t($language_negotiation ? 'none' : 'set'))));
     $language_negotiation = language_negotiation_get(LANGUAGE_TYPE_URL) == LANGUAGE_NEGOTIATION_DEFAULT;
     $this->assertTrue($language_negotiation, t('URL language negotiation: %setting', array('%setting' => t($language_negotiation ? 'none' : 'set'))));
-
+    $language_negotiation = variable_get('locale_language_negotiation') == LANGUAGE_NEGOTIATION_NONE;
+    $this->assertTrue($language_negotiation, t('Language negotiation mode: %setting', array('%setting' => t($language_negotiation ? 'none' : 'set'))));
+    $language_negotiation = !variable_get('locale_language_negotiation_user_override', FALSE);
+    $this->assertTrue($language_negotiation, t('Language negotiation user override: %setting', array('%setting' => t($language_negotiation ? 'none' : 'set'))));
+    
     // Check language providers settings.
     $this->assertFalse(variable_get('locale_language_negotiation_url_part', FALSE), t('URL language provider indicator settings cleared.'));
     $this->assertFalse(variable_get('locale_language_negotiation_session_param', FALSE), t('Visit language provider settings cleared.'));
@@ -1574,52 +1576,54 @@ class UILanguageNegotiationTest extends 
     $tests = array(
       // Default, browser preference should have no influence.
       array(
-        'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LANGUAGE_NEGOTIATION_DEFAULT),
+        'language_negotiation' => LANGUAGE_NEGOTIATION_PATH_DEFAULT,
         'path' => 'admin/config',
         'expect' => $default_string,
         '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.',
+        'message' => 'LANGUAGE_NEGOTIATION_PATH_DEFAULT: no language prefix, UI language is default and the browser language preference setting is not used.',
       ),
       // Language prefix.
       array(
-        'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LANGUAGE_NEGOTIATION_DEFAULT),
+        'language_negotiation' => LANGUAGE_NEGOTIATION_PATH_DEFAULT,
         'path' => "$language/admin/config",
         'expect' => $language_string,
         'http_header' => $http_header_browser_fallback,
-        'message' => 'URL (PATH) > DEFAULT: with language prefix, UI language is switched based on path prefix',
+        'message' => 'LANGUAGE_NEGOTIATION_PATH_DEFAULT: with language prefix, UI language is switched based on path prefix',
       ),
       // Default, go by browser preference.
       array(
-        'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LOCALE_LANGUAGE_NEGOTIATION_BROWSER),
+        'language_negotiation' => LANGUAGE_NEGOTIATION_PATH,
         'path' => 'admin/config',
         'expect' => $language_browser_fallback_string,
         'http_header' => $http_header_browser_fallback,
-        'message' => 'URL (PATH) > BROWSER: no language prefix, UI language is determined by browser language preference',
+        'message' => 'LANGUAGE_NEGOTIATION_PATH: no language prefix, UI language is determined by browser language preference',
       ),
       // Prefix, switch to the language.
       array(
-        'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LOCALE_LANGUAGE_NEGOTIATION_BROWSER),
+        'language_negotiation' => LANGUAGE_NEGOTIATION_PATH,
         'path' => "$language/admin/config",
         'expect' => $language_string,
         'http_header' => $http_header_browser_fallback,
-        'message' => 'URL (PATH) > BROWSER: with langage prefix, UI language is based on path prefix',
+        'message' => 'LANGUAGE_NEGOTIATION_PATH: with langage prefix, UI language is based on path prefix',
       ),
       // Default, browser language preference is not one of site's lang.
       array(
-        'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LOCALE_LANGUAGE_NEGOTIATION_BROWSER, LANGUAGE_NEGOTIATION_DEFAULT),
+        'language_negotiation' => LANGUAGE_NEGOTIATION_PATH,
         'path' => 'admin/config',
         'expect' => $default_string,
         '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',
+        'message' => 'LANGUAGE_NEGOTIATION_PATH: no language prefix and browser language preference set to unknown language should use default language',
       ),
     );
 
+    module_load_include('inc', 'locale', 'locale.admin');
+    
     foreach ($tests as $test) {
       $this->runTest($test);
     }
 
     // Unknown language prefix should return 404.
-    variable_set('language_negotiation_' . LANGUAGE_TYPE_INTERFACE, locale_language_negotiation_info());
+    locale_language_negotiation_set(LANGUAGE_NEGOTIATION_PATH);
     $this->drupalGet("$language_unknown/admin/config", array(), $http_header_browser_fallback);
     $this->assertResponse(404, "Unknown language path prefix should return 404");
 
@@ -1632,23 +1636,21 @@ class UILanguageNegotiationTest extends 
     $tests = array(
       // Default domain, browser preference should have no influence.
       array(
-        'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LANGUAGE_NEGOTIATION_DEFAULT),
-        'locale_language_negotiation_url_part' => LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN,
+        'language_negotiation' => LANGUAGE_NEGOTIATION_DOMAIN,
         'path' => 'admin/config',
         'expect' => $default_string,
         'http_header' => $http_header_browser_fallback,
-        'message' => 'URL (DOMAIN) > DEFAULT: default domain should get default language',
+        'message' => 'LANGUAGE_NEGOTIATION_DOMAIN: default domain should get default language',
       ),
       // Language domain specific URL, we set the $_SERVER['HTTP_HOST'] in
       // locale_test.module hook_boot() to simulate this.
       array(
-        'language_negotiation' => array(LOCALE_LANGUAGE_NEGOTIATION_URL, LANGUAGE_NEGOTIATION_DEFAULT),
-        'locale_language_negotiation_url_part' => LOCALE_LANGUAGE_NEGOTIATION_URL_DOMAIN,
+        'language_negotiation' => LANGUAGE_NEGOTIATION_DOMAIN,
         'locale_test_domain' => $language_domain,
         'path' => 'admin/config',
         'expect' => $language_string,
         'http_header' => $http_header_browser_fallback,
-        'message' => 'URL (DOMAIN) > DEFAULT: domain example.cn should switch to Chinese',
+        'message' => 'LANGUAGE_NEGOTIATION_DOMAIN: domain example.cn should switch to Chinese',
       ),
     );
 
@@ -1659,11 +1661,7 @@ class UILanguageNegotiationTest extends 
 
   private function runTest($test) {
     if (!empty($test['language_negotiation'])) {
-      $negotiation = array_flip($test['language_negotiation']);
-      language_negotiation_set(LANGUAGE_TYPE_INTERFACE, $negotiation);
-    }
-    if (!empty($test['locale_language_negotiation_url_part'])) {
-      variable_set('locale_language_negotiation_url_part', $test['locale_language_negotiation_url_part']);
+      locale_language_negotiation_set($test['language_negotiation']);
     }
     if (!empty($test['locale_test_domain'])) {
       variable_set('locale_test_domain', $test['locale_test_domain']);
@@ -1814,11 +1812,8 @@ class LocalizeDateFormatsFunctionalTest 
     $this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
 
     // Set language negotiation.
-    $edit = array(
-      'language[enabled][locale-url]' => TRUE,
-      'language_interface[enabled][locale-url]' => TRUE,
-    );
-    $this->drupalPost('admin/config/regional/language/configure', $edit, t('Save settings'));
+    module_load_include('inc', 'locale', 'locale.admin');
+    locale_language_negotiation_set(LANGUAGE_NEGOTIATION_PATH_DEFAULT);
 
     // Configure date formats.
     $this->drupalGet('admin/config/regional/date-time/locale');
Index: modules/node/node.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/node/node.module,v
retrieving revision 1.1203
diff -u -p -r1.1203 node.module
--- modules/node/node.module	11 Jan 2010 06:44:31 -0000	1.1203
+++ modules/node/node.module	11 Jan 2010 23:52:49 -0000
@@ -1236,52 +1236,6 @@ function node_build_content($node, $view
 }
 
 /**
- * Implements hook_language_negotiation_info().
- */
-function node_language_negotiation_info() {
-  $providers = array();
-
-  $providers['node-language'] = array(
-    'types' => array(LANGUAGE_TYPE_CONTENT),
-    'callbacks' => array('language' => 'node_language_provider'),
-    'file' => drupal_get_path('module', 'node') . '/node.module',
-    'name' => t('Node'),
-    'description' => t('The current node language is used.'),
-  );
-
-  return $providers;
-}
-
-/**
- * Return the language of the current node.
- *
- * @param $languages
- *   An array of valid language objects.
- *
- * @return
- *   A valid language code on succes, FALSE otherwise.
- */
-function node_language_provider($languages) {
-  require_once DRUPAL_ROOT . '/' . variable_get('path_inc', 'includes/path.inc');
-
-  $path = isset($_GET['q']) ? $_GET['q'] : '';
-  list($language, $path) = language_url_split_prefix($path, $languages);
-  $language = $language ? $language : language_default();
-  $path = drupal_get_normal_path($path, $language->language);
-
-  // We cannot use args now.
-  $path = explode('/', $path);
-  // Act only if we are in a node page.
-  if (isset($path[0]) && isset($path[1]) && $path[0] == 'node' && $nid = intval($path[1])) {
-    // We cannot perform a node load here.
-    $result = db_query('SELECT n.language FROM {node} n WHERE n.nid = :nid', array(':nid' => $nid))->fetchAssoc();
-    return $result['language'];
-  }
-
-  return FALSE;
-}
-
-/**
  * Generate an array which displays a node detail page.
  *
  * @param $node
