Commit 7f6f4678 authored by webchick's avatar webchick

Issue #1080964 by catch, beejeebus, Steven Jones, drewish: Be more sparing...

Issue #1080964 by catch, beejeebus, Steven Jones, drewish: Be more sparing with locale cache clears.
parent 82f095ad
<?php
/**
* @file
* Definition of LocaleLookup
*/
namespace Drupal\locale;
use Drupal\Core\Utility\CacheArray;
/**
* Extends CacheArray to allow for dynamic building of the locale cache.
*/
class LocaleLookup extends CacheArray {
/**
* A language code.
* @var string
*/
protected $langcode;
/**
* The msgctxt context.
* @var string
*/
protected $context;
/**
* Constructs a LocaleCache object.
*/
public function __construct($langcode, $context) {
$this->langcode = $langcode;
$this->context = (string) $context;
// Add the current user's role IDs to the cache key, this ensures that, for
// example, strings for admin menu items and settings forms are not cached
// for anonymous users.
$rids = implode(':', array_keys($GLOBALS['user']->roles));
parent::__construct("locale:$langcode:$context:$rids", 'cache');
}
/**
* Overrides DrupalCacheArray::resolveCacheMiss().
*/
protected function resolveCacheMiss($offset) {
$translation = db_query("SELECT s.lid, t.translation, s.version FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.source = :source AND s.context = :context", array(
':language' => $this->langcode,
':source' => $offset,
':context' => $this->context,
))->fetchObject();
if ($translation) {
if ($translation->version != VERSION) {
// This is the first use of this string under current Drupal version.
// Update the {locales_source} table to indicate the string is current.
db_update('locales_source')
->fields(array('version' => VERSION))
->condition('lid', $translation->lid)
->execute();
}
$value = !empty($translation->translation) ? $translation->translation : TRUE;
}
else {
// We don't have the source string, update the {locales_source} table to
// indicate the string is not translated.
db_merge('locales_source')
->insertFields(array(
'location' => request_uri(),
'version' => VERSION,
))
->key(array(
'source' => $offset,
'context' => $this->context,
))
->execute();
$value = TRUE;
}
$this->storage[$offset] = $value;
// Disabling the usage of string caching allows a module to watch for
// the exact list of strings used on a page. From a performance
// perspective that is a really bad idea, so we have no user
// interface for this. Be careful when turning this option off!
if (variable_get('locale_cache_strings', 1)) {
$this->persist($offset);
}
return $value;
}
}
......@@ -11,6 +11,8 @@
* Gettext portable object files are supported.
*/
use Drupal\locale\LocaleLookup;
/**
* Regular expression pattern used to localize JavaScript strings.
*/
......@@ -406,76 +408,11 @@ function locale($string = NULL, $context = NULL, $langcode = NULL) {
$langcode = isset($langcode) ? $langcode : $language_interface->langcode;
// Store database cached translations in a static variable. Only build the
// cache after $language_interface has been set to avoid an unnecessary cache
// rebuild.
if (!isset($locale_t[$langcode]) && isset($language_interface)) {
$locale_t[$langcode] = array();
// Disabling the usage of string caching allows a module to watch for
// the exact list of strings used on a page. From a performance
// perspective that is a really bad idea, so we have no user
// interface for this. Be careful when turning this option off!
if (variable_get('locale_cache_strings', 1) == 1) {
if ($cache = cache()->get('locale:' . $langcode)) {
$locale_t[$langcode] = $cache->data;
}
elseif (lock_acquire('locale_cache_' . $langcode)) {
// Refresh database stored cache of translations for given language.
// We only store short strings used in current version, to improve
// performance and consume less memory.
$result = db_query("SELECT s.source, s.context, t.translation, t.language FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.version = :version AND LENGTH(s.source) < :length", array(':language' => $langcode, ':version' => VERSION, ':length' => variable_get('locale_cache_length', 75)));
foreach ($result as $data) {
$locale_t[$langcode][$data->context][$data->source] = (empty($data->translation) ? TRUE : $data->translation);
}
cache()->set('locale:' . $langcode, $locale_t[$langcode]);
lock_release('locale_cache_' . $langcode);
}
}
// Strings are cached by langcode, context and roles, using instances of the
// LocaleLookup class to handle string lookup and caching.
if (!isset($locale_t[$langcode][$context]) && isset($language_interface)) {
$locale_t[$langcode][$context] = new LocaleLookup($langcode, $context);
}
// If we have the translation cached, skip checking the database
if (!isset($locale_t[$langcode][$context][$string])) {
// We do not have this translation cached, so get it from the DB.
$translation = db_query("SELECT s.lid, t.translation, s.version FROM {locales_source} s LEFT JOIN {locales_target} t ON s.lid = t.lid AND t.language = :language WHERE s.source = :source AND s.context = :context", array(
':language' => $langcode,
':source' => $string,
':context' => (string) $context,
))->fetchObject();
if ($translation) {
// We have the source string at least.
// Cache translation string or TRUE if no translation exists.
$locale_t[$langcode][$context][$string] = (empty($translation->translation) ? TRUE : $translation->translation);
if ($translation->version != VERSION) {
// This is the first use of this string under current Drupal version. Save version
// and clear cache, to include the string into caching next time. Saved version is
// also a string-history information for later pruning of the tables.
db_update('locales_source')
->fields(array('version' => VERSION))
->condition('lid', $translation->lid)
->execute();
cache()->deletePrefix('locale:');
}
}
else {
// We don't have the source string, cache this as untranslated.
db_merge('locales_source')
->insertFields(array(
'location' => request_uri(),
'version' => VERSION,
))
->key(array(
'source' => $string,
'context' => (string) $context,
))
->execute();
$locale_t[$langcode][$context][$string] = TRUE;
// Clear locale cache so this string can be added in a later request.
cache()->deletePrefix('locale:');
}
}
return ($locale_t[$langcode][$context][$string] === TRUE ? $string : $locale_t[$langcode][$context][$string]);
}
......
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