annotate core/modules/locale/src/LocaleLookup.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents af1871eacc83
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 namespace Drupal\locale;
Chris@0 4
Chris@18 5 use Drupal\Component\Gettext\PoItem;
Chris@0 6 use Drupal\Core\Cache\CacheBackendInterface;
Chris@0 7 use Drupal\Core\Cache\CacheCollector;
Chris@0 8 use Drupal\Core\Config\ConfigFactoryInterface;
Chris@0 9 use Drupal\Core\Language\LanguageManagerInterface;
Chris@0 10 use Drupal\Core\Lock\LockBackendInterface;
Chris@0 11 use Symfony\Component\HttpFoundation\RequestStack;
Chris@0 12
Chris@0 13 /**
Chris@0 14 * A cache collector to allow for dynamic building of the locale cache.
Chris@0 15 */
Chris@0 16 class LocaleLookup extends CacheCollector {
Chris@0 17
Chris@0 18 /**
Chris@0 19 * A language code.
Chris@0 20 *
Chris@0 21 * @var string
Chris@0 22 */
Chris@0 23 protected $langcode;
Chris@0 24
Chris@0 25 /**
Chris@0 26 * The msgctxt context.
Chris@0 27 *
Chris@0 28 * @var string
Chris@0 29 */
Chris@0 30 protected $context;
Chris@0 31
Chris@0 32 /**
Chris@0 33 * The locale storage.
Chris@0 34 *
Chris@0 35 * @var \Drupal\locale\StringStorageInterface
Chris@0 36 */
Chris@0 37 protected $stringStorage;
Chris@0 38
Chris@0 39 /**
Chris@0 40 * The cache backend that should be used.
Chris@0 41 *
Chris@0 42 * @var \Drupal\Core\Cache\CacheBackendInterface
Chris@0 43 */
Chris@0 44 protected $cache;
Chris@0 45
Chris@0 46 /**
Chris@0 47 * The lock backend that should be used.
Chris@0 48 *
Chris@0 49 * @var \Drupal\Core\Lock\LockBackendInterface
Chris@0 50 */
Chris@0 51 protected $lock;
Chris@0 52
Chris@0 53 /**
Chris@0 54 * The configuration factory.
Chris@0 55 *
Chris@0 56 * @var \Drupal\Core\Config\ConfigFactoryInterface
Chris@0 57 */
Chris@0 58 protected $configFactory;
Chris@0 59
Chris@0 60 /**
Chris@0 61 * The language manager.
Chris@0 62 *
Chris@0 63 * @var \Drupal\Core\Language\LanguageManagerInterface
Chris@0 64 */
Chris@0 65 protected $languageManager;
Chris@0 66
Chris@0 67 /**
Chris@0 68 * The request stack.
Chris@0 69 *
Chris@0 70 * @var \Symfony\Component\HttpFoundation\RequestStack
Chris@0 71 */
Chris@0 72 protected $requestStack;
Chris@0 73
Chris@0 74 /**
Chris@0 75 * Constructs a LocaleLookup object.
Chris@0 76 *
Chris@0 77 * @param string $langcode
Chris@0 78 * The language code.
Chris@0 79 * @param string $context
Chris@0 80 * The string context.
Chris@0 81 * @param \Drupal\locale\StringStorageInterface $string_storage
Chris@0 82 * The string storage.
Chris@0 83 * @param \Drupal\Core\Cache\CacheBackendInterface $cache
Chris@0 84 * The cache backend.
Chris@0 85 * @param \Drupal\Core\Lock\LockBackendInterface $lock
Chris@0 86 * The lock backend.
Chris@0 87 * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
Chris@0 88 * The config factory.
Chris@0 89 * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
Chris@0 90 * The language manager.
Chris@0 91 * @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
Chris@0 92 * The request stack.
Chris@0 93 */
Chris@0 94 public function __construct($langcode, $context, StringStorageInterface $string_storage, CacheBackendInterface $cache, LockBackendInterface $lock, ConfigFactoryInterface $config_factory, LanguageManagerInterface $language_manager, RequestStack $request_stack) {
Chris@0 95 $this->langcode = $langcode;
Chris@0 96 $this->context = (string) $context;
Chris@0 97 $this->stringStorage = $string_storage;
Chris@0 98 $this->configFactory = $config_factory;
Chris@0 99 $this->languageManager = $language_manager;
Chris@0 100
Chris@0 101 $this->cache = $cache;
Chris@0 102 $this->lock = $lock;
Chris@0 103 $this->tags = ['locale'];
Chris@0 104 $this->requestStack = $request_stack;
Chris@0 105 }
Chris@0 106
Chris@0 107 /**
Chris@0 108 * {@inheritdoc}
Chris@0 109 */
Chris@0 110 protected function getCid() {
Chris@0 111 if (!isset($this->cid)) {
Chris@0 112 // Add the current user's role IDs to the cache key, this ensures that,
Chris@0 113 // for example, strings for admin menu items and settings forms are not
Chris@0 114 // cached for anonymous users.
Chris@0 115 $user = \Drupal::currentUser();
Chris@0 116 $rids = $user ? implode(':', $user->getRoles()) : '';
Chris@0 117 $this->cid = "locale:{$this->langcode}:{$this->context}:$rids";
Chris@0 118
Chris@0 119 // Getting the roles from the current user might have resulted in t()
Chris@0 120 // calls that attempted to get translations from the locale cache. In that
Chris@0 121 // case they would not go into this method again as
Chris@0 122 // CacheCollector::lazyLoadCache() already set the loaded flag. They would
Chris@0 123 // however call resolveCacheMiss() and add that string to the list of
Chris@0 124 // cache misses that need to be written into the cache. Prevent that by
Chris@0 125 // resetting that list. All that happens in such a case are a few uncached
Chris@0 126 // translation lookups.
Chris@0 127 $this->keysToPersist = [];
Chris@0 128 }
Chris@0 129 return $this->cid;
Chris@0 130 }
Chris@0 131
Chris@0 132 /**
Chris@0 133 * {@inheritdoc}
Chris@0 134 */
Chris@0 135 protected function resolveCacheMiss($offset) {
Chris@0 136 $translation = $this->stringStorage->findTranslation([
Chris@0 137 'language' => $this->langcode,
Chris@0 138 'source' => $offset,
Chris@0 139 'context' => $this->context,
Chris@0 140 ]);
Chris@0 141
Chris@0 142 if ($translation) {
Chris@0 143 $value = !empty($translation->translation) ? $translation->translation : TRUE;
Chris@0 144 }
Chris@0 145 else {
Chris@0 146 // We don't have the source string, update the {locales_source} table to
Chris@0 147 // indicate the string is not translated.
Chris@0 148 $this->stringStorage->createString([
Chris@0 149 'source' => $offset,
Chris@0 150 'context' => $this->context,
Chris@0 151 'version' => \Drupal::VERSION,
Chris@0 152 ])->addLocation('path', $this->requestStack->getCurrentRequest()->getRequestUri())->save();
Chris@0 153 $value = TRUE;
Chris@0 154 }
Chris@0 155
Chris@0 156 // If there is no translation available for the current language then use
Chris@0 157 // language fallback to try other translations.
Chris@0 158 if ($value === TRUE) {
Chris@0 159 $fallbacks = $this->languageManager->getFallbackCandidates(['langcode' => $this->langcode, 'operation' => 'locale_lookup', 'data' => $offset]);
Chris@0 160 if (!empty($fallbacks)) {
Chris@0 161 foreach ($fallbacks as $langcode) {
Chris@0 162 $translation = $this->stringStorage->findTranslation([
Chris@0 163 'language' => $langcode,
Chris@0 164 'source' => $offset,
Chris@0 165 'context' => $this->context,
Chris@0 166 ]);
Chris@0 167
Chris@0 168 if ($translation && !empty($translation->translation)) {
Chris@0 169 $value = $translation->translation;
Chris@0 170 break;
Chris@0 171 }
Chris@0 172 }
Chris@0 173 }
Chris@0 174 }
Chris@0 175
Chris@18 176 if (is_string($value) && strpos($value, PoItem::DELIMITER) !== FALSE) {
Chris@12 177 // Community translations imported from localize.drupal.org as well as
Chris@12 178 // migrated translations may contain @count[number].
Chris@12 179 $value = preg_replace('!@count\[\d+\]!', '@count', $value);
Chris@12 180 }
Chris@12 181
Chris@0 182 $this->storage[$offset] = $value;
Chris@0 183 // Disabling the usage of string caching allows a module to watch for
Chris@0 184 // the exact list of strings used on a page. From a performance
Chris@0 185 // perspective that is a really bad idea, so we have no user
Chris@0 186 // interface for this. Be careful when turning this option off!
Chris@0 187 if ($this->configFactory->get('locale.settings')->get('cache_strings')) {
Chris@0 188 $this->persist($offset);
Chris@0 189 }
Chris@0 190 return $value;
Chris@0 191 }
Chris@0 192
Chris@0 193 }