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')); $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() public function testTransWithCachingWithInvalidLocale()
{ {
$loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface'); $loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');

View File

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