Commit aa9dd8ff authored by webchick's avatar webchick

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

Issue #1635084 by webflo, vasi1186: Added Track import status of files in the locale .po file directory.
parent 2103890d
<?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);
}
}
......@@ -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;
}
......@@ -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.
......
......@@ -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:
......
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"
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