Skip to content

Commit b39dd88

Browse files
committed
[Translation] added message cache + doctrine cache.
1 parent 37c137a commit b39dd88

File tree

12 files changed

+621
-69
lines changed

12 files changed

+621
-69
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,7 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode)
585585
->defaultValue(array('en'))
586586
->end()
587587
->booleanNode('logging')->defaultValue($this->debug)->end()
588+
->scalarNode('cache')->defaultValue('translation.cache.default')->end()
588589
->end()
589590
->end()
590591
->end()

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -652,6 +652,10 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
652652

653653
$container->setParameter('translator.logging', $config['logging']);
654654

655+
if (isset($config['cache'])) {
656+
$container->setAlias('translation.cache', $config['cache']);
657+
}
658+
655659
// Discover translation directories
656660
$dirs = array();
657661
if (class_exists('Symfony\Component\Validator\Validation')) {

src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
<argument key="debug">%kernel.debug%</argument>
4646
</argument>
4747
<argument type="collection" /> <!-- translation resources -->
48+
<argument type="service" id="translation.cache" />
4849
</service>
4950

5051
<service id="translator.logging" class="Symfony\Component\Translation\LoggingTranslator" public="false">
@@ -152,5 +153,13 @@
152153
<service id="translation.extractor" class="%translation.extractor.class%"/>
153154

154155
<service id="translation.writer" class="%translation.writer.class%"/>
156+
157+
<!-- Cache -->
158+
<service id="translation.cache.default" class="Symfony\Component\Translation\MessageCache" public="false">
159+
<argument key="cache_dir">%kernel.cache_dir%/translations</argument> <!-- cache_dir -->
160+
<argument>%kernel.debug%</argument> <!-- debug -->
161+
</service>
162+
163+
<service id="translation.cache" alias="translation.cache.default" />
155164
</services>
156165
</container>

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ protected static function getBundleDefaultConfig()
146146
'enabled' => false,
147147
'fallbacks' => array('en'),
148148
'logging' => true,
149+
'cache' => 'translation.cache.default'
149150
),
150151
'validation' => array(
151152
'enabled' => false,

src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Symfony\Component\Translation\Translator as BaseTranslator;
1515
use Symfony\Component\Translation\MessageSelector;
1616
use Symfony\Component\DependencyInjection\ContainerInterface;
17+
use Symfony\Component\Translation\MessageCacheInterface;
1718

1819
/**
1920
* Translator.
@@ -39,15 +40,16 @@ class Translator extends BaseTranslator
3940
* * cache_dir: The cache directory (or null to disable caching)
4041
* * debug: Whether to enable debugging or not (false by default)
4142
*
42-
* @param ContainerInterface $container A ContainerInterface instance
43-
* @param MessageSelector $selector The message selector for pluralization
44-
* @param array $loaderIds An array of loader Ids
45-
* @param array $options An array of options
46-
* @param array $resourceFiles An array of resource directories
43+
* @param ContainerInterface $container A ContainerInterface instance
44+
* @param MessageSelector $selector The message selector for pluralization
45+
* @param array $loaderIds An array of loader Ids
46+
* @param array $options An array of options
47+
* @param array $resourceFiles An array of resource directories
48+
* @param MessageCacheInterface $cache The message cache
4749
*
4850
* @throws \InvalidArgumentException
4951
*/
50-
public function __construct(ContainerInterface $container, MessageSelector $selector, $loaderIds = array(), array $options = array(), $resourceFiles = array())
52+
public function __construct(ContainerInterface $container, MessageSelector $selector, $loaderIds = array(), array $options = array(), $resourceFiles = array(), MessageCacheInterface $cache = null)
5153
{
5254
$this->container = $container;
5355
$this->loaderIds = $loaderIds;
@@ -63,7 +65,8 @@ public function __construct(ContainerInterface $container, MessageSelector $sele
6365
$this->loadResources();
6466
}
6567

66-
parent::__construct(null, $selector, $this->options['cache_dir'], $this->options['debug']);
68+
$cache = $cache ?: $this->options['cache_dir'];
69+
parent::__construct(null, $selector, $cache, $this->options['debug']);
6770
}
6871

6972
/**
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Translation;
13+
14+
use Doctrine\Common\Cache\Cache;
15+
16+
/**
17+
* @author Abdellatif Ait Boudad <a.aitboudad@gmail.com>
18+
*/
19+
class DoctrineMessageCache implements MessageCacheInterface
20+
{
21+
const CACHE_RESOURCE_HASH = 'resources_hash';
22+
23+
/**
24+
* @var bool
25+
*/
26+
private $debug;
27+
28+
/**
29+
* @var Cache
30+
*/
31+
private $cacheProvider;
32+
33+
/**
34+
* @param bool $debug
35+
* @param Cache $cacheProvider
36+
*/
37+
public function __construct($debug, Cache $cacheProvider)
38+
{
39+
$this->debug = $debug;
40+
$this->cacheProvider = $cacheProvider;
41+
}
42+
43+
/**
44+
* {@inheritdoc}
45+
*/
46+
public function isFresh($options = array())
47+
{
48+
$resourcesHash = $this->cacheProvider->fetch(self::CACHE_RESOURCE_HASH.'_'.$options['locale']);
49+
if ($this->debug && $resourcesHash !== $options['resources_hash']) {
50+
return false;
51+
}
52+
53+
return true;
54+
}
55+
56+
/**
57+
* {@inheritdoc}
58+
*/
59+
public function load($resource, $locale, $domain = null)
60+
{
61+
return new DoctrineMessageCatalogue($locale, $this->cacheProvider);
62+
}
63+
64+
/**
65+
* {@inheritdoc}
66+
*/
67+
public function dump(MessageCatalogue $messages, $options = array())
68+
{
69+
$catalogue = new DoctrineMessageCatalogue($messages->getLocale(), $this->cacheProvider);
70+
$catalogue->addCatalogue($messages);
71+
72+
$this->cacheProvider->save(self::CACHE_RESOURCE_HASH.'_'.$messages->getLocale(), $options['resources_hash']);
73+
}
74+
}
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Translation;
13+
14+
use Doctrine\Common\Cache\Cache;
15+
use Doctrine\Common\Cache\MultiGetCache;
16+
17+
/**
18+
* @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
19+
*/
20+
class DoctrineMessageCatalogue extends MessageCatalogue
21+
{
22+
const PREFIX = 'sf2_translation_';
23+
const CATALOGUE_DOMAINS = 'domains';
24+
const CATALOGUE_DOMAIN_METADATA = 'domain_meta_';
25+
26+
/**
27+
* @var Cache
28+
*/
29+
private $cache;
30+
31+
/**
32+
* @var string
33+
*/
34+
private $prefix;
35+
36+
/**
37+
* @var array
38+
*/
39+
private $domains = array();
40+
41+
/**
42+
* @param string $locale
43+
* @param Cache $cache
44+
* @param string $prefix
45+
*/
46+
public function __construct($locale, Cache $cache, $prefix = self::PREFIX)
47+
{
48+
parent::__construct($locale);
49+
if (0 === strlen($prefix)) {
50+
throw new \InvalidArgumentException('$prefix cannot be empty.');
51+
}
52+
53+
$this->cache = $cache;
54+
$this->prefix = $prefix.$locale;
55+
56+
if ($cache->contains($domainsId = $this->prefix.'_'.self::CATALOGUE_DOMAINS)) {
57+
$this->domains = $cache->fetch($domainsId);
58+
}
59+
}
60+
61+
/**
62+
* {@inheritdoc}
63+
*/
64+
public function getDomains()
65+
{
66+
return $this->domains;
67+
}
68+
69+
/**
70+
* {@inheritdoc}
71+
*/
72+
public function all($domain = null)
73+
{
74+
if (!$this->cache instanceof MultiGetCache) {
75+
return array();
76+
}
77+
78+
$domains = $this->domains;
79+
if (null !== $domain) {
80+
$domains = array($domain);
81+
}
82+
83+
$messages = array();
84+
foreach ($domains as $domainMeta) {
85+
$domainIdentity = $this->prefix.'_'.self::CATALOGUE_DOMAIN_METADATA.'_'.$domainMeta;
86+
if ($this->cache->contains($domainIdentity)) {
87+
$keys = $this->cache->fetch($domainIdentity);
88+
$values = $this->cache->fetchMultiple(array_keys($keys));
89+
foreach ($keys as $key => $id) {
90+
if (isset($values[$key])) {
91+
$messages[$domainMeta][$id] = $values[$key];
92+
}
93+
}
94+
}
95+
}
96+
97+
if (null === $domain) {
98+
return $messages;
99+
}
100+
101+
return isset($messages[$domain]) ? $messages[$domain] : array();
102+
}
103+
104+
/**
105+
* {@inheritdoc}
106+
*/
107+
public function set($id, $translation, $domain = 'messages')
108+
{
109+
$this->add(array($id => $translation), $domain);
110+
}
111+
112+
/**
113+
* {@inheritdoc}
114+
*/
115+
public function has($id, $domain = 'messages')
116+
{
117+
if ($this->defines($id, $domain)) {
118+
return true;
119+
}
120+
121+
$fallbackCatalogue = $this->getFallbackCatalogue();
122+
if (null !== $fallbackCatalogue) {
123+
return $fallbackCatalogue->has($id, $domain);
124+
}
125+
126+
return false;
127+
}
128+
129+
/**
130+
* {@inheritdoc}
131+
*/
132+
public function defines($id, $domain = 'messages')
133+
{
134+
$key = $this->getCacheId($domain, $id);
135+
136+
return $this->cache->contains($key);
137+
}
138+
139+
/**
140+
* {@inheritdoc}
141+
*/
142+
public function get($id, $domain = 'messages')
143+
{
144+
if ($this->defines($id, $domain)) {
145+
return $this->cache->fetch($this->getCacheId($domain, $id));
146+
}
147+
148+
$fallbackCatalogue = $this->getFallbackCatalogue();
149+
if (null !== $fallbackCatalogue) {
150+
return $fallbackCatalogue->get($id, $domain);
151+
}
152+
153+
return $id;
154+
}
155+
156+
/**
157+
* {@inheritdoc}
158+
*/
159+
public function replace($messages, $domain = 'messages')
160+
{
161+
$domainMetaData = array();
162+
$domainMetaKey = $this->prefix.'_'.self::CATALOGUE_DOMAIN_METADATA.'_'.$domain;
163+
if ($this->cache->contains($domainMetaKey)) {
164+
$domainMetaData = $this->cache->fetch($domainMetaKey);
165+
}
166+
167+
foreach ($domainMetaData as $key => $id) {
168+
if (!isset($messages[$id])) {
169+
unset($domainMetaData[$key]);
170+
$this->cache->delete($key);
171+
}
172+
}
173+
174+
$this->cache->save($domainMetaKey, $domainMetaData);
175+
$this->add($messages, $domain);
176+
}
177+
178+
/**
179+
* {@inheritdoc}
180+
*/
181+
public function add($messages, $domain = 'messages')
182+
{
183+
if (!isset($this->domains[$domain])) {
184+
$this->addDomain($domain);
185+
}
186+
187+
$domainMetaData = array();
188+
$domainMetaKey = $this->prefix.'_'.self::CATALOGUE_DOMAIN_METADATA.'_'.$domain;
189+
if ($this->cache->contains($domainMetaKey)) {
190+
$domainMetaData = $this->cache->fetch($domainMetaKey);
191+
}
192+
193+
foreach ($messages as $id => $translation) {
194+
$key = $this->getCacheId($domain, $id);
195+
$domainMetaData[$key] = $id;
196+
$this->cache->save($key, $translation);
197+
}
198+
199+
$this->addDomainMetaData($domain, $domainMetaData);
200+
}
201+
202+
private function getCacheId($id, $domain = 'messages')
203+
{
204+
return $this->prefix.'_'.$domain.'_'.sha1($id);
205+
}
206+
207+
private function addDomain($domain)
208+
{
209+
$this->domains[] = $domain;
210+
$this->cache->save($this->prefix.'_'.self::CATALOGUE_DOMAINS, $this->domains);
211+
}
212+
213+
private function addDomainMetaData($domain, $keys = array())
214+
{
215+
$domainIdentity = $this->prefix.'_'.self::CATALOGUE_DOMAIN_METADATA.'_'.$domain;
216+
$this->cache->save($domainIdentity, $keys);
217+
}
218+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy