Issue #1323176 by Gábor Hojtsy: Decouple UI translation language information from language list schema.

8.0.x
Nathaniel 2011-11-09 13:25:48 +09:00
parent 63f61838b4
commit e0b74b5b39
5 changed files with 77 additions and 90 deletions

View File

@ -392,8 +392,8 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
case 'db-store':
// We got header information.
if ($value['msgid'] == '') {
$languages = language_list();
if (($mode != LOCALE_IMPORT_KEEP) || empty($languages[$lang]->plurals)) {
$locale_plurals = variable_get('locale_translation_plurals', array());
if (($mode != LOCALE_IMPORT_KEEP) || empty($locale_plurals[$lang]['plurals'])) {
// Since we only need to parse the header if we ought to update the
// plural formula, only run this if we don't need to keep existing
// data untouched or if we don't have an existing plural formula.
@ -401,24 +401,17 @@ function _locale_import_one_string($op, $value = NULL, $mode = NULL, $lang = NUL
// Get the plural formula and update in database.
if (isset($header["Plural-Forms"]) && $p = _locale_import_parse_plural_forms($header["Plural-Forms"], $file->uri)) {
list($nplurals, $plural) = $p;
db_update('languages')
->fields(array(
'plurals' => $nplurals,
'formula' => $plural,
))
->condition('language', $lang)
->execute();
list($nplurals, $formula) = $p;
}
else {
db_update('languages')
->fields(array(
'plurals' => 0,
'formula' => '',
))
->condition('language', $lang)
->execute();
$nplurals = 0;
$formula = '';
}
$locale_plurals[$lang] = array(
'plurals' => $nplurals,
'formula' => $formula,
);
variable_set('locale_translation_plurals', $locale_plurals);
}
$header_done = TRUE;
}
@ -924,6 +917,8 @@ function _locale_export_get_strings($language = NULL) {
function _locale_export_po_generate($language = NULL, $strings = array(), $header = NULL) {
global $user;
$locale_plurals = variable_get('locale_translation_plurals', array());
if (!isset($header)) {
if (isset($language)) {
$header = '# ' . $language->name . ' translation of ' . variable_get('site_name', 'Drupal') . "\n";
@ -939,8 +934,8 @@ function _locale_export_po_generate($language = NULL, $strings = array(), $heade
$header .= "\"MIME-Version: 1.0\\n\"\n";
$header .= "\"Content-Type: text/plain; charset=utf-8\\n\"\n";
$header .= "\"Content-Transfer-Encoding: 8bit\\n\"\n";
if ($language->formula && $language->plurals) {
$header .= "\"Plural-Forms: nplurals=" . $language->plurals . "; plural=" . strtr($language->formula, array('$' => '')) . ";\\n\"\n";
if (!empty($locale_plurals[$language->language]['formula'])) {
$header .= "\"Plural-Forms: nplurals=" . $locale_plurals[$language->language]['plurals'] . "; plural=" . strtr($locale_plurals[$language->language]['formula'], array('$' => '')) . ";\\n\"\n";
}
}
else {
@ -978,7 +973,7 @@ function _locale_export_po_generate($language = NULL, $strings = array(), $heade
$output .= 'msgid_plural ' . _locale_export_string($strings[$plural]['source']);
if (isset($language)) {
$translation = $string['translation'];
for ($i = 0; $i < $language->plurals; $i++) {
for ($i = 0; $i < $locale_plurals[$language->language]['plurals']; $i++) {
$output .= 'msgstr[' . $i . '] ' . _locale_export_string($translation);
if ($plural) {
$translation = _locale_export_remove_plural($strings[$plural]['translation']);

View File

@ -751,8 +751,9 @@ function _locale_rebuild_js($langcode = NULL) {
$data = "Drupal.locale = { ";
if (!empty($language->formula)) {
$data .= "'pluralFormula': function (\$n) { return Number({$language->formula}); }, ";
$locale_plurals = variable_get('locale_translation_plurals', array());
if (!empty($locale_plurals[$language->language])) {
$data .= "'pluralFormula': function (\$n) { return Number({$locale_plurals[$language->language]['formula']}); }, ";
}
$data .= "'strings': " . drupal_json_encode($translations) . " };";
@ -764,10 +765,11 @@ function _locale_rebuild_js($langcode = NULL) {
$dir = 'public://' . variable_get('locale_js_directory', 'languages');
// Delete old file, if we have no translations anymore, or a different file to be saved.
$changed_hash = $language->javascript != $data_hash;
if (!empty($language->javascript) && (!$data || $changed_hash)) {
file_unmanaged_delete($dir . '/' . $language->language . '_' . $language->javascript . '.js');
$language->javascript = '';
$locale_javascripts = variable_get('locale_translation_javascript', array());
$changed_hash = !isset($locale_javascripts[$language->language]) || ($locale_javascripts[$language->language] != $data_hash);
if (!empty($locale_javascripts[$language->language]) && (!$data || $changed_hash)) {
file_unmanaged_delete($dir . '/' . $language->language . '_' . $locale_javascripts[$language->language] . '.js');
$locale_javascripts[$language->language] = '';
$status = 'deleted';
}
@ -780,7 +782,7 @@ function _locale_rebuild_js($langcode = NULL) {
// Save the file.
if (file_unmanaged_save_data($data, $dest)) {
$language->javascript = $data_hash;
$locale_javascripts[$language->language] = $data_hash;
// If we deleted a previous version of the file and we replace it with a
// new one we have an update.
if ($status == 'deleted') {
@ -798,7 +800,7 @@ function _locale_rebuild_js($langcode = NULL) {
}
}
else {
$language->javascript = '';
$locale_javascripts[$language->language] = '';
$status = 'error';
}
}
@ -807,22 +809,7 @@ function _locale_rebuild_js($langcode = NULL) {
// deleted). Act only if some operation was executed that changed the hash
// code.
if ($status && $changed_hash) {
db_update('languages')
->fields(array(
'javascript' => $language->javascript,
))
->condition('language', $language->language)
->execute();
// Update the default language variable if the default language has been altered.
// This is necessary to keep the variable consistent with the database
// version of the language and to prevent checking against an outdated hash.
$default_langcode = language_default()->language;
drupal_static_reset('language_list');
if ($default_langcode == $language->language) {
$default = language_load($default_langcode);
variable_set('language_default', $default);
}
variable_set('locale_translation_javascript', $locale_javascripts);
}
// Log the operation and return success flag.
@ -831,7 +818,7 @@ function _locale_rebuild_js($langcode = NULL) {
watchdog('locale', 'Updated JavaScript translation file for the language %language.', array('%language' => $language->name));
return TRUE;
case 'rebuilt':
watchdog('locale', 'JavaScript translation file %file.js was lost.', array('%file' => $language->javascript), WATCHDOG_WARNING);
watchdog('locale', 'JavaScript translation file %file.js was lost.', array('%file' => $locale_javascripts[$language->language]), WATCHDOG_WARNING);
// Proceed to the 'created' case as the JavaScript translation file has
// been created again.
case 'created':

View File

@ -22,10 +22,10 @@ function locale_uninstall() {
$locale_js_directory = 'public://' . variable_get('locale_js_directory', 'languages');
if (is_dir($locale_js_directory)) {
$files = db_query('SELECT language, javascript FROM {languages}');
foreach ($files as $file) {
if (!empty($file->javascript)) {
file_unmanaged_delete($locale_js_directory . '/' . $file->language . '_' . $file->javascript . '.js');
$locale_javascripts = variable_get('locale_translation_javascript', array());
foreach ($locale_javascripts as $langcode => $file_suffix) {
if (!empty($file_suffix)) {
file_unmanaged_delete($locale_js_directory . '/' . $langcode . '_' . $file_suffix . '.js');
}
}
// Delete the JavaScript translations directory if empty.
@ -47,6 +47,8 @@ function locale_uninstall() {
variable_del('javascript_parsed');
variable_del('locale_field_language_fallback');
variable_del('locale_cache_length');
variable_del('locale_translation_plurals');
variable_del('locale_translation_javascript');
foreach (language_types() as $type) {
variable_del("language_negotiation_$type");
@ -97,19 +99,6 @@ function locale_schema() {
'default' => 0,
'description' => 'Enabled flag (1 = Enabled, 0 = Disabled).',
),
'plurals' => array(
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'Number of plural indexes in this language.',
),
'formula' => array(
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
'default' => '',
'description' => 'Plural formula in PHP code to evaluate to get plural indexes.',
),
'domain' => array(
'type' => 'varchar',
'length' => 128,
@ -130,13 +119,6 @@ function locale_schema() {
'default' => 0,
'description' => 'Weight, used in lists of languages.',
),
'javascript' => array(
'type' => 'varchar',
'length' => 64,
'not null' => TRUE,
'default' => '',
'description' => 'Location of JavaScript translation file.',
),
),
'primary key' => array('language'),
'indexes' => array(
@ -249,6 +231,32 @@ function locale_update_8000() {
db_drop_field('languages', 'native');
}
/**
* Decouple interface translation related data from language objects.
*/
function locale_update_8001() {
// Gather data from existing languages table and save in variables.
$languages = db_select('languages', 'l')
->fields('l')
->execute();
$plurals = array();
$javascript = array();
foreach ($languages as $language) {
$plurals[$language->language] = array(
'plurals' => $language->plurals,
'formula' => $language->formula,
);
$javascript[$language->language] = $language->javascript;
}
variable_set('locale_translation_plurals', $plurals);
variable_set('locale_translation_javascript', $javascript);
// Drop now unneeded columns.
db_drop_field('languages', 'plurals');
db_drop_field('languages', 'formula');
db_drop_field('languages', 'javascript');
}
/**
* @} End of "addtogroup updates-7.x-to-8.x"
* The next series of updates should start at 9000.

View File

@ -725,19 +725,18 @@ function locale_reset() {
*/
function locale_get_plural($count, $langcode = NULL) {
global $language;
$locale_formula = &drupal_static(__FUNCTION__, array());
$locale_plurals = &drupal_static(__FUNCTION__, array());
$plurals = &drupal_static(__FUNCTION__ . ':plurals', array());
$langcode = $langcode ? $langcode : $language->language;
if (!isset($plurals[$langcode][$count])) {
if (empty($locale_formula)) {
$language_list = language_list();
$locale_formula[$langcode] = $language_list[$langcode]->formula;
if (empty($locale_plural_formulas)) {
$locale_plurals = variable_get('locale_translation_plurals', array());
}
if ($locale_formula[$langcode]) {
if (!empty($locale_plurals[$langcode])) {
$n = $count;
$plurals[$langcode][$count] = @eval('return intval(' . $locale_formula[$langcode] . ');');
$plurals[$langcode][$count] = @eval('return intval(' . $locale_plurals[$langcode]['formula'] . ');');
return $plurals[$langcode][$count];
}
else {
@ -925,9 +924,10 @@ function locale_js_alter(&$javascript) {
}
// Add the translation JavaScript file to the page.
if ($files && !empty($language->javascript)) {
$locale_javascripts = variable_get('locale_translation_javascript', array());
if ($files && !empty($locale_javascripts[$language->language])) {
// Add the translation JavaScript file to the page.
$file = $dir . '/' . $language->language . '_' . $language->javascript . '.js';
$file = $dir . '/' . $language->language . '_' . $locale_javascripts[$language->language] . '.js';
$javascript[$file] = drupal_js_defaults($file);
}
}

View File

@ -483,14 +483,8 @@ class LocaleTranslationFunctionalTest extends DrupalWebTestCase {
require_once DRUPAL_ROOT . '/core/includes/locale.inc';
_locale_rebuild_js($langcode);
// Retrieve the JavaScript translation hash code for the custom language to
// check that the translation file has been properly built.
$file = db_select('languages', 'l')
->fields('l', array('javascript'))
->condition('language', $langcode)
->execute()
->fetchObject();
$js_file = 'public://' . variable_get('locale_js_directory', 'languages') . '/' . $langcode . '_' . $file->javascript . '.js';
$locale_javascripts = variable_get('locale_translation_javascript', array());
$js_file = 'public://' . variable_get('locale_js_directory', 'languages') . '/' . $langcode . '_' . $locale_javascripts[$langcode] . '.js';
$this->assertTrue($result = file_exists($js_file), t('JavaScript file created: %file', array('%file' => $result ? $js_file : t('not found'))));
// Test JavaScript translation rebuilding.
@ -743,7 +737,8 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
$this->assertRaw(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => 9, '%update' => 0, '%delete' => 0)), t('The translation file was successfully imported.'));
// This import should have saved plural forms to have 2 variants.
$this->assert(db_query("SELECT plurals FROM {languages} WHERE language = 'fr'")->fetchField() == 2, t('Plural number initialized.'));
$locale_plurals = variable_get('locale_translation_plurals', array());
$this->assert($locale_plurals['fr']['plurals'] == 2, t('Plural number initialized.'));
// Ensure we were redirected correctly.
$this->assertEqual($this->getUrl(), url('admin/config/regional/translate', array('absolute' => TRUE)), t('Correct page redirection.'));
@ -789,7 +784,8 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
$this->assertText(t('No strings available.'), t('String not overwritten by imported string.'));
// This import should not have changed number of plural forms.
$this->assert(db_query("SELECT plurals FROM {languages} WHERE language = 'fr'")->fetchField() == 2, t('Plural numbers untouched.'));
$locale_plurals = variable_get('locale_translation_plurals', array());
$this->assert($locale_plurals['fr']['plurals'] == 2, t('Plural numbers untouched.'));
// Try importing a .po file with overriding strings, and ensure existing
// strings are overwritten.
@ -809,7 +805,8 @@ class LocaleImportFunctionalTest extends DrupalWebTestCase {
$this->drupalPost('admin/config/regional/translate/translate', $search, t('Filter'));
$this->assertNoText(t('No strings available.'), t('String overwritten by imported string.'));
// This import should have changed number of plural forms.
$this->assert(db_query("SELECT plurals FROM {languages} WHERE language = 'fr'")->fetchField() == 3, t('Plural numbers changed.'));
$locale_plurals = variable_get('locale_translation_plurals', array());
$this->assert($locale_plurals['fr']['plurals'] == 3, t('Plural numbers changed.'));
}
/**
@ -1233,8 +1230,8 @@ class LocaleUninstallFunctionalTest extends DrupalWebTestCase {
$edit = array('translations[fr]' => 'french translation');
$this->drupalPost('admin/config/regional/translate/edit/' . $string->lid, $edit, t('Save translations'));
_locale_rebuild_js('fr');
$file = db_query('SELECT javascript FROM {languages} WHERE language = :language', array(':language' => 'fr'))->fetchObject();
$js_file = 'public://' . variable_get('locale_js_directory', 'languages') . '/fr_' . $file->javascript . '.js';
$locale_javascripts = variable_get('locale_translation_javascript', array());
$js_file = 'public://' . variable_get('locale_js_directory', 'languages') . '/fr_' . $locale_javascripts['fr'] . '.js';
$this->assertTrue($result = file_exists($js_file), t('JavaScript file created: %file', array('%file' => $result ? $js_file : t('none'))));
// Disable string caching.