feature #13074 [Translation] Refresh catalogues when resources change (iamluc)

This PR was merged into the 2.7 branch.

Discussion
----------

[Translation] Refresh catalogues when resources change

| Q             | A
| ------------- | ---
| Bug fix?      | yes
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | #11530
| License       | MIT
| Doc PR        | no

When a translation file is added in a bundle, the container is refreshed thanks to a DirectoryResource watching for changes.
But the translator has his own cache that is not refreshed.

This PR adds a hash check when cached is used.

Commits
-------

1113999 Refresh catalogues when resources change
This commit is contained in:
Fabien Potencier 2015-02-05 08:41:54 +01:00
commit 53c8baeae2
2 changed files with 65 additions and 4 deletions

View File

@ -101,6 +101,41 @@ class TranslatorCacheTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax'));
}
public function testRefreshCacheWhenResourcesChange()
{
// prime the cache
$loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');
$loader
->method('load')
->will($this->returnValue($this->getCatalogue('fr', array(
'foo' => 'foo A',
))))
;
$translator = new Translator('fr', new MessageSelector(), $this->tmpDir, true);
$translator->setLocale('fr');
$translator->addLoader('loader', $loader);
$translator->addResource('loader', 'foo', 'fr');
$this->assertEquals('foo A', $translator->trans('foo'));
// add a new resource to refresh the cache
$loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');
$loader
->method('load')
->will($this->returnValue($this->getCatalogue('fr', array(
'foo' => 'foo B',
))))
;
$translator = new Translator('fr', new MessageSelector(), $this->tmpDir, true);
$translator->setLocale('fr');
$translator->addLoader('loader', $loader);
$translator->addResource('loader', 'bar', 'fr');
$this->assertEquals('foo B', $translator->trans('foo'));
}
public function testTransWithCachingWithInvalidLocale()
{
$loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');

View File

@ -346,8 +346,9 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
/**
* @param string $locale
* @param bool $forceRefresh
*/
private function initializeCacheCatalogue($locale)
private function initializeCacheCatalogue($locale, $forceRefresh = false)
{
if (isset($this->catalogues[$locale])) {
return;
@ -361,7 +362,7 @@ class Translator implements TranslatorInterface, TranslatorBagInterface
$this->assertValidLocale($locale);
$cache = new ConfigCache($this->cacheDir.'/catalogue.'.$locale.'.php', $this->debug);
if (!$cache->isFresh()) {
if ($forceRefresh || !$cache->isFresh()) {
$this->initializeCatalogue($locale);
$fallbackContent = '';
@ -392,13 +393,15 @@ EOF
use Symfony\Component\Translation\MessageCatalogue;
\$resourcesHash = '%s';
\$catalogue = new MessageCatalogue('%s', %s);
%s
return \$catalogue;
return array(\$catalogue, \$resourcesHash);
EOF
,
$this->getResourcesHash($locale),
$locale,
var_export($this->catalogues[$locale]->all(), true),
$fallbackContent
@ -409,7 +412,30 @@ EOF
return;
}
$this->catalogues[$locale] = include $cache;
$catalogue = include $cache;
/**
* Old cache returns only the catalogue, without resourcesHash
*/
$resourcesHash = null;
if (is_array($catalogue)) {
list($catalogue, $resourcesHash) = $catalogue;
}
if ($this->debug && $resourcesHash !== $this->getResourcesHash($locale)) {
return $this->initializeCacheCatalogue($locale, true);
}
$this->catalogues[$locale] = $catalogue;
}
private function getResourcesHash($locale)
{
if (!isset($this->resources[$locale])) {
return '';
}
return sha1(serialize($this->resources[$locale]));
}
private function doLoadCatalogue($locale)