Index: includes/bootstrap.inc
===================================================================
RCS file: /cvs/drupal/drupal/includes/bootstrap.inc,v
retrieving revision 1.293
diff -u -r1.293 bootstrap.inc
--- includes/bootstrap.inc 4 Aug 2009 04:02:25 -0000 1.293
+++ includes/bootstrap.inc 10 Aug 2009 14:47:14 -0000
@@ -202,6 +202,21 @@
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']);
@@ -1607,36 +1622,43 @@
/**
* 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.222
diff -u -r1.222 locale.inc
--- includes/locale.inc 5 Aug 2009 15:58:34 -0000 1.222
+++ includes/locale.inc 10 Aug 2009 14:47:16 -0000
@@ -33,7 +33,7 @@
*/
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 @@
$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 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 @@
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 @@
);
}
}
- $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 @@
'#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 @@
$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 @@
* 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 @@
'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 @@
}
variable_set('language_default', $default);
}
+ if ($form_state['values']['type'] & LANGUAGE_TYPE_UI) {
+ _locale_invalidate_js($form_state['values']['langcode']);
+ }
$form_state['redirect'] = 'admin/international/language';
return;
}
@@ -420,7 +442,7 @@
}
// 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 @@
* 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 @@
// 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 @@
* @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 @@
'domain' => $domain,
'prefix' => $prefix,
'enabled' => $enabled,
+ 'type' => $type,
))
->execute();
@@ -1140,8 +1165,10 @@
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 @@
}
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_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 @@
}
/**
+ * 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.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.test,v
retrieving revision 1.34
diff -u -r1.34 locale.test
--- modules/locale/locale.test 3 Aug 2009 22:18:59 -0000 1.34
+++ modules/locale/locale.test 10 Aug 2009 14:47:17 -0000
@@ -68,6 +68,7 @@
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/international/language/add', $edit, t('Add custom language'));
$this->assertEqual($this->getUrl(), url('admin/international/language', array('absolute' => TRUE)), t('Correct page redirection.'));
@@ -151,9 +152,30 @@
$this->assertEqual($this->getUrl(), url('admin/international/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/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 @@
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/international/language/add', $edit, t('Add custom language'));
// Add string.
@@ -336,6 +359,7 @@
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/international/language/add', $edit, t('Add custom language'));
// Add string.
@@ -397,6 +421,7 @@
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/international/language/add', $edit, t('Add custom language'));
// Add string.
@@ -632,6 +657,11 @@
);
$this->drupalPost('admin/international/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 @@
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/international/language/add', $edit, t('Add custom language'));
@@ -1146,6 +1177,7 @@
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/international/language/add', $edit, t('Add custom language'));
@@ -1164,6 +1196,7 @@
'native' => $native_disabled,
'prefix' => $prefix_disabled,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/international/language/add', $edit, t('Add custom language'));
// Disable the language.
@@ -1239,6 +1272,7 @@
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/international/language/add', $edit, t('Add custom language'));
@@ -1325,6 +1359,7 @@
'native' => $native,
'prefix' => $prefix,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/international/language/add', $edit, t('Add custom language'));
@@ -1343,6 +1378,7 @@
'native' => $native_disabled,
'prefix' => $prefix_disabled,
'direction' => '0',
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/international/language/add', $edit, t('Add custom language'));
// Disable second custom language.
Index: modules/locale/locale.module
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.module,v
retrieving revision 1.246
diff -u -r1.246 locale.module
--- modules/locale/locale.module 2 Aug 2009 15:44:08 -0000 1.246
+++ modules/locale/locale.module 10 Aug 2009 14:47:16 -0000
@@ -301,7 +301,7 @@
'#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
@@ -489,12 +489,12 @@
* @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.install
===================================================================
RCS file: /cvs/drupal/drupal/modules/locale/locale.install,v
retrieving revision 1.46
diff -u -r1.46 locale.install
--- modules/locale/locale.install 14 Jul 2009 10:22:17 -0000 1.46
+++ modules/locale/locale.install 10 Aug 2009 14:47:16 -0000
@@ -42,6 +42,7 @@
$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 @@
'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/simpletest/tests/common.test
===================================================================
RCS file: /cvs/drupal/drupal/modules/simpletest/tests/common.test,v
retrieving revision 1.57
diff -u -r1.57 common.test
--- modules/simpletest/tests/common.test 30 Jul 2009 19:57:10 -0000 1.57
+++ modules/simpletest/tests/common.test 10 Aug 2009 14:47:18 -0000
@@ -1111,6 +1111,7 @@
'native' => self::LANGCODE,
'direction' => LANGUAGE_LTR,
'prefix' => self::LANGCODE,
+ 'type' => LANGUAGE_TYPE_ANY,
);
$this->drupalPost('admin/international/language/add', $edit, t('Add custom language'));