Commit a7c92599 authored by catch's avatar catch

Issue #1266318 by Gábor Hojtsy, alberto56, David Lesieur: Make English a first class language.

parent d0fb1ad5
......@@ -158,6 +158,13 @@
*/
define('DRUPAL_KILOBYTE', 1024);
/**
* System language (only applicable to UI).
*
* Refers to the language used in Drupal and module/theme source code.
*/
define('LANGUAGE_SYSTEM', 'system');
/**
* The language code used when no language is explicitly assigned.
*
......@@ -1476,7 +1483,7 @@ function t($string, array $args = array(), array $options = array()) {
// Merge in default.
if (empty($options['langcode'])) {
$options['langcode'] = isset($language->language) ? $language->language : 'en';
$options['langcode'] = isset($language->language) ? $language->language : LANGUAGE_SYSTEM;
}
if (empty($options['context'])) {
$options['context'] = '';
......@@ -1494,7 +1501,7 @@ function t($string, array $args = array(), array $options = array()) {
$string = $custom_strings[$options['langcode']][$options['context']][$string];
}
// Translate with locale module if enabled.
elseif ($options['langcode'] != 'en' && function_exists('locale')) {
elseif ($options['langcode'] != LANGUAGE_SYSTEM && ($options['langcode'] != 'en' || variable_get('locale_translate_english', FALSE)) && function_exists('locale')) {
$string = locale($string, $options['context'], $options['langcode']);
}
if (empty($args)) {
......@@ -2632,12 +2639,6 @@ function language_list($field = 'language') {
$default = language_default();
if (drupal_multilingual() || module_exists('locale')) {
$languages['language'] = db_query('SELECT * FROM {languages} ORDER BY weight ASC, name ASC')->fetchAllAssoc('language');
// Users cannot uninstall the native English language. However, we allow
// it to be hidden from the installed languages. Therefore, at least one
// other language must be enabled then.
if (!$languages['language']['en']->enabled && !variable_get('language_native_enabled', TRUE)) {
unset($languages['language']['en']);
}
}
else {
// No locale module, so use the default language only.
......
......@@ -1875,7 +1875,7 @@ function format_date($timestamp, $type = 'medium', $format = '', $timezone = NUL
// Use the default langcode if none is set.
global $language;
if (empty($langcode)) {
$langcode = isset($language->language) ? $language->language : 'en';
$langcode = isset($language->language) ? $language->language : LANGUAGE_SYSTEM;
}
switch ($type) {
......
......@@ -703,7 +703,9 @@ function _locale_invalidate_js($langcode = NULL) {
if (empty($langcode)) {
// Invalidate all languages.
$languages = language_list();
unset($languages['en']);
if (!locale_translate_english()) {
unset($languages['en']);
}
foreach ($languages as $lcode => $data) {
$parsed['refresh:' . $lcode] = 'waiting';
}
......
......@@ -79,7 +79,7 @@ function locale_language_overview_form($form, &$form_state) {
'#type' => 'link',
'#title' => t('delete'),
'#href' => 'admin/config/regional/language/delete/' . $langcode,
'#access' => $langcode != 'en' && $langcode != $default->language,
'#access' => $langcode != $default->language,
);
}
......@@ -416,11 +416,6 @@ function locale_languages_edit_form_submit($form, &$form_state) {
*/
function locale_languages_delete_form($form, &$form_state, $language) {
$langcode = $language->language;
// Do not allow deletion of English locale.
if ($langcode == 'en') {
drupal_set_message(t('The English language cannot be deleted.'));
drupal_goto('admin/config/regional/language');
}
if (language_default()->language == $langcode) {
drupal_set_message(t('The default language cannot be deleted.'));
......
......@@ -14,7 +14,9 @@ function locale_translate_import_form($form) {
// Get all languages, except English
drupal_static_reset('language_list');
$names = locale_language_list('name');
unset($names['en']);
if (!locale_translate_english()) {
unset($names['en']);
}
if (!count($names)) {
$languages = _locale_prepare_predefined_list();
......@@ -101,7 +103,9 @@ function locale_translate_export_screen() {
// Get all languages, except English
drupal_static_reset('language_list');
$names = locale_language_list('name');
unset($names['en']);
if (!locale_translate_english()) {
unset($names['en']);
}
$output = '';
// Offer translation export if any language is set up.
if (count($names)) {
......@@ -215,7 +219,9 @@ function locale_batch_by_language($langcode, $finished = NULL, $skip = array())
function locale_batch_by_component($components, $finished = '_locale_batch_system_finished') {
$files = array();
$languages = language_list('enabled');
unset($languages[1]['en']);
if (!locale_translate_english()) {
unset($languages[1]['en']);
}
if (count($languages[1])) {
$language_list = join('|', array_keys($languages[1]));
// Collect all files to import for all $components.
......
......@@ -9,20 +9,9 @@
* Implements hook_install().
*/
function locale_install() {
// locales_source.source and locales_target.target are not used as binary
// fields; non-MySQL database servers need to ensure the field type is text
// and that LIKE produces a case-sensitive comparison.
db_insert('languages')
->fields(array(
'language' => 'en',
'name' => 'English',
'direction' => 0,
'enabled' => 1,
'weight' => 0,
'javascript' => '',
))
->execute();
// Add the default language to the database too.
include_once DRUPAL_ROOT . '/includes/locale.inc';
locale_language_save(language_default());
}
/**
......
......@@ -1100,7 +1100,7 @@ function locale_form_locale_language_overview_form_alter(&$form, &$form_state) {
'translated' => 0,
'ratio' => 0,
);
if ($langcode != 'en') {
if ($langcode != 'en' || locale_translate_english()) {
$form['languages'][$langcode]['locale_statistics'] = array(
'#type' => 'link',
'#title' => t('@translated/@total (@ratio%)', array(
......@@ -1113,8 +1113,36 @@ function locale_form_locale_language_overview_form_alter(&$form, &$form_state) {
}
else {
$form['languages'][$langcode]['locale_statistics'] = array(
'#markup' => t('built-in'),
'#markup' => t('not applicable'),
);
}
}
}
/**
* Implements hook_form_FORM_ID_alter() for locale_languages_edit_form().
*/
function locale_form_locale_languages_edit_form_alter(&$form, &$form_state) {
if ($form['langcode']['#type'] == 'value' && $form['langcode']['#value'] == 'en') {
$form['locale_translate_english'] = array(
'#title' => t('Enable interface translation to English'),
'#type' => 'checkbox',
'#default_value' => locale_translate_english(),
);
$form['#submit'][] = 'locale_form_locale_languages_edit_form_alter_submit';
}
}
/**
* Submission handler to record our custom setting.
*/
function locale_form_locale_languages_edit_form_alter_submit($form, $form_state) {
variable_set('locale_translate_english', $form_state['values']['locale_translate_english']);
}
/**
* Utility function to tell if locale translates to English.
*/
function locale_translate_english() {
return variable_get('locale_translate_english', FALSE);
}
......@@ -55,8 +55,8 @@ function _locale_translate_seek() {
default:
$condition = db_or()
->condition('s.source', '%' . db_like($query['string']) . '%', 'LIKE');
if ($query['language'] != 'en') {
// Only search in translations if the language is not forced to English.
if ($query['language'] != LANGUAGE_SYSTEM) {
// Only search in translations if the language is not forced to system language.
$condition->condition('t.translation', '%' . db_like($query['string']) . '%', 'LIKE');
}
$sql_query->condition($condition);
......@@ -64,7 +64,7 @@ function _locale_translate_seek() {
}
$limit_language = NULL;
if ($query['language'] != 'en' && $query['language'] != 'all') {
if ($query['language'] != LANGUAGE_SYSTEM && $query['language'] != 'all') {
$sql_query->condition('language', $query['language']);
$limit_language = $query['language'];
}
......@@ -114,7 +114,9 @@ function _locale_translate_language_list($translation, $limit_language) {
drupal_add_css(drupal_get_path('module', 'locale') . '/locale.css');
$languages = language_list();
unset($languages['en']);
if (!locale_translate_english()) {
unset($languages['en']);
}
$output = '';
foreach ($languages as $langcode => $language) {
if (!$limit_language || $limit_language == $langcode) {
......@@ -151,7 +153,9 @@ function locale_translation_filters() {
// Get all languages, except English
drupal_static_reset('language_list');
$languages = locale_language_list('name');
unset($languages['en']);
if (!locale_translate_english()) {
unset($languages['en']);
}
$filters['string'] = array(
'title' => t('String contains'),
......@@ -160,7 +164,7 @@ function locale_translation_filters() {
$filters['language'] = array(
'title' => t('Language'),
'options' => array_merge(array('all' => t('All languages'), 'en' => t('English (provided by Drupal)')), $languages),
'options' => array_merge(array('all' => t('All languages'), LANGUAGE_SYSTEM => t('System (English)')), $languages),
);
$filters['translation'] = array(
......@@ -297,7 +301,9 @@ 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();
unset($languages['en']);
if (!locale_translate_english()) {
unset($languages['en']);
}
$form['translations'] = array('#tree' => TRUE);
// Approximate the number of rows to use in the default textarea.
$rows = min(ceil(str_word_count($source->source) / 12), 10);
......
......@@ -163,11 +163,36 @@ class LocaleConfigurationTest extends DrupalWebTestCase {
// Make sure the "language_count" variable has not changed.
$this->assertEqual(variable_get('language_count', 1), count($enabled[1]), t('Language count is correct.'));
// Ensure we can delete the English language. Right now English is the only
// language so we must add a new language and make it the default before
// deleting English.
$langcode = 'xx';
$name = $this->randomName(16);
$edit = array(
'predefined_langcode' => 'custom',
'langcode' => $langcode,
'name' => $name,
'direction' => '0',
);
$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.'));
$this->assertText($name, t('Name found.'));
// Ensure we can't delete the English language.
$this->drupalGet('admin/config/regional/language/delete/en');
// Check if we can change the default language.
$path = 'admin/config/regional/language';
$this->drupalGet($path);
$this->assertFieldChecked('edit-site-default-en', t('English is the default language.'));
// Change the default language.
$edit = array(
'site_default' => $langcode,
);
$this->drupalPost(NULL, $edit, t('Save configuration'));
$this->assertNoFieldChecked('edit-site-default-en', t('Default language updated.'));
$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.'));
$this->drupalPost('admin/config/regional/language/delete/en', array(), t('Delete'));
// We need raw here because %locale will add HTML.
$this->assertRaw(t('The language %locale has been removed.', array('%locale' => 'English')), t('The English language has been removed.'));
}
}
......@@ -296,6 +321,7 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
$language_indicator = "<em class=\"locale-untranslated\">$langcode</em> ";
// This will be the translation of $name.
$translation = $this->randomName(16);
$translation_to_en = $this->randomName(16);
// Add custom language.
$this->drupalLogin($admin_user);
......@@ -335,13 +361,39 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
$lid = $matches[1];
// No t() here, it's surely not translated yet.
$this->assertText($name, t('name found on edit screen.'));
$this->assertNoText('English', t('No way to translate the string to English.'));
$this->drupalLogout();
$this->drupalLogin($admin_user);
$this->drupalPost('admin/config/regional/language/edit/en', array('locale_translate_english' => TRUE), t('Save language'));
$this->drupalLogout();
$this->drupalLogin($translate_user);
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
// assertText() seems to remove the input field where $name always could be
// found, so this is not a false assert. See how assertNoText succeeds
// later.
$this->assertText($name, t('Search found the name.'));
$this->assertRaw($language_indicator, t('Name is untranslated.'));
// Assume this is the only result, given the random name.
$this->clickLink(t('edit'));
$string_edit_url = $this->getUrl();
$edit = array(
"translations[$langcode]" => $translation,
'translations[en]' => $translation_to_en,
);
$this->drupalPost(NULL, $edit, t('Save translations'));
$this->assertText(t('The string has been saved.'), t('The string has been saved.'));
$this->assertEqual($this->getUrl(), url('admin/config/regional/translate/translate', array('absolute' => TRUE)), t('Correct page redirection.'));
$this->assertTrue($name != $translation && t($name, array(), array('langcode' => $langcode)) == $translation, t('t() works.'));
$this->drupalGet($string_edit_url);
$this->assertRaw($translation, t('Non-English translation properly saved.'));
$this->assertRaw($translation_to_en, t('English translation properly saved.'));
$this->assertTrue($name != $translation && t($name, array(), array('langcode' => $langcode)) == $translation, t('t() works for non-English.'));
// Refresh the locale() cache to get fresh data from t() below. We are in
// the same HTTP request and therefore t() is not refreshed by saving the
// translation above.
locale_reset();
// Now we should get the proper fresh translation from t().
$this->assertTrue($name != $translation_to_en && t($name, array(), array('langcode' => 'en')) == $translation_to_en, t('t() works for English.'));
$this->assertTrue(t($name, array(), array('langcode' => LANGUAGE_SYSTEM)) == $name, t('t() works for LANGUAGE_SYSTEM.'));
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
// The indicator should not be here.
$this->assertNoRaw($language_indicator, t('String is translated.'));
......@@ -627,10 +679,10 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
$this->assertNoText(t('No strings available.'), t('Search found the translation.'));
// Ensure translated string doesn't appear if searching on English.
// Ensure translated string doesn't appear if searching in System (English).
$search = array(
'string' => $translation,
'language' => 'en',
'language' => LANGUAGE_SYSTEM,
'translation' => 'all',
);
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment