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