You are here

class LocaleLookup in Drupal 9

Same name and namespace in other branches
  1. 8 core/modules/locale/src/LocaleLookup.php \Drupal\locale\LocaleLookup

A cache collector to allow for dynamic building of the locale cache.

Hierarchy

Expanded class hierarchy of LocaleLookup

1 file declares its use of LocaleLookup
LocaleLookupTest.php in core/modules/locale/tests/src/Unit/LocaleLookupTest.php

File

core/modules/locale/src/LocaleLookup.php, line 16

Namespace

Drupal\locale
View source
class LocaleLookup extends CacheCollector {

  /**
   * A language code.
   *
   * @var string
   */
  protected $langcode;

  /**
   * The msgctxt context.
   *
   * @var string
   */
  protected $context;

  /**
   * The locale storage.
   *
   * @var \Drupal\locale\StringStorageInterface
   */
  protected $stringStorage;

  /**
   * The cache backend that should be used.
   *
   * @var \Drupal\Core\Cache\CacheBackendInterface
   */
  protected $cache;

  /**
   * The lock backend that should be used.
   *
   * @var \Drupal\Core\Lock\LockBackendInterface
   */
  protected $lock;

  /**
   * The configuration factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $languageManager;

  /**
   * The request stack.
   *
   * @var \Symfony\Component\HttpFoundation\RequestStack
   */
  protected $requestStack;

  /**
   * Constructs a LocaleLookup object.
   *
   * @param string $langcode
   *   The language code.
   * @param string $context
   *   The string context.
   * @param \Drupal\locale\StringStorageInterface $string_storage
   *   The string storage.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache
   *   The cache backend.
   * @param \Drupal\Core\Lock\LockBackendInterface $lock
   *   The lock backend.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The config factory.
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   The language manager.
   * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
   *   The request stack.
   */
  public function __construct($langcode, $context, StringStorageInterface $string_storage, CacheBackendInterface $cache, LockBackendInterface $lock, ConfigFactoryInterface $config_factory, LanguageManagerInterface $language_manager, RequestStack $request_stack) {
    $this->langcode = $langcode;
    $this->context = (string) $context;
    $this->stringStorage = $string_storage;
    $this->configFactory = $config_factory;
    $this->languageManager = $language_manager;
    $this->cache = $cache;
    $this->lock = $lock;
    $this->tags = [
      'locale',
    ];
    $this->requestStack = $request_stack;
  }

  /**
   * {@inheritdoc}
   */
  protected function getCid() {
    if (!isset($this->cid)) {

      // 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.
      $user = \Drupal::currentUser();
      $rids = '';
      if ($user) {
        $roles = $user
          ->getRoles();
        sort($roles);
        $rids = implode(':', $roles);
      }
      $this->cid = "locale:{$this->langcode}:{$this->context}:{$rids}";

      // Getting the roles from the current user might have resulted in t()
      // calls that attempted to get translations from the locale cache. In that
      // case they would not go into this method again as
      // CacheCollector::lazyLoadCache() already set the loaded flag. They would
      // however call resolveCacheMiss() and add that string to the list of
      // cache misses that need to be written into the cache. Prevent that by
      // resetting that list. All that happens in such a case are a few uncached
      // translation lookups.
      $this->keysToPersist = [];
    }
    return $this->cid;
  }

  /**
   * {@inheritdoc}
   */
  protected function resolveCacheMiss($offset) {
    $translation = $this->stringStorage
      ->findTranslation([
      'language' => $this->langcode,
      'source' => $offset,
      'context' => $this->context,
    ]);
    if ($translation) {
      $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.
      $this->stringStorage
        ->createString([
        'source' => $offset,
        'context' => $this->context,
        'version' => \Drupal::VERSION,
      ])
        ->addLocation('path', $this->requestStack
        ->getCurrentRequest()
        ->getRequestUri())
        ->save();
      $value = TRUE;
    }

    // If there is no translation available for the current language then use
    // language fallback to try other translations.
    if ($value === TRUE) {
      $fallbacks = $this->languageManager
        ->getFallbackCandidates([
        'langcode' => $this->langcode,
        'operation' => 'locale_lookup',
        'data' => $offset,
      ]);
      if (!empty($fallbacks)) {
        foreach ($fallbacks as $langcode) {
          $translation = $this->stringStorage
            ->findTranslation([
            'language' => $langcode,
            'source' => $offset,
            'context' => $this->context,
          ]);
          if ($translation && !empty($translation->translation)) {
            $value = $translation->translation;
            break;
          }
        }
      }
    }
    if (is_string($value) && strpos($value, PoItem::DELIMITER) !== FALSE) {

      // Community translations imported from localize.drupal.org as well as
      // migrated translations may contain @count[number].
      $value = preg_replace('!@count\\[\\d+\\]!', '@count', $value);
    }
    $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 ($this->configFactory
      ->get('locale.settings')
      ->get('cache_strings')) {
      $this
        ->persist($offset);
    }
    return $value;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
CacheCollector::$cacheCreated protected property Stores the cache creation time.
CacheCollector::$cacheInvalidated protected property Flag that indicates of the cache has been invalidated.
CacheCollector::$cacheLoaded protected property Indicates if the collected cache was already loaded.
CacheCollector::$cid protected property The cache id that is used for the cache entry.
CacheCollector::$keysToPersist protected property An array of keys to add to the cache on service termination.
CacheCollector::$keysToRemove protected property An array of keys to remove from the cache on service termination.
CacheCollector::$storage protected property Storage for the data itself.
CacheCollector::$tags protected property A list of tags that are used for the cache entry.
CacheCollector::clear public function Clears the collected cache entry. Overrides CacheCollectorInterface::clear 1
CacheCollector::delete public function Deletes the element. Overrides CacheCollectorInterface::delete
CacheCollector::destruct public function Performs destruct operations. Overrides DestructableInterface::destruct
CacheCollector::get public function Gets value from the cache. Overrides CacheCollectorInterface::get 2
CacheCollector::has public function Returns whether data exists for this key. Overrides CacheCollectorInterface::has 1
CacheCollector::invalidateCache protected function Invalidate the cache.
CacheCollector::lazyLoadCache protected function Loads the cache if not already done. 1
CacheCollector::normalizeLockName protected function Normalizes a cache ID in order to comply with database limitations.
CacheCollector::persist protected function Flags an offset value to be written to the persistent cache.
CacheCollector::reset public function Resets the local cache. Overrides CacheCollectorInterface::reset 1
CacheCollector::set public function Implements \Drupal\Core\Cache\CacheCollectorInterface::set(). Overrides CacheCollectorInterface::set 1
CacheCollector::updateCache protected function Writes a value to the persistent cache immediately. 1
LocaleLookup::$cache protected property The cache backend that should be used. Overrides CacheCollector::$cache
LocaleLookup::$configFactory protected property The configuration factory.
LocaleLookup::$context protected property The msgctxt context.
LocaleLookup::$langcode protected property A language code.
LocaleLookup::$languageManager protected property The language manager.
LocaleLookup::$lock protected property The lock backend that should be used. Overrides CacheCollector::$lock
LocaleLookup::$requestStack protected property The request stack.
LocaleLookup::$stringStorage protected property The locale storage.
LocaleLookup::getCid protected function Gets the cache ID. Overrides CacheCollector::getCid
LocaleLookup::resolveCacheMiss protected function Resolves a cache miss. Overrides CacheCollector::resolveCacheMiss
LocaleLookup::__construct public function Constructs a LocaleLookup object. Overrides CacheCollector::__construct