Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.302
diff -u -p -r1.302 bootstrap.inc
--- includes/bootstrap.inc 24 Aug 2009 00:14:18 -0000 1.302
+++ includes/bootstrap.inc 26 Aug 2009 20:30:14 -0000
@@ -193,6 +193,21 @@ define('LANGUAGE_LTR', 0);
define('LANGUAGE_RTL', 1);
/**
+ * The type of language used to select the user interface.
+ */
+define('LANGUAGE_TYPE_UI', 0x1);
+
+/**
+ * The type of language used to define the content language.
+ */
+define('LANGUAGE_TYPE_CONTENT', 0x2);
+
+/**
+ * Any type of language.
+ */
+define('LANGUAGE_TYPE_ANY', LANGUAGE_TYPE_UI | LANGUAGE_TYPE_CONTENT);
+
+/**
* For convenience, define a short form of the request time global.
*/
define('REQUEST_TIME', $_SERVER['REQUEST_TIME']);
@@ -1657,36 +1672,43 @@ function drupal_language_initialize() {
/**
* Get a list of languages set up indexed by the specified key
*
- * @param $field The field to index the list with.
+ * @param $field
+ * The field to index the list with.
+ * @param $type
+ * The type of the languages to be returned.
*/
-function language_list($field = 'language') {
+function language_list($field = 'language', $type = LANGUAGE_TYPE_UI) {
$languages = &drupal_static(__FUNCTION__);
// Init language list
- if (!isset($languages)) {
+ if (!isset($languages[$type])) {
if (variable_get('language_count', 1) > 1 || module_exists('locale')) {
- $languages['language'] = db_query('SELECT * FROM {languages} ORDER BY weight ASC, name ASC')->fetchAllAssoc('language');
+ $types = array($type, LANGUAGE_TYPE_ANY);
+ $where = $type == LANGUAGE_TYPE_ANY ? '' : 'WHERE type IN (%d, %d) ';
+ $languages[$type]['language'] = db_query('SELECT * FROM {languages} ' . $where . ' ORDER BY weight ASC, name ASC', $types)
+ ->fetchAllAssoc('language');
}
else {
// No locale module, so use the default language only.
$default = language_default();
- $languages['language'][$default->language] = $default;
+ $languages[$type]['language'][$default->language] = $default;
}
}
// Return the array indexed by the right field
- if (!isset($languages[$field])) {
- $languages[$field] = array();
- foreach ($languages['language'] as $lang) {
+ if (!isset($languages[$type][$field])) {
+ $languages[$type][$field] = array();
+ foreach ($languages[$type]['language'] as $lang) {
// Some values should be collected into an array
if (in_array($field, array('enabled', 'weight'))) {
- $languages[$field][$lang->$field][$lang->language] = $lang;
+ $languages[$type][$field][$lang->$field][$lang->language] = $lang;
}
else {
- $languages[$field][$lang->$field] = $lang;
+ $languages[$type][$field][$lang->$field] = $lang;
}
}
}
- return $languages[$field];
+
+ return $languages[$type][$field];
}
/**
Index: includes/locale.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/locale.inc,v
retrieving revision 1.226
diff -u -p -r1.226 locale.inc
--- includes/locale.inc 22 Aug 2009 14:34:17 -0000 1.226
+++ includes/locale.inc 26 Aug 2009 20:30:14 -0000
@@ -33,7 +33,7 @@ define('LOCALE_IMPORT_KEEP', 1);
*/
function locale_languages_overview_form() {
drupal_static_reset('language');
- $languages = language_list('language');
+ $languages = language_list('language', LANGUAGE_TYPE_ANY);
$options = array();
$form['weight'] = array('#tree' => TRUE);
@@ -51,6 +51,7 @@ function locale_languages_overview_form(
$form['name'][$langcode] = array('#markup' => check_plain($language->name));
$form['native'][$langcode] = array('#markup' => check_plain($language->native));
$form['direction'][$langcode] = array('#markup' => ($language->direction == LANGUAGE_RTL ? t('Right to left') : t('Left to right')));
+ $form['type'][$langcode] = array('#markup' => _locale_language_type_label($language->type));
}
$form['enabled'] = array('#type' => 'checkboxes',
'#options' => $options,
@@ -73,6 +74,7 @@ function locale_languages_overview_form(
*/
function theme_locale_languages_overview_form($form) {
$default = language_default();
+ $languages = language_list();
foreach ($form['name'] as $key => $element) {
// Do not take form control structures.
if (is_array($element) && element_child($key)) {
@@ -80,11 +82,16 @@ function theme_locale_languages_overview
if ($key == $default->language) {
$form['enabled'][$key]['#attributes']['disabled'] = 'disabled';
}
+ // Disable the default radio button for content languages.
+ if (!isset($languages[$key])) {
+ $form['site_default'][$key]['#attributes']['disabled'] = 'disabled';
+ }
$rows[] = array(
'data' => array(
'' . drupal_render($form['name'][$key]) . '',
drupal_render($form['native'][$key]),
check_plain($key),
+ drupal_render($form['type'][$key]),
drupal_render($form['direction'][$key]),
array('data' => drupal_render($form['enabled'][$key]), 'align' => 'center'),
drupal_render($form['site_default'][$key]),
@@ -95,7 +102,7 @@ function theme_locale_languages_overview
);
}
}
- $header = array(array('data' => t('English name')), array('data' => t('Native name')), array('data' => t('Code')), array('data' => t('Direction')), array('data' => t('Enabled')), array('data' => t('Default')), array('data' => t('Weight')), array('data' => t('Operations')));
+ $header = array(array('data' => t('English name')), array('data' => t('Native name')), array('data' => t('Code')), array('data' => t('Type')), array('data' => t('Direction')), array('data' => t('Enabled')), array('data' => t('Default')), array('data' => t('Weight')), array('data' => t('Operations')));
$output = theme('table', $header, $rows, array('id' => 'language-order'));
$output .= drupal_render_children($form);
@@ -294,6 +301,13 @@ function _locale_languages_common_contro
'#default_value' => @$language->direction,
'#options' => array(LANGUAGE_LTR => t('Left to right'), LANGUAGE_RTL => t('Right to left'))
);
+ $form['type'] = array('#type' => 'radios',
+ '#title' => t('Type'),
+ '#required' => TRUE,
+ '#description' => t('The type of language being configured.'),
+ '#default_value' => @$language->type,
+ '#options' => _locale_language_type_label(),
+ );
return $form;
}
@@ -328,7 +342,7 @@ function locale_languages_predefined_for
$langcode = $form_state['values']['langcode'];
if (isset($form_state['values']['name'])) {
// Custom language form.
- locale_add_language($langcode, $form_state['values']['name'], $form_state['values']['native'], $form_state['values']['direction'], $form_state['values']['domain'], $form_state['values']['prefix']);
+ locale_add_language($langcode, $form_state['values']['name'], $form_state['values']['native'], $form_state['values']['direction'], $form_state['values']['domain'], $form_state['values']['prefix'], TRUE, FALSE, $form_state['values']['type']);
drupal_set_message(t('The language %language has been created and can now be used. More information is available on the help screen.', array('%language' => t($form_state['values']['name']), '@locale-help' => url('admin/help/locale'))));
}
else {
@@ -353,18 +367,22 @@ function locale_languages_predefined_for
* Validate the language editing form. Reused for custom language addition too.
*/
function locale_languages_edit_form_validate($form, &$form_state) {
+ $default = language_default('language');
if (!empty($form_state['values']['domain']) && !empty($form_state['values']['prefix'])) {
form_set_error('prefix', t('Domain and path prefix values should not be set at the same time.'));
}
if (!empty($form_state['values']['domain']) && $duplicate = db_query("SELECT language FROM {languages} WHERE domain = :domain AND language <> :language", array(':domain' => $form_state['values']['domain'], ':language' => $form_state['values']['langcode']))->fetchField()) {
form_set_error('domain', t('The domain (%domain) is already tied to a language (%language).', array('%domain' => $form_state['values']['domain'], '%language' => $duplicate->language)));
}
- if (empty($form_state['values']['prefix']) && language_default('language') != $form_state['values']['langcode'] && empty($form_state['values']['domain'])) {
+ if (empty($form_state['values']['prefix']) && $default != $form_state['values']['langcode'] && empty($form_state['values']['domain'])) {
form_set_error('prefix', t('Only the default language can have both the domain and prefix empty.'));
}
if (!empty($form_state['values']['prefix']) && $duplicate = db_query("SELECT language FROM {languages} WHERE prefix = :prefix AND language <> :language", array(':prefix' => $form_state['values']['prefix'], ':language' => $form_state['values']['langcode']))->fetchField()) {
form_set_error('prefix', t('The prefix (%prefix) is already tied to a language (%language).', array('%prefix' => $form_state['values']['prefix'], '%language' => $duplicate->language)));
}
+ if ($form_state['values']['type'] == LANGUAGE_TYPE_CONTENT && $default == $form_state['values']['langcode']) {
+ form_set_error('type', t('The default site language type cannot be set to "Content".'));
+ }
}
/**
@@ -378,6 +396,7 @@ function locale_languages_edit_form_subm
'domain' => $form_state['values']['domain'],
'prefix' => $form_state['values']['prefix'],
'direction' => $form_state['values']['direction'],
+ 'type' => $form_state['values']['type'],
))
->condition('language', $form_state['values']['langcode'])
->execute();
@@ -391,6 +410,9 @@ function locale_languages_edit_form_subm
}
variable_set('language_default', $default);
}
+ if ($form_state['values']['type'] & LANGUAGE_TYPE_UI) {
+ _locale_invalidate_js($form_state['values']['langcode']);
+ }
$form_state['redirect'] = 'admin/config/regional/language';
return;
}
@@ -420,7 +442,7 @@ function locale_languages_delete_form(&$
}
// For other languages, warn user that data loss is ahead.
- $languages = language_list();
+ $languages = language_list('language', LANGUAGE_TYPE_ANY);
if (!isset($languages[$langcode])) {
drupal_not_found();
@@ -435,7 +457,7 @@ function locale_languages_delete_form(&$
* Process language deletion submissions.
*/
function locale_languages_delete_form_submit($form, &$form_state) {
- $languages = language_list();
+ $languages = language_list('language', LANGUAGE_TYPE_ANY);
if (isset($languages[$form_state['values']['langcode']])) {
// Remove translations first.
db_delete('locales_target')
@@ -542,8 +564,10 @@ function locale_translate_overview_scree
// Languages with at least one record in the locale table.
$translations = db_query("SELECT COUNT(*) AS translation, t.language, s.textgroup FROM {locales_source} s INNER JOIN {locales_target} t ON s.lid = t.lid GROUP BY textgroup, language");
foreach ($translations as $data) {
- $ratio = (!empty($groupsums[$data->textgroup]) && $data->translation > 0) ? round(($data->translation/$groupsums[$data->textgroup]) * 100.0, 2) : 0;
- $rows[$data->language][$data->textgroup] = $data->translation . '/' . $groupsums[$data->textgroup] . " ($ratio%)";
+ if (isset($languages[$data->language])) {
+ $ratio = (!empty($groupsums[$data->textgroup]) && $data->translation > 0) ? round(($data->translation/$groupsums[$data->textgroup]) * 100.0, 2) : 0;
+ $rows[$data->language][$data->textgroup] = $data->translation . '/' . $groupsums[$data->textgroup] . " ($ratio%)";
+ }
}
return theme('table', $headers, $rows);
@@ -1103,7 +1127,7 @@ function locale_translate_delete_form_su
* @param $default
* Optionally set this language to be the default.
*/
-function locale_add_language($langcode, $name = NULL, $native = NULL, $direction = LANGUAGE_LTR, $domain = '', $prefix = '', $enabled = TRUE, $default = FALSE) {
+function locale_add_language($langcode, $name = NULL, $native = NULL, $direction = LANGUAGE_LTR, $domain = '', $prefix = '', $enabled = TRUE, $default = FALSE, $type = LANGUAGE_TYPE_ANY) {
// Default prefix on language code.
if (empty($prefix)) {
$prefix = $langcode;
@@ -1127,6 +1151,7 @@ function locale_add_language($langcode,
'domain' => $domain,
'prefix' => $prefix,
'enabled' => $enabled,
+ 'type' => $type,
))
->execute();
@@ -1140,8 +1165,10 @@ function locale_add_language($langcode,
variable_set('language_count', variable_get('language_count', 1) + 1);
}
- // Force JavaScript translation file creation for the newly added language.
- _locale_invalidate_js($langcode);
+ if ($type & LANGUAGE_TYPE_UI) {
+ // Force JavaScript translation file creation for the newly added language.
+ _locale_invalidate_js($langcode);
+ }
watchdog('locale', 'The %language language (%code) has been created.', array('%language' => $name, '%code' => $langcode));
}
@@ -2383,7 +2410,7 @@ function _locale_rebuild_js($langcode =
}
else {
// Get information about the locale.
- $languages = language_list();
+ $languages = language_list('language', LANGUAGE_TYPE_ANY);
$language = $languages[$langcode];
}
@@ -2533,7 +2560,7 @@ function _locale_translate_language_list
*/
function _locale_prepare_predefined_list() {
include_once DRUPAL_ROOT . '/includes/iso.inc';
- $languages = language_list();
+ $languages = language_list('language', LANGUAGE_TYPE_ANY);
$predefined = _locale_get_predefined_list();
foreach ($predefined as $key => $value) {
if (isset($languages[$key])) {
@@ -2709,6 +2736,18 @@ function _locale_batch_language_finished
}
/**
+ * Helper function to provide language type labels.
+ */
+function _locale_language_type_label($type = NULL) {
+ $labels = array(
+ LANGUAGE_TYPE_UI => t('Interface'),
+ LANGUAGE_TYPE_CONTENT => t('Content'),
+ LANGUAGE_TYPE_ANY => t('Interface and content')
+ );
+ return empty($type) ? $labels : $labels[$type];
+}
+
+/**
* @} End of "locale-autoimport"
*/
Index: modules/locale/locale.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.install,v
retrieving revision 1.47
diff -u -p -r1.47 locale.install
--- modules/locale/locale.install 17 Aug 2009 19:14:40 -0000 1.47
+++ modules/locale/locale.install 26 Aug 2009 20:30:14 -0000
@@ -42,6 +42,7 @@ function locale_update_7000() {
$ret = array();
db_drop_index($ret, 'locales_source', 'source');
db_add_index($ret, 'locales_source', 'source_context', array(array('source', 30), 'context'));
+ db_add_column($ret, 'languages', 'type', 'int', array('not null' => TRUE, 'default' => LANGUAGE_TYPE_ANY));
return $ret;
}
@@ -167,6 +168,12 @@ function locale_schema() {
'default' => '',
'description' => 'Location of JavaScript translation file.',
),
+ 'type' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'default' => LANGUAGE_TYPE_ANY,
+ 'description' => 'Language type (UI, Content, Any).',
+ ),
),
'primary key' => array('language'),
'indexes' => array(
Index: modules/locale/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.module,v
retrieving revision 1.256
diff -u -p -r1.256 locale.module
--- modules/locale/locale.module 24 Aug 2009 00:14:20 -0000 1.256
+++ modules/locale/locale.module 26 Aug 2009 20:30:14 -0000
@@ -315,7 +315,7 @@ function locale_form_alter(&$form, &$for
'#type' => 'select',
'#title' => t('Language'),
'#default_value' => (isset($form['#node']->language) ? $form['#node']->language : ''),
- '#options' => array('' => t('Language neutral')) + locale_language_list('name'),
+ '#options' => array('' => t('Language neutral')) + locale_language_list('name', FALSE, LANGUAGE_TYPE_CONTENT),
);
}
// Node type without language selector: assign the default for new nodes
@@ -504,12 +504,12 @@ function locale_language_name($lang) {
* @param $all
* Boolean to return all languages or only enabled ones
*/
-function locale_language_list($field = 'name', $all = FALSE) {
+function locale_language_list($field = 'name', $all = FALSE, $type = LANGUAGE_TYPE_UI) {
if ($all) {
- $languages = language_list();
+ $languages = language_list('language', $type);
}
else {
- $languages = language_list('enabled');
+ $languages = language_list('enabled', $type);
$languages = $languages[1];
}
$list = array();
Index: modules/locale/locale.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.test,v
retrieving revision 1.39
diff -u -p -r1.39 locale.test
--- modules/locale/locale.test 22 Aug 2009 00:58:53 -0000 1.39
+++ modules/locale/locale.test 26 Aug 2009 20:30:14 -0000
@@ -68,6 +68,7 @@ class LocaleConfigurationTest extends Dr
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
$this->assertEqual($this->getUrl(), url('admin/config/regional/language', array('absolute' => TRUE)), t('Correct page redirection.'));
@@ -151,9 +152,30 @@ class LocaleConfigurationTest extends Dr
$this->assertEqual($this->getUrl(), url('admin/config/regional/language', array('absolute' => TRUE)), t('Correct page redirection.'));
$this->assertText(t('The English language cannot be deleted.'), t('Failed to delete English language.'));
+ // Test language type settings.
+ drupal_static_reset('language_list');
+ require_once DRUPAL_ROOT . '/includes/locale.inc';
+ $langtypes = array(LANGUAGE_TYPE_UI => 'ui', LANGUAGE_TYPE_CONTENT => 'ct');
+ foreach ($langtypes as $type => $langcode) {
+ $edit = array(
+ 'langcode' => $langcode,
+ 'name' => $this->randomName(16),
+ 'native' => $this->randomName(16),
+ 'prefix' => $langcode,
+ 'direction' => LANGUAGE_LTR,
+ 'type' => $type,
+ );
+ $this->drupalPost('admin/config/international/language/add', $edit, t('Add custom language'));
+ $languages = language_list('language', $type);
+ $this->assertTrue(isset($languages[$langcode]), t('%type language correctly added', array('%type' => _locale_language_type_label($type))));
+ $language_type = isset($languages[$langcode]) ? $languages[$langcode]->type : -1;
+ $this->assertTrue($language_type == $type, t('Language type correctly set'));
+ $type = $type == LANGUAGE_TYPE_UI ? LANGUAGE_TYPE_CONTENT : LANGUAGE_TYPE_UI;
+ $this->assertFalse(isset($languages[$langtypes[$type]]), t('%type language not listed', array('%type' => _locale_language_type_label($type))));
+ }
+
$this->drupalLogout();
}
-
}
/**
@@ -204,6 +226,7 @@ class LocaleTranslationFunctionalTest ex
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
// Add string.
@@ -336,6 +359,7 @@ class LocaleTranslationFunctionalTest ex
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
// Add string.
@@ -397,6 +421,7 @@ class LocaleTranslationFunctionalTest ex
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
// Add string.
@@ -632,6 +657,11 @@ class LocaleImportFunctionalTest extends
);
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
$this->assertNoText(t('No strings found for your search.'), t('String overwritten by imported string.'));
+
+ // Content languages cannot be listed in the language selector.
+ locale_inc_callback('locale_add_language', 'de', 'German', 'Deutsch', LANGUAGE_LTR, '', 'de', TRUE, FALSE, LANGUAGE_TYPE_CONTENT);
+ $this->drupalGet('admin/international/translate/import');
+ $this->assertNoRaw('Deutsch', t('Content language not listed in the language selector'));
}
/**
@@ -655,6 +685,7 @@ class LocaleImportFunctionalTest extends
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
@@ -1146,6 +1177,7 @@ class LocaleUserLanguageFunctionalTest e
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
@@ -1164,6 +1196,7 @@ class LocaleUserLanguageFunctionalTest e
'native' => $native_disabled,
'prefix' => $prefix_disabled,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
// Disable the language.
@@ -1239,6 +1272,7 @@ class LocalePathFunctionalTest extends D
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
@@ -1325,6 +1359,7 @@ class LocaleContentFunctionalTest extend
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
@@ -1343,6 +1378,7 @@ class LocaleContentFunctionalTest extend
'native' => $native_disabled,
'prefix' => $prefix_disabled,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));
// Disable second custom language.
Index: modules/simpletest/tests/common.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/common.test,v
retrieving revision 1.69
diff -u -p -r1.69 common.test
--- modules/simpletest/tests/common.test 25 Aug 2009 21:16:31 -0000 1.69
+++ modules/simpletest/tests/common.test 26 Aug 2009 20:30:14 -0000
@@ -1238,6 +1238,7 @@ class FormatDateUnitTest extends DrupalW
'native' => self::LANGCODE,
'direction' => LANGUAGE_LTR,
'prefix' => self::LANGCODE,
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add custom language'));