summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/includes/update.inc54
-rw-r--r--core/modules/locale/lib/Drupal/locale/LocaleLookup.php4
-rw-r--r--core/modules/locale/lib/Drupal/locale/PoDatabaseWriter.php8
-rw-r--r--core/modules/locale/lib/Drupal/locale/StringBase.php33
-rw-r--r--core/modules/locale/lib/Drupal/locale/StringDatabaseStorage.php109
-rw-r--r--core/modules/locale/lib/Drupal/locale/StringInterface.php48
-rw-r--r--core/modules/locale/lib/Drupal/locale/StringStorageInterface.php32
-rw-r--r--core/modules/locale/lib/Drupal/locale/Tests/LocaleJavascriptTranslation.php9
-rw-r--r--core/modules/locale/lib/Drupal/locale/Tests/LocaleStringTest.php3
-rw-r--r--core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php6
-rw-r--r--core/modules/locale/locale.bulk.inc25
-rw-r--r--core/modules/locale/locale.install63
-rw-r--r--core/modules/locale/locale.module63
-rw-r--r--core/modules/locale/locale.pages.inc34
14 files changed, 396 insertions, 95 deletions
diff --git a/core/includes/update.inc b/core/includes/update.inc
index fe8034c..acdf83e 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -412,6 +412,60 @@ function update_prepare_d8_language() {
);
db_add_field('locales_target', 'customized', $spec);
}
+ // Add locales_location table to track string locations.
+ // When updating in a non-English language, this table is used for
+ // refreshing JavaScript translations.
+ if (db_table_exists('locales_source') && !db_table_exists('locales_location')) {
+ $table = array(
+ 'description' => 'Location information for source strings.',
+ 'fields' => array(
+ 'lid' => array(
+ 'type' => 'serial',
+ 'not null' => TRUE,
+ 'description' => 'Unique identifier of this location.',
+ ),
+ 'sid' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'description' => 'Unique identifier of this string.',
+ ),
+ 'type' => array(
+ 'type' => 'varchar',
+ 'length' => 50,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'The location type (file, config, path, etc).',
+ ),
+ 'name' => array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'Type dependent location information (file name, path, etc).',
+ ),
+ 'version' => array(
+ 'type' => 'varchar',
+ 'length' => 20,
+ 'not null' => TRUE,
+ 'default' => 'none',
+ 'description' => 'Version of Drupal where the location was found.',
+ ),
+ ),
+ 'primary key' => array('lid'),
+ 'foreign keys' => array(
+ 'locales_source' => array(
+ 'table' => 'locales_source',
+ 'columns' => array('sid' => 'lid'),
+ ),
+ ),
+ 'indexes' => array(
+ 'string_id' => array('sid'),
+ 'string_type' => array('sid', 'type'),
+ ),
+ );
+
+ db_create_table('locales_location', $table);
+ }
}
}
diff --git a/core/modules/locale/lib/Drupal/locale/LocaleLookup.php b/core/modules/locale/lib/Drupal/locale/LocaleLookup.php
index cd2f9c0..9dd04f6 100644
--- a/core/modules/locale/lib/Drupal/locale/LocaleLookup.php
+++ b/core/modules/locale/lib/Drupal/locale/LocaleLookup.php
@@ -61,7 +61,6 @@ class LocaleLookup extends CacheArray {
));
if ($translation) {
- $this->stringStorage->checkVersion($translation, VERSION);
$value = !empty($translation->translation) ? $translation->translation : TRUE;
}
else {
@@ -70,9 +69,8 @@ class LocaleLookup extends CacheArray {
$this->stringStorage->createString(array(
'source' => $offset,
'context' => $this->context,
- 'location' => request_uri(),
'version' => VERSION
- ))->save();
+ ))->addLocation('path', request_uri())->save();
$value = TRUE;
}
$this->storage[$offset] = $value;
diff --git a/core/modules/locale/lib/Drupal/locale/PoDatabaseWriter.php b/core/modules/locale/lib/Drupal/locale/PoDatabaseWriter.php
index 7afa1db..b5b03c0 100644
--- a/core/modules/locale/lib/Drupal/locale/PoDatabaseWriter.php
+++ b/core/modules/locale/lib/Drupal/locale/PoDatabaseWriter.php
@@ -102,6 +102,7 @@ class PoDatabaseWriter implements PoWriterInterface {
'updates' => 0,
'deletes' => 0,
'skips' => 0,
+ 'strings' => array(),
);
$this->_report = $report;
}
@@ -226,13 +227,13 @@ class PoDatabaseWriter implements PoWriterInterface {
$source = $item->getSource();
$translation = $item->getTranslation();
-
// Look up the source string and any existing translation.
- $string = locale_storage()->findTranslation(array(
+ $strings = locale_storage()->getTranslations(array(
'language' => $this->_langcode,
'source' => $source,
'context' => $context
));
+ $string = reset($strings);
if (!empty($translation)) {
// Skip this string unless it passes a check for dangerous code.
@@ -258,6 +259,7 @@ class PoDatabaseWriter implements PoWriterInterface {
$string->save();
$this->_report['updates']++;
}
+ $this->_report['strings'][] = $string->getId();
return $string->lid;
}
else {
@@ -272,6 +274,7 @@ class PoDatabaseWriter implements PoWriterInterface {
))->save();
$this->_report['additions']++;
+ $this->_report['strings'][] = $string->getId();
return $string->lid;
}
}
@@ -279,6 +282,7 @@ class PoDatabaseWriter implements PoWriterInterface {
// Empty translation, remove existing if instructed.
$string->delete();
$this->_report['deletes']++;
+ $this->_report['strings'][] = $string->lid;
return $string->lid;
}
}
diff --git a/core/modules/locale/lib/Drupal/locale/StringBase.php b/core/modules/locale/lib/Drupal/locale/StringBase.php
index 8ff9815..e2d9bcc 100644
--- a/core/modules/locale/lib/Drupal/locale/StringBase.php
+++ b/core/modules/locale/lib/Drupal/locale/StringBase.php
@@ -22,11 +22,11 @@ abstract class StringBase implements StringInterface {
public $lid;
/**
- * The string location.
+ * The string locations indexed by type.
*
* @var string
*/
- public $location;
+ public $locations;
/**
* The source string.
@@ -152,6 +152,35 @@ abstract class StringBase implements StringInterface {
}
/**
+ * Implements Drupal\locale\StringInterface::getLocation().
+ */
+ public function getLocations($check_only = FALSE) {
+ if (!isset($this->locations) && !$check_only) {
+ $this->locations = array();
+ foreach ($this->getStorage()->getLocations(array('sid' => $this->getId())) as $location) {
+ $this->locations[$location->type][$location->name] = $location->lid;
+ }
+ }
+ return isset($this->locations) ? $this->locations : array();
+ }
+
+ /**
+ * Implements Drupal\locale\StringInterface::addLocation().
+ */
+ public function addLocation($type, $name) {
+ $this->locations[$type][$name] = TRUE;
+ return $this;
+ }
+
+ /**
+ * Implements Drupal\locale\StringInterface::hasLocation().
+ */
+ public function hasLocation($type, $name) {
+ $locations = $this->getLocations();
+ return isset($locations[$type]) ? !empty($locations[$type][$name]) : FALSE;
+ }
+
+ /**
* Implements Drupal\locale\LocaleString::save().
*/
public function save() {
diff --git a/core/modules/locale/lib/Drupal/locale/StringDatabaseStorage.php b/core/modules/locale/lib/Drupal/locale/StringDatabaseStorage.php
index 38e9df5..33138e7 100644
--- a/core/modules/locale/lib/Drupal/locale/StringDatabaseStorage.php
+++ b/core/modules/locale/lib/Drupal/locale/StringDatabaseStorage.php
@@ -80,12 +80,25 @@ class StringDatabaseStorage implements StringStorageInterface {
->execute()
->fetchObject('Drupal\locale\TranslationString');
if ($string) {
+ $this->checkVersion($string, VERSION);
$string->setStorage($this);
}
return $string;
}
/**
+ * Implements Drupal\locale\StringStorageInterface::getLocations().
+ */
+ function getLocations(array $conditions = array()) {
+ $query = $this->connection->select('locales_location', 'l', $this->options)
+ ->fields('l');
+ foreach ($conditions as $field => $value) {
+ $query->condition('l.' . $field, $value);
+ }
+ return $query->execute()->fetchAll();
+ }
+
+ /**
* Implements Drupal\locale\StringStorageInterface::countStrings().
*/
public function countStrings() {
@@ -100,19 +113,6 @@ class StringDatabaseStorage implements StringStorageInterface {
}
/**
- * Implements Drupal\locale\StringStorageInterface::checkVersion().
- */
- public function checkVersion($string, $version) {
- if ($string->getId() && $string->getVersion() != $version) {
- $string->setVersion($version);
- $this->connection->update('locales_source', $this->options)
- ->condition('lid', $string->getId())
- ->fields(array('version' => $version))
- ->execute();
- }
- }
-
- /**
* Implements Drupal\locale\StringStorageInterface::save().
*/
public function save($string) {
@@ -127,10 +127,63 @@ class StringDatabaseStorage implements StringStorageInterface {
else {
$this->dbStringUpdate($string);
}
+ // Update locations if they come with the string.
+ $this->updateLocation($string);
return $this;
}
/**
+ * Update locations for string.
+ *
+ * @param Drupal\locale\StringInterface $string
+ * The string object.
+ */
+ protected function updateLocation($string) {
+ if ($locations = $string->getLocations(TRUE)) {
+ $created = FALSE;
+ foreach ($locations as $type => $location) {
+ foreach ($location as $name => $lid) {
+ if (!$lid) {
+ $this->dbDelete('locales_location', array('sid' => $string->getId(), 'type' => $type, 'name' => $name))
+ ->execute();
+ }
+ elseif ($lid === TRUE) {
+ // This is a new location to add, take care not to duplicate.
+ $this->connection->merge('locales_location', $this->options)
+ ->key(array('sid' => $string->getId(), 'type' => $type, 'name' => $name))
+ ->fields(array('version' => VERSION))
+ ->execute();
+ $created = TRUE;
+ }
+ // Loaded locations have 'lid' integer value, nor FALSE, nor TRUE.
+ }
+ }
+ if ($created) {
+ // As we've set a new location, check string version too.
+ $this->checkVersion($string, VERSION);
+ }
+ }
+ }
+
+ /**
+ * Checks whether the string version matches a given version, fix it if not.
+ *
+ * @param Drupal\locale\StringInterface $string
+ * The string object.
+ * @param string $version
+ * Drupal version to check against.
+ */
+ protected function checkVersion($string, $version) {
+ if ($string->getId() && $string->getVersion() != $version) {
+ $string->setVersion($version);
+ $this->connection->update('locales_source', $this->options)
+ ->condition('lid', $string->getId())
+ ->fields(array('version' => $version))
+ ->execute();
+ }
+ }
+
+ /**
* Implements Drupal\locale\StringStorageInterface::delete().
*/
public function delete($string) {
@@ -138,6 +191,7 @@ class StringDatabaseStorage implements StringStorageInterface {
$this->dbDelete('locales_target', $keys)->execute();
if ($string->isSource()) {
$this->dbDelete('locales_source', $keys)->execute();
+ $this->dbDelete('locales_location', $keys)->execute();
$string->setId(NULL);
}
}
@@ -157,6 +211,7 @@ class StringDatabaseStorage implements StringStorageInterface {
if ($lids) {
$this->dbDelete('locales_target', array('lid' => $lids))->execute();
$this->dbDelete('locales_source', array('lid' => $lids))->execute();
+ $this->dbDelete('locales_location', array('sid' => $lids))->execute();
}
}
@@ -191,11 +246,19 @@ class StringDatabaseStorage implements StringStorageInterface {
* Field name to find the table alias for.
*
* @return string
- * Either 's' or 't' depending on whether the field belongs to source or
- * target table.
+ * Either 's', 't' or 'l' depending on whether the field belongs to source,
+ * target or location table table.
*/
protected function dbFieldTable($field) {
- return in_array($field, array('language', 'translation', 'customized')) ? 't' : 's';
+ if (in_array($field, array('language', 'translation', 'customized'))) {
+ return 't';
+ }
+ elseif (in_array($field, array('type', 'name'))) {
+ return 'l';
+ }
+ else {
+ return 's';
+ }
}
/**
@@ -367,6 +430,20 @@ class StringDatabaseStorage implements StringStorageInterface {
}
}
+ // If we have conditions for location's type or name, then we need the
+ // location table, for which we add a subquery.
+ if (isset($conditions['type']) || isset($conditions['name'])) {
+ $subquery = $this->connection->select('locales_location', 'l', $this->options)
+ ->fields('l', array('sid'));
+ foreach (array('type', 'name') as $field) {
+ if (isset($conditions[$field])) {
+ $subquery->condition('l.' . $field, $conditions[$field]);
+ unset($conditions[$field]);
+ }
+ }
+ $query->condition('s.lid', $subquery, 'IN');
+ }
+
// Add conditions for both tables.
foreach ($conditions as $field => $value) {
$table_alias = $this->dbFieldTable($field);
diff --git a/core/modules/locale/lib/Drupal/locale/StringInterface.php b/core/modules/locale/lib/Drupal/locale/StringInterface.php
index ec04386..05e3c01 100644
--- a/core/modules/locale/lib/Drupal/locale/StringInterface.php
+++ b/core/modules/locale/lib/Drupal/locale/StringInterface.php
@@ -158,6 +158,54 @@ interface StringInterface {
public function getValues(array $fields);
/**
+ * Gets location information for this string.
+ *
+ * Locations are arbitrary pairs of type and name strings, used to store
+ * information about the origins of the string, like the file name it
+ * was found on, the path on which it was discovered, etc...
+ *
+ * A string can have any number of locations since the same string may be
+ * found on different places of Drupal code and configuration.
+ *
+ * @param bool $check_only
+ * (optional) Set to TRUE to get only new locations added during the
+ * current page request and not loading all existing locations.
+ *
+ * @return array
+ * Location ids indexed by type and name.
+ */
+ public function getLocations($check_only = FALSE);
+
+ /**
+ * Adds a location for this string.
+ *
+ * @param string $type
+ * Location type that may be any arbitrary string. Types used in Drupal
+ * core are: 'javascript', 'path', 'code', 'configuration'.
+ * @param string $name
+ * Location name. Drupal path in case of online discovered translations,
+ * file path in case of imported strings, configuration name for strings
+ * that come from configuration, etc...
+ *
+ * @return Drupal\locale\LocaleString
+ * The called object.
+ */
+ public function addLocation($type, $name);
+
+ /**
+ * Checks whether the string has a given location.
+ *
+ * @param string $type.
+ * Location type.
+ * @param string $name.
+ * Location name.
+ *
+ * @return bool
+ * TRUE if the string has a location with this type and name.
+ */
+ public function hasLocation($type, $name);
+
+ /**
* Saves string object to storage.
*
* @return Drupal\locale\LocaleString
diff --git a/core/modules/locale/lib/Drupal/locale/StringStorageInterface.php b/core/modules/locale/lib/Drupal/locale/StringStorageInterface.php
index bdfd5fa..d02774f 100644
--- a/core/modules/locale/lib/Drupal/locale/StringStorageInterface.php
+++ b/core/modules/locale/lib/Drupal/locale/StringStorageInterface.php
@@ -50,6 +50,24 @@ interface StringStorageInterface {
* Array of Drupal\locale\StringInterface objects matching the conditions.
*/
public function getTranslations(array $conditions = array(), array $options = array());
+
+ /**
+ * Loads string location information.
+ *
+ * @see Drupal\locale\StringStorageInterface::getStrings()
+ *
+ * @param array $conditions
+ * (optional) Array with conditions to filter the locations that may be any
+ * of the follwing elements:
+ * - 'sid', The tring identifier.
+ * - 'type', The location type.
+ * - 'name', The location name.
+ *
+ * @return array
+ * Array of location objects matching the conditions.
+ */
+ public function getLocations(array $conditions = array());
+
/**
* Loads a string source object, fast query.
*
@@ -69,6 +87,10 @@ interface StringStorageInterface {
/**
* Loads a string translation object, fast query.
*
+ * This function must only be used when actually translating strings as it
+ * will have the effect of updating the string version. For other purposes
+ * the getTranslations() method should be used instead.
+ *
* @param array $conditions
* (optional) Array with conditions that will be used to filter the strings
* returned and may include all of the conditions defined by getStrings().
@@ -79,16 +101,6 @@ interface StringStorageInterface {
public function findTranslation(array $conditions);
/**
- * Checks whether the string version matches a given version, fix it if not.
- *
- * @param Drupal\locale\StringInterface $string
- * The string object.
- * @param string $version
- * Drupal version to check against.
- */
- public function checkVersion($string, $version);
-
- /**
* Save string object to storage.
*
* @param Drupal\locale\StringInterface $string
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleJavascriptTranslation.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleJavascriptTranslation.php
index 8962267..d8e028f 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleJavascriptTranslation.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleJavascriptTranslation.php
@@ -37,12 +37,9 @@ class LocaleJavascriptTranslation extends WebTestBase {
_locale_parse_js_file($filename);
// Get all of the source strings that were found.
- $source_strings = db_select('locales_source', 's')
- ->fields('s', array('source', 'context'))
- ->condition('s.location', $filename)
- ->execute()
- ->fetchAllKeyed();
-
+ foreach (locale_storage()->getStrings(array('type' => 'javascript', 'name' => $filename)) as $string) {
+ $source_strings[$string->source] = $string->context;
+ }
// List of all strings that should be in the file.
$test_strings = array(
"Standard Call t" => '',
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleStringTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleStringTest.php
index 3c9e739..5dd4e23 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleStringTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleStringTest.php
@@ -72,8 +72,7 @@ class LocaleStringTest extends WebTestBase {
// Check version handling and updating.
$this->assertEqual($source->version, 'none', 'String originally created without version.');
- $this->storage->checkVersion($source, VERSION);
- $string = $this->storage->findString(array('lid' => $source->lid));
+ $string = $this->storage->findTranslation(array('lid' => $source->lid));
$this->assertEqual($string->version, VERSION, 'Checked and updated string version to Drupal version.');
// Create translation and find it by lid and source.
diff --git a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
index 3476db7..0dc3948 100644
--- a/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
+++ b/core/modules/locale/lib/Drupal/locale/Tests/LocaleUninstallTest.php
@@ -70,9 +70,9 @@ class LocaleUninstallTest extends WebTestBase {
$user = $this->drupalCreateUser(array('translate interface', 'access administration pages'));
$this->drupalLogin($user);
$this->drupalGet('admin/config/regional/translate/translate');
- $string = db_query('SELECT min(lid) AS lid, source FROM {locales_source} WHERE location LIKE :location', array(
- ':location' => '%.js%',
- ))->fetchObject();
+ // Get any of the javascript strings to translate.
+ $js_strings = locale_storage()->getStrings(array('type' => 'javascript'));
+ $string = reset($js_strings);
$edit = array('string' => $string->source);
$this->drupalPost('admin/config/regional/translate', $edit, t('Filter'));
$edit = array('strings[' . $string->lid . '][translations][0]' => 'french translation');
diff --git a/core/modules/locale/locale.bulk.inc b/core/modules/locale/locale.bulk.inc
index b7850db..0be2aec 100644
--- a/core/modules/locale/locale.bulk.inc
+++ b/core/modules/locale/locale.bulk.inc
@@ -492,17 +492,20 @@ function locale_translate_batch_import($filepath, $options, &$context) {
$file->timestamp = filemtime($file->uri);
locale_translate_update_file_history($file);
$context['results']['files'][$filepath] = $filepath;
+ $context['results']['languages'][$filepath] = $file->langcode;
}
// Add the values from the report to the stats for this file.
if (!isset($context['results']['stats']) || !isset($context['results']['stats'][$filepath])) {
$context['results']['stats'][$filepath] = array();
}
foreach ($report as $key => $value) {
- if (is_numeric($report[$key])) {
- if (!isset($context['results']['stats'][$filepath][$key])) {
- $context['results']['stats'][$filepath][$key] = 0;
- }
- $context['results']['stats'][$filepath][$key] += $report[$key];
+ if (is_numeric($value)) {
+ $context['results']['stats'][$filepath] += array($key => 0);
+ $context['results']['stats'][$filepath][$key] += $value;
+ }
+ elseif (is_array($value)) {
+ $context['results']['stats'][$filepath] += array($key => array());
+ $context['results']['stats'][$filepath][$key] = array_merge($context['results']['stats'][$filepath][$key], $value);
}
}
}
@@ -519,6 +522,7 @@ function locale_translate_batch_import($filepath, $options, &$context) {
function locale_translate_batch_finished($success, $results) {
if ($success) {
$additions = $updates = $deletes = $skips = 0;
+ $strings = $langcodes = array();
drupal_set_message(format_plural(count($results['files']), 'One translation file imported.', '@count translation files imported.'));
$skipped_files = array();
// If there are no results and/or no stats (eg. coping with an empty .po
@@ -532,7 +536,11 @@ function locale_translate_batch_finished($success, $results) {
if ($report['skips'] > 0) {
$skipped_files[] = $filepath;
}
+ $strings = array_merge($strings, $report['strings']);
}
+ // Get list of unique string identifiers and language codes updated.
+ $strings = array_unique($strings);
+ $langcodes = array_unique(array_values($results['languages']));
}
drupal_set_message(t('The translation was successfully imported. There are %number newly created translated strings, %update strings were updated and %delete strings were removed.', array('%number' => $additions, '%update' => $updates, '%delete' => $deletes)));
watchdog('locale', 'The translation was succesfully imported. %number new strings added, %update updated and %delete removed.', array('%number' => $additions, '%update' => $updates, '%delete' => $deletes));
@@ -547,9 +555,10 @@ function locale_translate_batch_finished($success, $results) {
watchdog('locale', '@count disallowed HTML string(s) in files: @files.', array('@count' => $skips, '@files' => implode(',', $skipped_files)), WATCHDOG_WARNING);
}
- // Clear cache and force refresh of JavaScript translations.
- _locale_invalidate_js();
- cache()->invalidateTags(array('locale' => TRUE));
+ if ($strings) {
+ // Clear cache and force refresh of JavaScript translations.
+ _locale_refresh_translations($langcodes, $strings);
+ }
}
}
diff --git a/core/modules/locale/locale.install b/core/modules/locale/locale.install
index b470963..1e8a3e8 100644
--- a/core/modules/locale/locale.install
+++ b/core/modules/locale/locale.install
@@ -52,12 +52,6 @@ function locale_schema() {
'not null' => TRUE,
'description' => 'Unique identifier of this string.',
),
- 'location' => array(
- 'type' => 'text',
- 'not null' => FALSE,
- 'size' => 'big',
- 'description' => 'Drupal path in case of online discovered translations or file path in case of imported strings.',
- ),
'source' => array(
'type' => 'text',
'mysql_type' => 'blob',
@@ -76,7 +70,7 @@ function locale_schema() {
'length' => 20,
'not null' => TRUE,
'default' => 'none',
- 'description' => 'Version of Drupal, where the string was last used (for locales optimization).',
+ 'description' => 'Version of Drupal where the string was last used (for locales optimization).',
),
),
'primary key' => array('lid'),
@@ -126,6 +120,54 @@ function locale_schema() {
),
);
+ $schema['locales_location'] = array(
+ 'description' => 'Location information for source strings.',
+ 'fields' => array(
+ 'lid' => array(
+ 'type' => 'serial',
+ 'not null' => TRUE,
+ 'description' => 'Unique identifier of this location.',
+ ),
+ 'sid' => array(
+ 'type' => 'int',
+ 'not null' => TRUE,
+ 'description' => 'Unique identifier of this string.',
+ ),
+ 'type' => array(
+ 'type' => 'varchar',
+ 'length' => 50,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'The location type (file, config, path, etc).',
+ ),
+ 'name' => array(
+ 'type' => 'varchar',
+ 'length' => 255,
+ 'not null' => TRUE,
+ 'default' => '',
+ 'description' => 'Type dependent location information (file name, path, etc).',
+ ),
+ 'version' => array(
+ 'type' => 'varchar',
+ 'length' => 20,
+ 'not null' => TRUE,
+ 'default' => 'none',
+ 'description' => 'Version of Drupal where the location was found.',
+ ),
+ ),
+ 'primary key' => array('lid'),
+ 'foreign keys' => array(
+ 'locales_source' => array(
+ 'table' => 'locales_source',
+ 'columns' => array('sid' => 'lid'),
+ ),
+ ),
+ 'indexes' => array(
+ 'string_id' => array('sid'),
+ 'string_type' => array('sid', 'type'),
+ ),
+ );
+
$schema['locale_file'] = array(
'description' => 'File import status information for interface translation files.',
'fields' => array(
@@ -741,6 +783,13 @@ function locale_update_8013() {
}
/**
+ * Drop old 'location' field.
+ */
+function locale_update_8014() {
+ db_drop_field('locales_source', 'location');
+}
+
+/**
* @} End of "addtogroup updates-7.x-to-8.x".
* The next series of updates should start at 9000.
*/
diff --git a/core/modules/locale/locale.module b/core/modules/locale/locale.module
index 3d3ce1f..3ebe97d 100644
--- a/core/modules/locale/locale.module
+++ b/core/modules/locale/locale.module
@@ -771,8 +771,37 @@ function locale_string_is_safe($string) {
}
/**
+ * Refresh related information after string translations have been updated.
+ *
+ * The information that will be refreshed includes:
+ * - JavaScript translations.
+ * - Locale cache.
+ *
+ * @param array $langcodes
+ * Language codes for updated translations.
+ * @param array $lids
+ * List of string identifiers that have been updated / created.
+ */
+function _locale_refresh_translations($langcodes, $lids) {
+ if ($lids && $langcodes) {
+ // Update javascript translations if any of the strings has a javascript location.
+ if ($strings = locale_storage()->getStrings(array('lid' => $lids, 'type' => 'javascript'))) {
+ array_map('_locale_invalidate_js', $langcodes);
+ }
+ }
+ // Clear locale cache.
+ cache()->invalidateTags(array('locale' => TRUE));
+}
+
+/**
* Parses a JavaScript file, extracts strings wrapped in Drupal.t() and
* Drupal.formatPlural() and inserts them into the database.
+ *
+ * @param string $filepath
+ * File name to parse.
+ *
+ * @return array
+ * Array of string objects to update indexed by context and source.
*/
function _locale_parse_js_file($filepath) {
// The file path might contain a query string, so make sure we only use the
@@ -858,28 +887,17 @@ function _locale_parse_js_file($filepath) {
$context = implode('', preg_split('~(?<!\\\\)[\'"]\s*\+\s*[\'"]~s', substr($match['context'], 1, -1)));
$source = locale_storage()->findString(array('source' => $string, 'context' => $context));
- if ($source) {
- // We already have this source string and now have to add the location
- // to the location column, if this file is not yet present in there.
- $locations = preg_split('~\s*;\s*~', $source->location);
-
- if (!in_array($filepath, $locations)) {
- $locations[] = $filepath;
- $locations = implode('; ', $locations);
-
- // Save the new locations string to the database.
- $source->setValues(array('location' => $locations))
- ->save();
- }
- }
- else {
+
+ if (!$source) {
// We don't have the source string yet, thus we insert it into the database.
- locale_storage()->createString(array(
- 'location' => $filepath,
+ $source = locale_storage()->createString(array(
'source' => $string,
'context' => $context,
- ))->save();
+ ));
}
+ // Besides adding the location this will tag it for current version.
+ $source->addLocation('javascript', $filepath);
+ $source->save();
}
}
@@ -934,10 +952,13 @@ function _locale_rebuild_js($langcode = NULL) {
// Construct the array for JavaScript translations.
// Only add strings with a translation to the translations array.
- $options['filters']['location'] = '.js';
- $conditions['language'] = $language->langcode;
+ $conditions = array(
+ 'type' => 'javascript',
+ 'language' => $language->langcode,
+ 'translated' => TRUE,
+ );
$translations = array();
- foreach (locale_storage()->getTranslations($conditions, $options) as $data) {
+ foreach (locale_storage()->getTranslations($conditions) as $data) {
$translations[$data->context][$data->source] = $data->translation;
}
diff --git a/core/modules/locale/locale.pages.inc b/core/modules/locale/locale.pages.inc
index 71aa14d..8ea8780 100644
--- a/core/modules/locale/locale.pages.inc
+++ b/core/modules/locale/locale.pages.inc
@@ -324,11 +324,6 @@ function locale_translate_edit_form($form, &$form_state) {
'#value' => check_plain($string->context),
);
}
- $form['strings'][$string->lid]['location'] = array(
- '#type' => 'value',
- '#value' => $string->location,
- );
-
// Approximate the number of rows to use in the default textarea.
$rows = min(ceil(str_word_count($source_array[0]) / 12), 10);
if (empty($form['strings'][$string->lid]['plural']['#value'])) {
@@ -403,10 +398,16 @@ function locale_translate_edit_form_validate($form, &$form_state) {
*/
function locale_translate_edit_form_submit($form, &$form_state) {
$langcode = $form_state['values']['langcode'];
- foreach ($form_state['values']['strings'] as $lid => $translations) {
- // Get target string, that may be NULL if there's no translation.
- $target = locale_storage()->findTranslation(array('language' => $langcode, 'lid' => $lid));
+ $updated = array();
+
+ // Preload all translations for strings in the form.
+ $lids = array_keys($form_state['values']['strings']);
+ $strings = array();
+ foreach (locale_storage()->getTranslations(array('lid' => $lids, 'language' => $langcode, 'translated' => TRUE)) as $string) {
+ $strings[$string->lid] = $string;
+ }
+ foreach ($form_state['values']['strings'] as $lid => $translations) {
// No translation when all strings are empty.
$has_translation = FALSE;
foreach ($translations['translations'] as $string) {
@@ -417,14 +418,16 @@ function locale_translate_edit_form_submit($form, &$form_state) {
}
if ($has_translation) {
// Only update or insert if we have a value to use.
- $target = $target && !$target->isNew() ? $target : locale_storage()->createTranslation(array('lid' => $lid, 'language' => $langcode));
+ $target = isset($strings[$lid]) ? $strings[$lid] : locale_storage()->createTranslation(array('lid' => $lid, 'language' => $langcode));
$target->setPlurals($translations['translations'])
->setCustomized()
->save();
+ $updated[] = $target->getId();
}
- elseif ($target) {
+ elseif (isset($strings[$lid])) {
// Empty translation entered: remove existing entry from database.
- $target->delete();
+ $strings[$lid]->delete();
+ $updated[] = $lid;
}
}
@@ -435,10 +438,11 @@ function locale_translate_edit_form_submit($form, &$form_state) {
$form_state['redirect'] = array('admin/config/regional/translate', array('query' => array('page' => $_GET['page'])));
}
- // Force JavaScript translation file recreation for this language.
- _locale_invalidate_js($langcode);
- // Clear locale cache.
- cache()->invalidateTags(array('locale' => TRUE));
+ if ($updated) {
+ // Clear cache and force refresh of JavaScript translations.
+ _locale_refresh_translations(array($langcode), $updated);
+ }
+
}
/**