diff --git a/core/includes/bootstrap.inc b/core/includes/bootstrap.inc index f50dd39..bfb7d33 100644 --- a/core/includes/bootstrap.inc +++ b/core/includes/bootstrap.inc @@ -206,6 +206,13 @@ const LANGUAGE_NOT_APPLICABLE = 'zxx'; const LANGUAGE_MULTIPLE = 'mul'; /** + * The language code used when referring to all languages. + * + * @todo W3C uses this for 'Allar', need to find a better code. + */ +const LANGUAGE_ALL = 'all'; + +/** * The type of language used to define the content language. */ const LANGUAGE_TYPE_CONTENT = 'language_content'; @@ -231,6 +238,16 @@ const LANGUAGE_LTR = 0; const LANGUAGE_RTL = 1; /** + * Flag for language list extension to add disabled languages. + */ +const LANGUAGE_ADD_DISABLED = 1; + +/** + * Flag for language list extension to add locked languages. + */ +const LANGUAGE_ADD_LOCKED = 2; + +/** * Time of the current request in seconds elapsed since the Unix Epoch. * * This differs from $_SERVER['REQUEST_TIME'], which is stored as a float @@ -2502,43 +2519,50 @@ function language_multilingual() { /** * Returns a list of configured languages. * - * @param $only_enabled - * (optional) Whether to return only enabled languages. + * @param $flags + * (optional) A combination of LANGUAGE_ADD_DISABLED and LANGUAGE_ADD_LOCKED + * depending on the need for disabled and locked (special) languages in the + * returned list. * * @return * An associative array of languages, keyed by the language code, ordered by * weight ascending and name ascending. */ -function language_list($only_enabled = FALSE) { +function language_list($flags = NULL) { + $languages = &drupal_static(__FUNCTION__); + // Initialize master language list. if (!isset($languages)) { - // Initialize local language list caches. - $languages = array('all' => array(), 'enabled' => array()); + // Initialize local language list cache. + $languages = array(); // Fill in master language list based on current configuration. $default = language_default(); if (language_multilingual() || module_exists('language')) { // Use language module configuration if available. - $languages['all'] = db_query('SELECT * FROM {language} ORDER BY weight ASC, name ASC')->fetchAllAssoc('langcode'); + $languages = db_query('SELECT *, 0 as `default` FROM {language} ORDER BY weight ASC, name ASC')->fetchAllAssoc('langcode'); + $languages[$default->langcode]->default = 1; } else { // No language module, so use the default language only. - $languages['all'][$default->langcode] = $default; + $languages[$default->langcode] = $default; } + } - // Initialize default property so callers have an easy reference and can - // save the same object without data loss. Also fill in the filtered list - // of enabled languages only. - foreach ($languages['all'] as $langcode => $language) { - $languages['all'][$langcode]->default = ($langcode == $default->langcode); - if ($language->enabled) { - $languages['enabled'][$langcode] = $languages['all'][$langcode]; - } + // Filter the full list of languages based on the criteria in $flags. By + // default we remove the disabled and locked languages, but the caller may + // request for those languages to be added as well. + $filtered_languages = array(); + foreach ($languages as $langcode => $language) { + if ((!$language->enabled && !($flags & LANGUAGE_ADD_DISABLED)) || + ($language->locked && !($flags & LANGUAGE_ADD_LOCKED))) { + continue; } + $filtered_languages[$langcode] = $language; } - return $only_enabled ? $languages['enabled'] : $languages['all']; + return $filtered_languages; } /** @@ -2551,7 +2575,7 @@ function language_list($only_enabled = FALSE) { * A fully-populated language object or FALSE. */ function language_load($langcode) { - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED); return isset($languages[$langcode]) ? $languages[$langcode] : FALSE; } @@ -2591,6 +2615,7 @@ function language_default() { 'direction' => 0, 'enabled' => 1, 'weight' => 0, + 'locked' => 0, )); $default->default = TRUE; return $default; diff --git a/core/includes/language.inc b/core/includes/language.inc index 2c46c76..6d9f156 100644 --- a/core/includes/language.inc +++ b/core/includes/language.inc @@ -338,8 +338,7 @@ function language_negotiation_method_invoke($method_id, $method = NULL) { if (!isset($results[$method_id])) { global $user; - // Get the enabled languages only. - $languages = language_list(TRUE); + $languages = language_list(); if (!isset($method)) { $negotiation_info = language_negotiation_info(); diff --git a/core/includes/update.inc b/core/includes/update.inc index 2715fdf..0b67646 100644 --- a/core/includes/update.inc +++ b/core/includes/update.inc @@ -195,9 +195,10 @@ function update_prepare_d8_language() { update_module_add_to_system($modules); update_module_enable($modules); - // Rename 'language' column to 'langcode'. + // Rename 'language' column to 'langcode', add locked column. require_once DRUPAL_ROOT . '/core/modules/language/language.install'; language_update_8000(); + language_update_8001(); } } diff --git a/core/modules/field/field.multilingual.inc b/core/modules/field/field.multilingual.inc index f054bf1..2290f67 100644 --- a/core/modules/field/field.multilingual.inc +++ b/core/modules/field/field.multilingual.inc @@ -165,14 +165,14 @@ function _field_language_suggestion($available_langcodes, $langcode_suggestion, /** * Returns available content language codes. * - * The language codes that may be associated to fields include - * LANGUAGE_NOT_SPECIFIED. + * The languages that may be associated to fields may include + * LANGUAGE_NOT_SPECIFIED, LANGUAGE_NOT_APPLICABLE and LANGUAGE_MULTIPLE. * * @return * An array of language codes. */ function field_content_languages() { - return array_keys(language_list() + array(LANGUAGE_NOT_SPECIFIED => NULL)); + return array_keys(language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED)); } /** diff --git a/core/modules/language/language.admin.inc b/core/modules/language/language.admin.inc index e341094..4c7b461 100644 --- a/core/modules/language/language.admin.inc +++ b/core/modules/language/language.admin.inc @@ -10,7 +10,7 @@ */ function language_admin_overview_form($form, &$form_state) { drupal_static_reset('language_list'); - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED); $default = language_default(); $form['languages'] = array( @@ -29,8 +29,24 @@ function language_admin_overview_form($form, &$form_state) { foreach ($languages as $langcode => $language) { $form['languages'][$langcode]['#weight'] = $language->weight; + $title = check_plain($language->name); + $description = ''; + switch ($langcode) { + case LANGUAGE_NOT_APPLICABLE: + $description = t('For language independent content.'); + break; + case LANGUAGE_NOT_SPECIFIED: + $description = t('Use this when the language is not (yet) known.'); + break; + case LANGUAGE_MULTIPLE: + $description = t('Use this when multiple languages can be assigned, such as a multilingual PDF.'); + break; + } + if (!empty($description)) { + $title .= '
' . $description . '
'; + } $form['languages'][$langcode]['name'] = array( - '#markup' => check_plain($language->name), + '#markup' => $title, ); $form['languages'][$langcode]['enabled'] = array( '#type' => 'checkbox', @@ -61,17 +77,22 @@ function language_admin_overview_form($form, &$form_state) { '#theme_wrappers' => array('language_admin_operations'), '#weight' => 100, ); - $form['languages'][$langcode]['operations']['edit'] = array( - '#type' => 'link', - '#title' => t('edit'), - '#href' => 'admin/config/regional/language/edit/' . $langcode, - ); - $form['languages'][$langcode]['operations']['delete'] = array( - '#type' => 'link', - '#title' => t('delete'), - '#href' => 'admin/config/regional/language/delete/' . $langcode, - '#access' => $langcode != $default->langcode, - ); + if (empty($language->locked)) { + $form['languages'][$langcode]['operations']['edit'] = array( + '#type' => 'link', + '#title' => t('edit'), + '#href' => 'admin/config/regional/language/edit/' . $langcode, + ); + $form['languages'][$langcode]['operations']['delete'] = array( + '#type' => 'link', + '#title' => t('delete'), + '#href' => 'admin/config/regional/language/delete/' . $langcode, + '#access' => $langcode != $default->langcode, + ); + } + else{ + $form['languages'][$langcode]['default']['#disabled'] = TRUE; + } } $form['actions'] = array('#type' => 'actions'); @@ -148,7 +169,7 @@ function theme_language_admin_overview_form_table($variables) { * Process language overview form submissions, updating existing languages. */ function language_admin_overview_form_submit($form, &$form_state) { - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED); $old_default = language_default(); foreach ($languages as $langcode => $language) { @@ -314,7 +335,7 @@ function language_admin_add_custom_form_validate($form, &$form_state) { // Reuse the editing form validation routine if we add a custom language. language_admin_edit_form_validate($form, $form_state); - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED); if (isset($languages[$langcode])) { form_set_error('langcode', t('The language %language (%langcode) already exists.', array('%language' => $languages[$langcode]->name, '%langcode' => $langcode))); } @@ -374,7 +395,7 @@ function language_admin_edit_form_validate($form, &$form_state) { */ function language_admin_edit_form_submit($form, &$form_state) { // Prepare a language object for saving. - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED); $langcode = $form_state['values']['langcode']; $language = $languages[$langcode]; $language->name = $form_state['values']['name']; @@ -395,7 +416,7 @@ function language_admin_delete_form($form, &$form_state, $language) { } // For other languages, warn the user that data loss is ahead. - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED); if (!isset($languages[$langcode])) { drupal_not_found(); @@ -412,7 +433,7 @@ function language_admin_delete_form($form, &$form_state, $language) { */ function language_admin_delete_form_submit($form, &$form_state) { $langcode = $form_state['values']['langcode']; - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED); $language = $languages[$langcode]; $success = language_delete($langcode); @@ -430,7 +451,7 @@ function language_admin_delete_form_submit($form, &$form_state) { */ function language_admin_predefined_list() { include_once DRUPAL_ROOT . '/core/includes/standard.inc'; - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED); $predefined = standard_language_list(); foreach ($predefined as $key => $value) { if (isset($languages[$key])) { @@ -694,8 +715,7 @@ function language_negotiation_configure_url_form($form, &$form_state) { ), ); - // Get the enabled languages only. - $languages = language_list(TRUE); + $languages = language_list(LANGUAGE_ADD_DISABLED); $prefixes = language_negotiation_url_prefixes(); $domains = language_negotiation_url_domains(); foreach ($languages as $langcode => $language) { @@ -731,8 +751,7 @@ function language_negotiation_configure_url_form($form, &$form_state) { * the prefix and domain are only blank for the default. */ function language_negotiation_configure_url_form_validate($form, &$form_state) { - // Get the enabled languages only. - $languages = language_list(TRUE); + $languages = language_list(LANGUAGE_ADD_DISABLED); // Count repeated values for uniqueness check. $count = array_count_values($form_state['values']['prefix']); diff --git a/core/modules/language/language.install b/core/modules/language/language.install index 92f61a0..fbd130d 100644 --- a/core/modules/language/language.install +++ b/core/modules/language/language.install @@ -12,8 +12,13 @@ * system on multilingual sites without needing any preliminary configuration. */ function language_install() { - // Add the default language to the database too. + // Add the default language at first so that language_list() returns this in + // language_special_languages(). language_save(language_default()); + $languages = language_special_languages(); + foreach ($languages as $language) { + language_save($language); + } // Enable URL language detection for each configurable language type. require_once DRUPAL_ROOT . '/core/includes/language.inc'; @@ -23,6 +28,43 @@ function language_install() { } /** + * List of special languages to install on a site. + * + * @return + * An array of language objects. + */ +function language_special_languages() { + $locked_language = array( + 'default' => FALSE, + 'locked' => TRUE, + 'enabled' => TRUE, + ); + $languages = language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED); + + // Language list is ordered by weight, get the biggest one. + $keys = array_keys($languages); + $max_weight = $languages[array_pop($keys)]->weight; + $languages = array(); + + $languages[LANGUAGE_NOT_SPECIFIED] = (object) (array( + 'langcode' => LANGUAGE_NOT_SPECIFIED, + 'name' => t('Not specified'), + 'weight' => ++$max_weight, + ) + $locked_language); + $languages[LANGUAGE_NOT_APPLICABLE] = (object) (array( + 'langcode' => LANGUAGE_NOT_APPLICABLE, + 'name' => t('Not applicable'), + 'weight' => ++$max_weight, + ) + $locked_language); + $languages[LANGUAGE_MULTIPLE] = (object) (array( + 'langcode' => LANGUAGE_MULTIPLE, + 'name' => t('Multiple'), + 'weight' => ++$max_weight, + ) + $locked_language); + return $languages; +} + +/** * Implements hook_uninstall(). */ function language_uninstall() { @@ -88,6 +130,13 @@ function language_schema() { 'default' => 0, 'description' => 'Weight, used in lists of languages.', ), + 'locked' => array( + 'type' => 'int', + 'size' => 'tiny', + 'not null' => TRUE, + 'default' => 0, + 'description' => 'A boolean indicating whether the administrator can edit or delete the language.', + ), ), 'primary key' => array('langcode'), 'indexes' => array( @@ -124,3 +173,49 @@ function language_update_8000() { variable_set('language_default', $language_default); } } + +/** + * Adds the locked column and saves the special languages. + */ +function language_update_8001() { + if (!db_field_exists('language', 'locked')) { + $locked_spec = array( + 'type' => 'int', + 'size' => 'tiny', + 'not null' => TRUE, + 'default' => 0, + 'description' => 'A boolean indicating whether the administrator can edit or delete the language.', + ); + db_add_field('language', 'locked', $locked_spec); + + $max_weight = db_query('SELECT MAX(weight) FROM {language}')->fetchField(); + $languages = array(); + $languages[LANGUAGE_NOT_SPECIFIED] = array( + 'langcode' => LANGUAGE_NOT_SPECIFIED, + 'name' => 'Not specified', + 'weight' => ++$max_weight, + ); + $languages[LANGUAGE_NOT_APPLICABLE] = array( + 'langcode' => LANGUAGE_NOT_APPLICABLE, + 'name' => 'Not applicable', + 'weight' => ++$max_weight, + ); + $languages[LANGUAGE_MULTIPLE] = array( + 'langcode' => LANGUAGE_MULTIPLE, + 'name' => 'Multiple', + 'weight' => ++$max_weight, + ); + foreach ($languages as $language) { + db_insert('language') + ->fields(array( + 'langcode' => $language['langcode'], + 'name' => $language['name'], + 'weight' => $language['weight'], + // These languages are locked, default to enabled. + 'locked' => 1, + 'enabled' => 1, + )) + ->execute(); + } + } +} diff --git a/core/modules/language/language.module b/core/modules/language/language.module index 34f1a59..4e6c990 100644 --- a/core/modules/language/language.module +++ b/core/modules/language/language.module @@ -24,7 +24,7 @@ function language_help($path, $arg) { return $output; case 'admin/config/regional/language': - return '

' . t('With multiple languages enabled, registered users may select their preferred language and authors can assign a specific language to content.') . '

'; + return '

' . t('With multiple languages enabled, registered users can select their preferred language and authors can assign a specific language to content.') . '

'; case 'admin/config/regional/language/add': return '

' . t('Add a language to be supported by your site. If your desired language is not available, pick Custom language... at the end and provide a language code and other details manually.') . '

'; @@ -77,14 +77,16 @@ function language_menu() { 'title' => 'Edit language', 'page callback' => 'drupal_get_form', 'page arguments' => array('language_admin_edit_form', 5), - 'access arguments' => array('administer languages'), + 'access callback' => 'language_access_language_edit_or_delete', + 'access arguments' => array(5), 'file' => 'language.admin.inc', ); $items['admin/config/regional/language/delete/%language'] = array( 'title' => 'Confirm delete', 'page callback' => 'drupal_get_form', 'page arguments' => array('language_admin_delete_form', 5), - 'access arguments' => array('administer languages'), + 'access callback' => 'language_access_language_edit_or_delete', + 'access arguments' => array(5), 'file' => 'language.admin.inc', ); @@ -119,6 +121,13 @@ function language_menu() { } /** + * Editing or deleting locked languages should not be possible. + */ +function language_access_language_edit_or_delete($language) { + return !$language->locked && user_access('administer languages'); +} + +/** * Implements hook_permission(). */ function language_permission() { @@ -192,11 +201,10 @@ function language_save($language) { } // Update language count based on enabled language count. - variable_set('language_count', db_query('SELECT COUNT(langcode) FROM {language} WHERE enabled = 1')->fetchField()); + variable_set('language_count', db_query('SELECT COUNT(langcode) FROM {language} WHERE enabled = 1 AND locked = 0')->fetchField()); // Kill the static cache in language_list(). drupal_static_reset('language_list'); - return $language; } @@ -209,8 +217,8 @@ function language_save($language) { * TRUE if language is successfully deleted. Otherwise FALSE. */ function language_delete($langcode) { - $languages = language_list(); - if (isset($languages[$langcode])) { + $languages = language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED); + if (isset($languages[$langcode]) && !$languages[$langcode]->locked) { $language = $languages[$langcode]; module_invoke_all('language_delete', $language); @@ -394,6 +402,10 @@ function language_modules_disabled($modules) { * Implements hook_language_insert(). */ function language_language_insert($language) { + if (!empty($language->locked)) { + return; + } + language_negotiation_include(); // Add new language to the list of language prefixes. @@ -411,6 +423,10 @@ function language_language_insert($language) { * Implements hook_language_update(). */ function language_language_update($language) { + if (!empty($language->locked)) { + return; + } + language_negotiation_include(); // If the language is the default, then ensure that no other languages have @@ -527,15 +543,16 @@ function language_url_outbound_alter(&$path, &$options, $original_path) { $callbacks = array_keys($callbacks); } + // No language dependent path allowed in this mode. + if (empty($callbacks)) { + unset($options['language']); + return; + } + foreach ($callbacks as $callback) { if (function_exists($callback)) { $callback($path, $options); } } - - // No language dependent path allowed in this mode. - if (empty($callbacks)) { - unset($options['language']); - } } } diff --git a/core/modules/language/language.negotiation.inc b/core/modules/language/language.negotiation.inc index c90457f..401b528 100644 --- a/core/modules/language/language.negotiation.inc +++ b/core/modules/language/language.negotiation.inc @@ -294,8 +294,7 @@ function language_url_fallback($language = NULL, $language_type = LANGUAGE_TYPE_ * Translation links may be provided by other modules. */ function language_switcher_url($type, $path) { - // Get the enabled languages only. - $languages = language_list(TRUE); + $languages = language_list(); $links = array(); foreach ($languages as $language) { @@ -317,8 +316,7 @@ function language_switcher_session($type, $path) { $param = variable_get('language_negotiation_session_param', 'language'); $language_query = isset($_SESSION[$param]) ? $_SESSION[$param] : $GLOBALS[$type]->langcode; - // Get the enabled languages only. - $languages = language_list(TRUE); + $languages = language_list(); $links = array(); $query = $_GET; @@ -354,8 +352,7 @@ function language_url_rewrite_url(&$path, &$options) { $languages = &$drupal_static_fast['languages']; if (!isset($languages)) { - // Get the enabled languages only. - $languages = language_list(TRUE); + $languages = language_list(); $languages = array_flip(array_keys($languages)); } @@ -365,7 +362,7 @@ function language_url_rewrite_url(&$path, &$options) { $options['language'] = $language_url; } // We allow only enabled languages here. - elseif (!isset($languages[$options['language']->langcode])) { + elseif (is_object($options['language']) && !isset($languages[$options['language']->langcode])) { unset($options['language']); return; } @@ -374,7 +371,7 @@ function language_url_rewrite_url(&$path, &$options) { switch (variable_get('language_negotiation_url_part', LANGUAGE_NEGOTIATION_URL_PREFIX)) { case LANGUAGE_NEGOTIATION_URL_DOMAIN: $domains = language_negotiation_url_domains(); - if (!empty($domains[$options['language']->langcode])) { + if (is_object($options['language']) && !empty($domains[$options['language']->langcode])) { // Ask for an absolute URL with our modified base_url. global $is_https; $url_scheme = ($is_https) ? 'https://' : 'http://'; @@ -393,7 +390,7 @@ function language_url_rewrite_url(&$path, &$options) { case LANGUAGE_NEGOTIATION_URL_PREFIX: $prefixes = language_negotiation_url_prefixes(); - if (!empty($prefixes[$options['language']->langcode])) { + if (is_object($options['language']) &&!empty($prefixes[$options['language']->langcode])) { $options['prefix'] = $prefixes[$options['language']->langcode] . '/'; } break; @@ -440,8 +437,7 @@ function language_url_rewrite_session(&$path, &$options) { if (!isset($query_rewrite)) { global $user; if (!$user->uid) { - // Get the enabled languages only. - $languages = language_list(TRUE); + $languages = language_list(); $query_param = check_plain(variable_get('language_negotiation_session_param', 'language')); $query_value = isset($_GET[$query_param]) ? check_plain($_GET[$query_param]) : NULL; $query_rewrite = isset($languages[$query_value]) && language_negotiation_method_enabled(LANGUAGE_NEGOTIATION_SESSION); diff --git a/core/modules/language/language.test b/core/modules/language/language.test index 6c64c29..bd1130d 100644 --- a/core/modules/language/language.test +++ b/core/modules/language/language.test @@ -122,7 +122,7 @@ class LanguageListTest extends DrupalWebTestCase { $this->assertResponse(404, t('Language no longer found.')); // Make sure the "language_count" variable has been updated correctly. drupal_static_reset('language_list'); - $enabled_languages = language_list(TRUE); + $enabled_languages = language_list(); $this->assertEqual(variable_get('language_count', 1), count($enabled_languages), t('Language count is correct.')); // Delete a disabled language. // Disable an enabled language. @@ -133,7 +133,7 @@ class LanguageListTest extends DrupalWebTestCase { $this->assertNoFieldChecked('edit-languages-fr-enabled', t('French language disabled.')); // Get the count of enabled languages. drupal_static_reset('language_list'); - $enabled_languages = language_list(TRUE); + $enabled_languages = language_list(); // Delete the disabled language. $this->drupalPost('admin/config/regional/language/delete/fr', array(), t('Delete')); // We need raw here because %language and %langcode will add HTML. diff --git a/core/modules/locale/locale.admin.inc b/core/modules/locale/locale.admin.inc index d74f714..0e4a94b 100644 --- a/core/modules/locale/locale.admin.inc +++ b/core/modules/locale/locale.admin.inc @@ -45,9 +45,7 @@ function locale_date_format_language_overview_page() { array('data' => t('Operations'), 'colspan' => '2'), ); - // Get the enabled languages only. - $languages = language_list(TRUE); - + $languages = language_list(LANGUAGE_ADD_DISABLED); foreach ($languages as $langcode => $language) { $row = array(); $row[] = $language->name; diff --git a/core/modules/locale/locale.bulk.inc b/core/modules/locale/locale.bulk.inc index ed3d3a6..997500d 100644 --- a/core/modules/locale/locale.bulk.inc +++ b/core/modules/locale/locale.bulk.inc @@ -12,7 +12,7 @@ include_once DRUPAL_ROOT . '/core/includes/gettext.inc'; */ function locale_translate_import_form($form, &$form_state) { drupal_static_reset('language_list'); - $languages = language_list(TRUE); + $languages = language_list(LANGUAGE_ADD_DISABLED); // Initialize a language list to the ones available, including English if we // are to translate Drupal to English as well. @@ -127,7 +127,8 @@ function locale_translate_import_form_submit($form, &$form_state) { * Builds form to export Gettext translation files. */ function locale_translate_export_form($form, &$form_state) { - $languages = language_list(TRUE); + // Get all configurable languages, except English, if we should not translate that. + $languages = language_list(LANGUAGE_ADD_DISABLED); $language_options = array(); foreach ($languages as $langcode => $language) { if ($langcode != 'en' || locale_translate_english()) { @@ -242,8 +243,8 @@ function locale_translate_batch_import_files($langcode = NULL, $finish_feedback } else { // If langcode was not provided, make sure to only import files for the - // languages we have enabled. - $langcodes = array_keys(language_list()); + // languages we have configured. + $langcodes = array_keys(language_list(LANGUAGE_ADD_DISABLED)); } foreach ($langcodes as $langcode) { $files = array_merge($files, file_scan_directory($directory, '!' . (!empty($langcode) ? '\.' . preg_quote($langcode, '!') : '') . '\.po$!', array('recurse' => FALSE))); diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module index 6f81480..655faec 100644 --- a/core/modules/locale/locale.module +++ b/core/modules/locale/locale.module @@ -228,15 +228,14 @@ function locale_permission() { */ function locale_language_selector_form($user) { global $language_interface; - // Get list of enabled languages only. - $languages = language_list(TRUE); + $languages = language_list(); // If the user is being created, we set the user language to the page language. $user_preferred_language = $user->uid ? user_preferred_language($user) : $language_interface; $names = array(); - foreach ($languages as $langcode => $item) { - $names[$langcode] = $item->name; + foreach ($languages as $langcode => $language) { + $names[$langcode] = $language->name; } // Get language negotiation settings. $mode = language_negotiation_method_get_first(LANGUAGE_TYPE_INTERFACE) != LANGUAGE_NEGOTIATION_DEFAULT; @@ -770,7 +769,7 @@ function locale_form_language_admin_overview_form_alter(&$form, &$form_state) { 'translated' => 0, 'ratio' => 0, ); - if ($langcode != 'en' || locale_translate_english()) { + if (empty($language->locked) && ($langcode != 'en' || locale_translate_english())) { $form['languages'][$langcode]['locale_statistics'] = array( '#type' => 'link', '#title' => t('@translated/@total (@ratio%)', array( @@ -781,9 +780,14 @@ function locale_form_language_admin_overview_form_alter(&$form, &$form_state) { '#href' => 'admin/config/regional/translate/translate', ); } + elseif ($langcode == LANGUAGE_SYSTEM) { + $form['languages'][$langcode]['locale_statistics'] = array( + '#markup' => t('Built-in'), + ); + } else { $form['languages'][$langcode]['locale_statistics'] = array( - '#markup' => t('not applicable'), + '#markup' => t('Not applicable'), ); } } diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc index 74603a9..943c55e 100644 --- a/core/modules/locale/locale.pages.inc +++ b/core/modules/locale/locale.pages.inc @@ -28,7 +28,7 @@ function _locale_translate_seek() { if (!($query = _locale_translate_seek_query())) { $query = array( 'translation' => 'all', - 'language' => 'all', + 'language' => LANGUAGE_ALL, 'customized' => 'all', 'string' => '', ); @@ -68,7 +68,7 @@ function _locale_translate_seek() { } $limit_language = NULL; - if ($query['language'] != LANGUAGE_SYSTEM && $query['language'] != 'all') { + if ($query['language'] != LANGUAGE_SYSTEM && $query['language'] != LANGUAGE_ALL) { $sql_query->condition('language', $query['language']); $limit_language = $query['language']; } @@ -117,7 +117,7 @@ function _locale_translate_language_list($translation, $limit_language) { // Add CSS. drupal_add_css(drupal_get_path('module', 'locale') . '/locale.css'); - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED); if (!locale_translate_english()) { unset($languages['en']); } @@ -154,9 +154,9 @@ function _locale_translate_seek_query() { function locale_translation_filters() { $filters = array(); - // Get all languages, except English + // Get all configurable languages, except English if not translatable. drupal_static_reset('language_list'); - $languages = language_list(TRUE); + $languages = language_list(LANGUAGE_ADD_DISABLED); $language_options = array(); foreach ($languages as $langcode => $language) { if ($langcode != 'en' || locale_translate_english()) { @@ -171,7 +171,7 @@ function locale_translation_filters() { $filters['language'] = array( 'title' => t('Language'), - 'options' => array_merge(array('all' => t('All languages'), LANGUAGE_SYSTEM => t('System (English)')), $language_options), + 'options' => array_merge(array(LANGUAGE_ALL => t('All languages'), LANGUAGE_SYSTEM => t('System (English)')), $language_options), ); $filters['translation'] = array( @@ -352,10 +352,11 @@ function locale_translate_edit_form($form, &$form_state, $lid) { // Include default form controls with empty values for all languages. // This ensures that the languages are always in the same order in forms. - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED); if (!locale_translate_english()) { unset($languages['en']); } + // Store languages to iterate for validation and submission of the form. $form_state['langcodes'] = array_keys($languages); $plural_formulas = variable_get('locale_translation_plurals', array()); diff --git a/core/modules/locale/locale.test b/core/modules/locale/locale.test index bb3c6e7..d30d44b 100644 --- a/core/modules/locale/locale.test +++ b/core/modules/locale/locale.test @@ -2520,7 +2520,7 @@ class LocaleUILanguageNegotiationTest extends DrupalWebTestCase { // is for some reason not found when doing translate search. This might // be some bug. drupal_static_reset('language_list'); - $languages = language_list(TRUE); + $languages = language_list(); variable_set('language_default', $languages['vi']); // First visit this page to make sure our target string is searchable. $this->drupalGet('admin/config'); @@ -2804,7 +2804,7 @@ class LocaleUrlRewritingTest extends DrupalWebTestCase { */ function testUrlRewritingEdgeCases() { // Check URL rewriting with a disabled language. - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED); $this->checkUrl($languages['it'], t('Path language is ignored if language is disabled.'), t('URL language negotiation does not work with disabled languages')); // Check URL rewriting with a non-installed language. diff --git a/core/modules/node/node.admin.inc b/core/modules/node/node.admin.inc index ac18da7..2d4ec70 100644 --- a/core/modules/node/node.admin.inc +++ b/core/modules/node/node.admin.inc @@ -106,10 +106,10 @@ function node_filters() { // Language filter if language support is present. if (language_multilingual()) { - $languages = language_list(TRUE); - $language_options = array(LANGUAGE_NOT_SPECIFIED => t('- None -')); + $languages = language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED); foreach ($languages as $langcode => $language) { - $language_options[$langcode] = $language->name; + // Make locked languages appear special in the list. + $language_options[$langcode] = $language->locked ? t('- @name -', array('@name' => $language->name)) : $language->name; } $filters['language'] = array( 'title' => t('language'), @@ -474,7 +474,7 @@ function node_admin_nodes() { $nodes = node_load_multiple($nids); // Prepare the list of nodes. - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED); $destination = drupal_get_destination(); $options = array(); foreach ($nodes as $node) { diff --git a/core/modules/node/node.module b/core/modules/node/node.module index a59a5c7..3b668e0 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -2857,8 +2857,9 @@ function node_form_search_form_alter(&$form, $form_state) { // Languages: $language_options = array(); - foreach (language_list(TRUE) as $langcode => $language) { - $language_options[$langcode] = $language->name; + foreach (language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED) as $langcode => $language) { + // Make locked languages appear special in the list. + $language_options[$langcode] = $language->locked ? t('- @name -', array('@name' => $language->name)) : $language->name; } if (count($language_options) > 1) { $form['advanced']['language'] = array( diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc index 4e94b26..9389731 100644 --- a/core/modules/node/node.pages.inc +++ b/core/modules/node/node.pages.inc @@ -176,17 +176,17 @@ function node_form($form, &$form_state, $node) { $form['#node'] = $node; if (variable_get('node_type_language_' . $node->type, 0) && module_exists('language')) { - $languages = language_list(TRUE); + $languages = language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED); $language_options = array(); foreach ($languages as $langcode => $language) { - $language_options[$langcode] = $language->name; + // Make locked languages appear special in the list. + $language_options[$langcode] = $language->locked ? t('- @name -', array('@name' => $language->name)) : $language->name; } $form['langcode'] = array( '#type' => 'select', '#title' => t('Language'), - '#default_value' => (isset($node->langcode) ? $node->langcode : ''), + '#default_value' => (isset($node->langcode) ? $node->langcode : LANGUAGE_NOT_SPECIFIED), '#options' => $language_options, - '#empty_value' => LANGUAGE_NOT_SPECIFIED, ); } else { diff --git a/core/modules/openid/openid.module b/core/modules/openid/openid.module index 141a3ab..2de64a0 100644 --- a/core/modules/openid/openid.module +++ b/core/modules/openid/openid.module @@ -263,7 +263,7 @@ function openid_form_user_register_form_alter(&$form, &$form_state) { $candidate_langcodes[] = $parts[0] . '-' . $parts[2]; $candidate_langcodes[] = $parts[0] . '-' . $parts[1] . '-' . $parts[2]; } - $enabled_languages = language_list(TRUE); + $enabled_languages = language_list(); // Iterate over the generated permutations starting with the longest (most // specific) strings. foreach (array_reverse($candidate_langcodes) as $candidate_langcode) { diff --git a/core/modules/path/path.admin.inc b/core/modules/path/path.admin.inc index 24921b8..d6bb7b7 100644 --- a/core/modules/path/path.admin.inc +++ b/core/modules/path/path.admin.inc @@ -145,7 +145,7 @@ function path_admin_form($form, &$form_state, $path = array('source' => '', 'ali // A hidden value unless language.module is enabled. if (module_exists('language')) { - $languages = language_list(TRUE); + $languages = language_list(LANGUAGE_ADD_DISABLED); foreach ($languages as $langcode => $language) { $language_options[$langcode] = $language->name; } diff --git a/core/modules/system/system.module b/core/modules/system/system.module index 6fb56e3..7d0a8a5 100644 --- a/core/modules/system/system.module +++ b/core/modules/system/system.module @@ -3909,8 +3909,8 @@ function system_date_format_save($date_format, $dfid = 0) { drupal_write_record('date_formats', $info, $keys); } - // Retrieve an array of language objects for enabled languages. - $languages = language_list(TRUE); + // Retrieve an array of language objects for configurable languages. + $languages = language_list(LANGUAGE_ADD_DISABLED); $locale_format = array(); $locale_format['type'] = $date_format['type']; diff --git a/core/modules/system/tests/upgrade/upgrade.language.test b/core/modules/system/tests/upgrade/upgrade.language.test index e473c63..589632f 100644 --- a/core/modules/system/tests/upgrade/upgrade.language.test +++ b/core/modules/system/tests/upgrade/upgrade.language.test @@ -37,7 +37,7 @@ class LanguageUpgradePathTestCase extends UpgradePathTestCase { // Ensure Catalan was properly upgraded to be the new default language. $this->assertTrue(language_default()->langcode == 'ca', t('Catalan is the default language')); - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED); foreach ($languages as $language) { $this->assertTrue($language->default == ($language->langcode == 'ca'), t('@language default property properly set', array('@language' => $language->name))); } diff --git a/core/modules/translation/translation.module b/core/modules/translation/translation.module index fa73df5..a36f4cd 100644 --- a/core/modules/translation/translation.module +++ b/core/modules/translation/translation.module @@ -137,7 +137,7 @@ function translation_form_node_form_alter(&$form, &$form_state) { $node = $form['#node']; // Build two lists with the disabled and enabled languages. - $languages = language_list(); + $languages = language_list(LANGUAGE_ADD_DISABLED | LANGUAGE_ADD_LOCKED); $grouped_languages = array(); foreach ($languages as $langcode => $language) { $grouped_languages[(int) $language->enabled][$langcode] = $language; @@ -149,7 +149,7 @@ function translation_form_node_form_alter(&$form, &$form_state) { // might need to distinguish between enabled and disabled languages, hence // we divide them in two option groups. if ($translator_widget) { - $options = array($groups[1] => array(LANGUAGE_NOT_SPECIFIED => t('- None -'))); + $options = array(); foreach (array(1, 0) as $status) { $group = $groups[$status]; foreach ($grouped_languages[$status] as $langcode => $language) { @@ -223,7 +223,7 @@ function translation_node_view($node, $view_mode) { // If the site has no translations or is not multilingual we have no content // translation links to display. if (isset($node->tnid) && language_multilingual() && $translations = translation_node_get_translations($node->tnid)) { - $languages = language_list(TRUE); + $languages = language_list(LANGUAGE_ADD_LOCKED); // There might be a language provider enabled defining custom language // switch links which need to be taken into account while generating the @@ -238,8 +238,7 @@ function translation_node_view($node, $view_mode) { foreach ($translations as $langcode => $translation) { // Do not show links to the same node, to unpublished translations or to // translations in disabled languages. - if ($translation->status && isset($languages[$langcode]) && $langcode != $node->langcode) { - $language = $languages[$langcode]; + if ($translation->status && isset($languages[$langcode]) && $languages[$langcode]->enabled && $langcode != $node->langcode) { $key = "translation_$langcode"; if (isset($custom_links->links[$langcode])) { @@ -248,7 +247,7 @@ function translation_node_view($node, $view_mode) { else { $links[$key] = array( 'href' => "node/{$translation->nid}", - 'title' => $language->name, + 'title' => language_name($langcode), 'language' => $language, ); } @@ -295,7 +294,7 @@ function translation_node_prepare($node) { return; } - $language_list = language_list(); + $language_list = language_list(LANGUAGE_ADD_DISABLED); $langcode = $_GET['target']; if (!isset($language_list[$langcode]) || ($source_node->langcode == $langcode)) { // If not supported language, or same language as source node, break. diff --git a/core/modules/translation/translation.pages.inc b/core/modules/translation/translation.pages.inc index 66dfc42..4a5c264 100644 --- a/core/modules/translation/translation.pages.inc +++ b/core/modules/translation/translation.pages.inc @@ -33,7 +33,7 @@ function translation_node_overview($node) { $type = variable_get('translation_language_type', LANGUAGE_TYPE_INTERFACE); $header = array(t('Language'), t('Title'), t('Status'), t('Operations')); - foreach (language_list() as $langcode => $language) { + foreach (language_list(LANGUAGE_ADD_DISABLED) as $langcode => $language) { $options = array(); $language_name = $language->name; if (isset($translations[$langcode])) {