Issue #1635084 by webflo, vasi1186: Added Track import status of files in the locale .po file directory.

8.0.x
webchick 2012-06-16 17:16:07 +02:00
parent 2103890de1
commit aa9dd8ff88
5 changed files with 387 additions and 5 deletions

View File

@ -0,0 +1,181 @@
<?php
/**
* @file
* Definition of Drupal\locale\Tests\LocaleFileImportStatus.
*/
namespace Drupal\locale\Tests;
use Drupal\simpletest\WebTestBase;
/**
* Functional tests for the import of translation files.
*/
class LocaleFileImportStatus extends WebTestBase {
public static function getInfo() {
return array(
'name' => 'Translation file import status',
'description' => 'Tests the status of imported translation files.',
'group' => 'Locale',
);
}
function setUp() {
parent::setUp('locale');
// Create and login user.
$admin_user = $this->drupalCreateUser(array('administer site configuration', 'administer languages', 'access administration pages'));
$this->drupalLogin($admin_user);
// Set the translation file directory.
variable_set('locale_translate_file_directory', drupal_get_path('module', 'locale') . '/tests');
}
/**
* Add a language.
*
* @param $langcode
* The language of the langcode to add.
*/
function addLanguage($langcode) {
// Add language.
$edit = array('predefined_langcode' => $langcode);
$this->drupalPost('admin/config/regional/language/add', $edit, t('Add language'));
drupal_static_reset('language_list');
$this->assertTrue(language_load($langcode), t('Language %langcode added.', array('%langcode' => $langcode)));
}
/**
* Get translations for a array of strings.
*
* @param $strings
* A array of strings to translate.
* @param $langcode
* The language code of the language to translate to.
*/
function checkTranslations($strings, $langcode) {
foreach ($strings as $source => $translation) {
$db_translation = db_query('SELECT translation FROM {locales_target} lt INNER JOIN {locales_source} ls ON ls.lid = lt.lid WHERE ls.source = :source AND lt.language = :langcode', array(':source' => $source, ':langcode' => $langcode))->fetchField();
$this->assertEqual((string) $translation, (string) $db_translation);
}
}
/**
* Import a single interface translation file.
*
* @param $langcode
* Langcode of the po file and language to import.
* @param int $timestamp_difference
* (optional) Timestamp offset, used to mock older or newer files.
*
* @return stdClass
* A file object of type stdClass.
*/
function mockImportedPoFile($langcode, $timestamp_difference = 0) {
$dir = variable_get('locale_translate_file_directory', drupal_get_path('module', 'locale') . '/tests');
$testfile_uri = $dir . '/test.' . $langcode . '.po';
$file = locale_translate_file_create($testfile_uri);
$file->original_timestamp = $file->timestamp;
$file->timestamp = $file->timestamp + $timestamp_difference;
$file->langcode = $langcode;
// Fill the {locale_file} with a custom timestamp.
if ($timestamp_difference != 0) {
locale_translate_update_file_history($file);
}
$count = db_query('SELECT COUNT(*) FROM {locale_file} WHERE langcode = :langcode', array(':langcode' => $langcode))->fetchField();
$this->assertEqual(1, $count, format_plural($count, '@count file registered in {locale_file}.', '@count files registered in {locale_file}.'));
$result = db_query('SELECT langcode, uri FROM {locale_file}')->fetchAssoc();
$this->assertEqual($result['uri'], $testfile_uri, t('%uri is in {locale_file}.', array('%uri' => $result['uri'])));
$this->assertEqual($result['langcode'], $langcode, t('Langcode is %langcode.', array('%langcode' => $langcode)));
return $file;
}
/**
* Test the basic bulk import functionality.
*/
function testBulkImport() {
$langcode = 'de';
// Translations should not exist.
$strings = array(
'Monday' => '',
'Tuesday' => '',
);
$this->checkTranslations($strings, $langcode);
// Add language.
$this->addLanguage($langcode);
// The file was imported, translations should exist.
$strings = array(
'Monday' => 'Montag',
'Tuesday' => 'Dienstag',
);
$this->checkTranslations($strings, $langcode);
}
/**
* Update a pre-existing file.
*/
function testBulkImportUpdateExisting() {
$langcode = 'de';
// Translations should not exist.
$strings = array(
'Monday' => '',
'Tuesday' => '',
);
$this->checkTranslations($strings, $langcode);
// Fill the {locale_file} table with a older file.
$file = $this->mockImportedPoFile($langcode, -1);
// Add language.
$this->addLanguage($langcode);
// The file was imported, translations should exist.
$strings = array(
'Monday' => 'Montag',
'Tuesday' => 'Dienstag',
);
$this->checkTranslations($strings, $langcode);
$timestamp = db_query('SELECT timestamp FROM {locale_file} WHERE uri = :uri', array(':uri' => $file->uri))->fetchField();
$this->assertEqual($timestamp, $file->original_timestamp, t('File is updated.'));
}
/**
* Don't update a pre-existing file.
*/
function testBulkImportNotUpdateExisting() {
$langcode = 'de';
// Translations should not exist.
$strings = array(
'Monday' => '',
'Tuesday' => '',
);
$this->checkTranslations($strings, $langcode);
// Fill the {locale_file} table with a newer file.
$file = $this->mockImportedPoFile($langcode, 1);
// Add language.
$this->addLanguage($langcode);
// The file was not imported, the translation should not exist.
$strings = array(
'Monday' => '',
'Tuesday' => '',
);
$this->checkTranslations($strings, $langcode);
$timestamp = db_query('SELECT timestamp FROM {locale_file} WHERE uri = :uri', array(':uri' => $file->uri))->fetchField();
$this->assertEqual($timestamp, $file->timestamp);
}
}

