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 11 Jan 2010 03:00:45 -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. Modifying this setting may break all incoming URLs and should be used with caution in a production environment.") ); - 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,92 @@ 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; +/** + * Submit handler for language negotiation settings. + */ +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.')); } /** - * Theme the language configure form. + * TODO * - * @ingroup themeable + * @param $negotiation + * @return unknown_type */ -function theme_locale_languages_configure_form($variables) { - $form = $variables['form']; - $output = ''; - - foreach ($form['#language_types'] as $type) { - $rows = array(); - $info = $form['#language_types_info'][$type]; - $title = ''; - $description = '
' . $form[$type]['#description'] . '
'; - - foreach ($form[$type]['title'] as $id => $element) { - // Do not take form control structures. - if (is_array($element) && element_child($id)) { - $row = array( - 'data' => array( - '' . drupal_render($form[$type]['title'][$id]) . '', - 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; - } - } +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: + $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: + $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 .= '
' . $title . $description . $table . '
'; + 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 11 Jan 2010 03:00:45 -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.inc'); - 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 11 Jan 2010 03:12:00 -0000 @@ -69,13 +69,12 @@ function locale_help($path, $arg) { case 'admin/config/regional/language/add': return '

' . t('Add all languages to be supported by your site. If your desired language is not available in the Language name drop-down, click Custom language 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.') . '

'; case 'admin/config/regional/language/configure': - $output = '

' . 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. Changing these settings may break all incoming URLs, use with caution in a production environment.") . '

'; - return $output; - case 'admin/config/regional/language/configure/url': - $output = '

' . 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.') . '

'; - return $output; - case 'admin/config/regional/language/configure/session': - $output = '

' . 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.') . '

'; + $output = '

' . t("Language negotiation settings determine the site's presentation language. Available options include:") . '

'; + $output .= ''; + $output .= '

' . t('The path prefix or domain name for a language may be set by editing the available languages. In the absence of an appropriate match, the site is displayed in the default language.', array('@languages' => url('admin/settings/language'))) . '

'; return $output; case 'admin/config/regional/translate': $output = '

' . 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.') . '

'; @@ -440,9 +439,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/node/node.module =================================================================== RCS file: /cvs/drupal/drupal/modules/node/node.module,v retrieving revision 1.1202 diff -u -p -r1.1202 node.module --- modules/node/node.module 9 Jan 2010 23:03:21 -0000 1.1202 +++ modules/node/node.module 11 Jan 2010 03:00:45 -0000 @@ -1230,52 +1230,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