View File

@ -228,14 +228,15 @@ function locale_translate_add_language_set_batch($langcode) {
* (optional) Language code to limit files being imported.
* @param $finish_feedback
* (optional) Whether to give feedback to the user when finished.
* @param $force
* (optional) Import all available files, even if they were imported before.
*
* @todo
* Integrate with update status to identify projects needed and integrate
* l10n_update functionality to feed in translation files alike.
* See http://drupal.org/node/1191488.
*/
function locale_translate_batch_import_files($langcode = NULL, $finish_feedback = FALSE) {
$directory = variable_get('locale_translate_file_directory', conf_path() . '/files/translations');
function locale_translate_batch_import_files($langcode = NULL, $finish_feedback = FALSE, $force = FALSE) {
$files = array();
if (!empty($langcode)) {
$langcodes = array($langcode);
@ -246,11 +247,40 @@ function locale_translate_batch_import_files($langcode = NULL, $finish_feedback
$langcodes = array_keys(language_list());
}
foreach ($langcodes as $langcode) {
$files = array_merge($files, file_scan_directory($directory, '!' . (!empty($langcode) ? '\.' . preg_quote($langcode, '!') : '') . '\.po$!', array('recurse' => FALSE)));
$files = array_merge($files, locale_translate_get_interface_translation_files($langcode));
}
if (!$force) {
$result = db_select('locale_file', 'lf')
->fields('lf', array('langcode', 'uri', 'timestamp'))
->condition('langcode', $langcodes)
->execute()
->fetchAllAssoc('uri');
foreach ($result as $uri => $info) {
if (isset($files[$uri]) && filemtime($uri) <= $info->timestamp) {
// The file is already imported and it did not change since the import.
// Remove it from file list and don't import it again.
unset($files[$uri]);
}
}
}
return locale_translate_batch_build($files, $finish_feedback);
}
/**
* Get an array of available interface translation file.
*
* @param $langcode
* The langcode for the interface translation files. Pass NULL to get all
* available interface translation files.
*
* @return array
* An array of interface translation files.
*/
function locale_translate_get_interface_translation_files($langcode = NULL) {
$directory = variable_get('locale_translate_file_directory', conf_path() . '/files/translations');
return file_scan_directory($directory, '!' . (!empty($langcode) ? '\.' . preg_quote($langcode, '!') : '') . '\.po$!', array('recurse' => FALSE));
}
/**
* Build a locale batch from an array of files.
*
@ -297,8 +327,12 @@ function locale_translate_batch_import($filepath, &$context) {
// The filename is either {langcode}.po or {prefix}.{langcode}.po, so
// we can extract the language code to use for the import from the end.
if (preg_match('!(/|\.)([^\./]+)\.po$!', $filepath, $langcode)) {
$file = entity_create('file', array('filename' => drupal_basename($filepath), 'uri' => $filepath));
_locale_import_read_po('db-store', $file, array(), $langcode[2]);
$file = locale_translate_file_create($filepath, $langcode[2]);
$success = _locale_import_read_po('db-store', $file, array(), $langcode[2]);
if ($success == NULL) {
$file->langcode = $langcode[2];
locale_translate_update_file_history($file);
}
$context['results'][] = $filepath;
}
}
@ -311,3 +345,66 @@ function locale_translate_batch_finished($success, $results) {
drupal_set_message(format_plural(count($results), 'One translation file imported.', '@count translation files imported.'));
}
}
/**
* Creates a file object and populates the timestamp property.
*
* @param $filepath
* The filepath of a file to import.
*
* @return
* An object representing the file.
*/
function locale_translate_file_create($filepath) {
$file = new stdClass();
$file->filename = drupal_basename($filepath);
$file->uri = $filepath;
$file->timestamp = filemtime($file->uri);
return $file;
}
/**
* Update the {locale_file} table.
*
* @param $file
* Object representing the file just imported.
*
* @return integer
* FALSE on failure. Otherwise SAVED_NEW or SAVED_UPDATED.
*
* @see drupal_write_record()
*/
function locale_translate_update_file_history($file) {
// Update or write new record.
if (db_query("SELECT uri FROM {locale_file} WHERE uri = :uri AND langcode = :langcode", array(':uri' => $file->uri, ':langcode' => $file->langcode))->fetchField()) {
$update = array('uri', 'langcode');
}
else {
$update = array();
}
return drupal_write_record('locale_file', $file, $update);
}
/**
* Deletes all interface translation files depending on the langcode.
*
* @param $langcode
* A langcode or NULL. Pass NULL to delete all interface translation files.
*/
function locale_translate_delete_translation_files($langcode) {
$files = locale_translate_get_interface_translation_files($langcode);
if (!empty($files)) {
foreach ($files as $file) {
$success = file_unmanaged_delete($file->uri);
if (!$success) {
return FALSE;
}
// Remove the registered translation file if any.
db_delete('locale_file')
->condition('langcode', $langcode)
->coddition('uri', $file->uri)
->execute();
}
}
return TRUE;
}

View File

@ -126,6 +126,39 @@ function locale_schema() {
),
);
$schema['locale_file'] = array(
'description' => 'File import status information for interface translation files.',
'fields' => array(
'langcode' => array(
'description' => 'Reference to the {languages}.langcode for this translation.',
'type' => 'varchar',
'length' => '12',
'not null' => TRUE,
),
'filename' => array(
'description' => 'Filename for importing the file.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'uri' => array(
'description' => 'File system path for importing the file.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'timestamp' => array(
'description' => 'Unix timestamp of the file itself from the point when it was last imported.',
'type' => 'int',
'not null' => FALSE,
'default' => 0,
),
),
'primary key' => array('uri', 'langcode'),
);
return $schema;
}
@ -550,6 +583,45 @@ function locale_update_8009() {
}
}
/**
* Add {locale_file} table.
*/
function locale_update_8010() {
$table = array(
'description' => 'File import status information for interface translation files.',
'fields' => array(
'langcode' => array(
'description' => 'Reference to the {languages}.langcode for this translation.',
'type' => 'varchar',
'length' => '12',
'not null' => TRUE,
),
'filename' => array(
'description' => 'Filename for importing the file.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'uri' => array(
'description' => 'File system path for importing the file.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
'default' => '',
),
'timestamp' => array(
'description' => 'Unix timestamp of the file itself from the point when it was last imported.',
'type' => 'int',
'not null' => FALSE,
'default' => 0,
),
),
'primary key' => array('uri', 'langcode'),
);
db_create_table('locale_file', $table);
}
/**
* @} End of "addtogroup updates-7.x-to-8.x".
* The next series of updates should start at 9000.

View File

@ -200,6 +200,10 @@ function locale_language_delete($language) {
->condition('language', $language->langcode)
->execute();
// Remove interface translation files.
module_load_include('inc', 'locale', 'locale.bulk');
locale_translate_delete_translation_files($language->langcode);
_locale_invalidate_js($language->langcode);
// Changing the language settings impacts the interface:

View File

@ -0,0 +1,28 @@
msgid ""
msgstr ""
"Project-Id-Version: Drupal 7\\n"
"MIME-Version: 1.0\\n"
"Content-Type: text/plain; charset=UTF-8\\n"
"Content-Transfer-Encoding: 8bit\\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\\n"
msgid "Monday"
msgstr "Montag"
msgid "Tuesday"
msgstr "Dienstag"
msgid "Wednesday"
msgstr "Mittwoch"
msgid "Thursday"
msgstr "Donnerstag"
msgid "Friday"
msgstr "Freitag"
msgid "Saturday"
msgstr "Samstag"
msgid "Sunday"
msgstr "Sonntag"