[FrameworkBundle][Translation] moved cache to Translation component
[Translation][Cache] removed accessors for options.
This commit is contained in:
parent
eb1e3c344c
commit
8b2d9a8d4d
@ -14,7 +14,6 @@ namespace Symfony\Bundle\FrameworkBundle\Translation;
|
|||||||
use Symfony\Component\Translation\Translator as BaseTranslator;
|
use Symfony\Component\Translation\Translator as BaseTranslator;
|
||||||
use Symfony\Component\Translation\MessageSelector;
|
use Symfony\Component\Translation\MessageSelector;
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
use Symfony\Component\Config\ConfigCache;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translator.
|
* Translator.
|
||||||
@ -24,10 +23,6 @@ use Symfony\Component\Config\ConfigCache;
|
|||||||
class Translator extends BaseTranslator
|
class Translator extends BaseTranslator
|
||||||
{
|
{
|
||||||
protected $container;
|
protected $container;
|
||||||
protected $options = array(
|
|
||||||
'cache_dir' => null,
|
|
||||||
'debug' => false,
|
|
||||||
);
|
|
||||||
protected $loaderIds;
|
protected $loaderIds;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,14 +45,7 @@ class Translator extends BaseTranslator
|
|||||||
$this->container = $container;
|
$this->container = $container;
|
||||||
$this->loaderIds = $loaderIds;
|
$this->loaderIds = $loaderIds;
|
||||||
|
|
||||||
// check option names
|
parent::__construct(null, $selector, $options);
|
||||||
if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
|
|
||||||
throw new \InvalidArgumentException(sprintf('The Translator does not support the following options: \'%s\'.', implode('\', \'', $diff)));
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->options = array_merge($this->options, $options);
|
|
||||||
|
|
||||||
parent::__construct(null, $selector);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -80,72 +68,10 @@ class Translator extends BaseTranslator
|
|||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
protected function loadCatalogue($locale)
|
protected function initializeCatalogue($locale)
|
||||||
{
|
{
|
||||||
if (isset($this->catalogues[$locale])) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null === $this->options['cache_dir']) {
|
|
||||||
$this->initialize();
|
$this->initialize();
|
||||||
|
parent::initializeCatalogue($locale);
|
||||||
return parent::loadCatalogue($locale);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->assertValidLocale($locale);
|
|
||||||
|
|
||||||
$cache = new ConfigCache($this->options['cache_dir'].'/catalogue.'.$locale.'.php', $this->options['debug']);
|
|
||||||
if (!$cache->isFresh()) {
|
|
||||||
$this->initialize();
|
|
||||||
|
|
||||||
parent::loadCatalogue($locale);
|
|
||||||
|
|
||||||
$fallbackContent = '';
|
|
||||||
$current = '';
|
|
||||||
$replacementPattern = '/[^a-z0-9_]/i';
|
|
||||||
foreach ($this->computeFallbackLocales($locale) as $fallback) {
|
|
||||||
$fallbackSuffix = ucfirst(preg_replace($replacementPattern, '_', $fallback));
|
|
||||||
$currentSuffix = ucfirst(preg_replace($replacementPattern, '_', $current));
|
|
||||||
|
|
||||||
$fallbackContent .= sprintf(<<<EOF
|
|
||||||
\$catalogue%s = new MessageCatalogue('%s', %s);
|
|
||||||
\$catalogue%s->addFallbackCatalogue(\$catalogue%s);
|
|
||||||
|
|
||||||
|
|
||||||
EOF
|
|
||||||
,
|
|
||||||
$fallbackSuffix,
|
|
||||||
$fallback,
|
|
||||||
var_export($this->catalogues[$fallback]->all(), true),
|
|
||||||
$currentSuffix,
|
|
||||||
$fallbackSuffix
|
|
||||||
);
|
|
||||||
$current = $fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
$content = sprintf(<<<EOF
|
|
||||||
<?php
|
|
||||||
|
|
||||||
use Symfony\Component\Translation\MessageCatalogue;
|
|
||||||
|
|
||||||
\$catalogue = new MessageCatalogue('%s', %s);
|
|
||||||
|
|
||||||
%s
|
|
||||||
return \$catalogue;
|
|
||||||
|
|
||||||
EOF
|
|
||||||
,
|
|
||||||
$locale,
|
|
||||||
var_export($this->catalogues[$locale]->all(), true),
|
|
||||||
$fallbackContent
|
|
||||||
);
|
|
||||||
|
|
||||||
$cache->write($content, $this->catalogues[$locale]->getResources());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->catalogues[$locale] = include $cache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function initialize()
|
protected function initialize()
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
2.6.0
|
||||||
|
-----
|
||||||
|
* added possibility to cache catalogues
|
||||||
|
|
||||||
2.5.0
|
2.5.0
|
||||||
-----
|
-----
|
||||||
|
|
||||||
|
169
src/Symfony/Component/Translation/Tests/TranslatorCacheTest.php
Normal file
169
src/Symfony/Component/Translation/Tests/TranslatorCacheTest.php
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Component\Translation\Tests;
|
||||||
|
|
||||||
|
use Symfony\Component\Translation\Translator;
|
||||||
|
use Symfony\Component\Translation\MessageCatalogue;
|
||||||
|
use Symfony\Component\Translation\MessageSelector;
|
||||||
|
|
||||||
|
class TranslatorCacheTest extends \PHPUnit_Framework_TestCase
|
||||||
|
{
|
||||||
|
protected $tmpDir;
|
||||||
|
|
||||||
|
protected function setUp()
|
||||||
|
{
|
||||||
|
$this->tmpDir = sys_get_temp_dir().'/sf2_translation';
|
||||||
|
$this->deleteTmpDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function tearDown()
|
||||||
|
{
|
||||||
|
$this->deleteTmpDir();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function deleteTmpDir()
|
||||||
|
{
|
||||||
|
if (!file_exists($dir = $this->tmpDir)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->tmpDir), \RecursiveIteratorIterator::CHILD_FIRST);
|
||||||
|
foreach ($iterator as $path) {
|
||||||
|
if (preg_match('#[/\\\\]\.\.?$#', $path->__toString())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($path->isDir()) {
|
||||||
|
rmdir($path->__toString());
|
||||||
|
} else {
|
||||||
|
unlink($path->__toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rmdir($this->tmpDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTransWithoutCaching()
|
||||||
|
{
|
||||||
|
$translator = $this->getTranslator($this->getLoader());
|
||||||
|
$translator->setLocale('fr');
|
||||||
|
$translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR'));
|
||||||
|
|
||||||
|
$this->assertEquals('foo (FR)', $translator->trans('foo'));
|
||||||
|
$this->assertEquals('bar (EN)', $translator->trans('bar'));
|
||||||
|
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
|
||||||
|
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
|
||||||
|
$this->assertEquals('no translation', $translator->trans('no translation'));
|
||||||
|
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
|
||||||
|
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testTransWithCaching()
|
||||||
|
{
|
||||||
|
// prime the cache
|
||||||
|
$translator = $this->getTranslator($this->getLoader(), array('cache_dir' => $this->tmpDir));
|
||||||
|
$translator->setLocale('fr');
|
||||||
|
$translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR'));
|
||||||
|
|
||||||
|
$this->assertEquals('foo (FR)', $translator->trans('foo'));
|
||||||
|
$this->assertEquals('bar (EN)', $translator->trans('bar'));
|
||||||
|
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
|
||||||
|
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
|
||||||
|
$this->assertEquals('no translation', $translator->trans('no translation'));
|
||||||
|
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
|
||||||
|
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
|
||||||
|
|
||||||
|
// do it another time as the cache is primed now
|
||||||
|
$loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');
|
||||||
|
$translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir));
|
||||||
|
$translator->setLocale('fr');
|
||||||
|
$translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR'));
|
||||||
|
|
||||||
|
$this->assertEquals('foo (FR)', $translator->trans('foo'));
|
||||||
|
$this->assertEquals('bar (EN)', $translator->trans('bar'));
|
||||||
|
$this->assertEquals('foobar (ES)', $translator->trans('foobar'));
|
||||||
|
$this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0));
|
||||||
|
$this->assertEquals('no translation', $translator->trans('no translation'));
|
||||||
|
$this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo'));
|
||||||
|
$this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getCatalogue($locale, $messages)
|
||||||
|
{
|
||||||
|
$catalogue = new MessageCatalogue($locale);
|
||||||
|
foreach ($messages as $key => $translation) {
|
||||||
|
$catalogue->set($key, $translation);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $catalogue;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getLoader()
|
||||||
|
{
|
||||||
|
$loader = $this->getMock('Symfony\Component\Translation\Loader\LoaderInterface');
|
||||||
|
$loader
|
||||||
|
->expects($this->at(0))
|
||||||
|
->method('load')
|
||||||
|
->will($this->returnValue($this->getCatalogue('fr', array(
|
||||||
|
'foo' => 'foo (FR)',
|
||||||
|
))))
|
||||||
|
;
|
||||||
|
$loader
|
||||||
|
->expects($this->at(1))
|
||||||
|
->method('load')
|
||||||
|
->will($this->returnValue($this->getCatalogue('en', array(
|
||||||
|
'foo' => 'foo (EN)',
|
||||||
|
'bar' => 'bar (EN)',
|
||||||
|
'choice' => '{0} choice 0 (EN)|{1} choice 1 (EN)|]1,Inf] choice inf (EN)',
|
||||||
|
))))
|
||||||
|
;
|
||||||
|
$loader
|
||||||
|
->expects($this->at(2))
|
||||||
|
->method('load')
|
||||||
|
->will($this->returnValue($this->getCatalogue('es', array(
|
||||||
|
'foobar' => 'foobar (ES)',
|
||||||
|
))))
|
||||||
|
;
|
||||||
|
$loader
|
||||||
|
->expects($this->at(3))
|
||||||
|
->method('load')
|
||||||
|
->will($this->returnValue($this->getCatalogue('pt-PT', array(
|
||||||
|
'foobarfoo' => 'foobarfoo (PT-PT)',
|
||||||
|
))))
|
||||||
|
;
|
||||||
|
$loader
|
||||||
|
->expects($this->at(4))
|
||||||
|
->method('load')
|
||||||
|
->will($this->returnValue($this->getCatalogue('pt_BR', array(
|
||||||
|
'other choice' => '{0} other choice 0 (PT-BR)|{1} other choice 1 (PT-BR)|]1,Inf] other choice inf (PT-BR)',
|
||||||
|
))))
|
||||||
|
;
|
||||||
|
|
||||||
|
return $loader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTranslator($loader, $options = array())
|
||||||
|
{
|
||||||
|
$translator = new Translator(
|
||||||
|
$loader,
|
||||||
|
new MessageSelector(),
|
||||||
|
$options
|
||||||
|
);
|
||||||
|
|
||||||
|
$translator->addLoader('loader', $loader);
|
||||||
|
$translator->addResource('loader', 'foo', 'fr');
|
||||||
|
$translator->addResource('loader', 'foo', 'en');
|
||||||
|
$translator->addResource('loader', 'foo', 'es');
|
||||||
|
$translator->addResource('loader', 'foo', 'pt-PT'); // European Portuguese
|
||||||
|
$translator->addResource('loader', 'foo', 'pt_BR'); // Brazilian Portuguese
|
||||||
|
|
||||||
|
return $translator;
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ namespace Symfony\Component\Translation;
|
|||||||
|
|
||||||
use Symfony\Component\Translation\Loader\LoaderInterface;
|
use Symfony\Component\Translation\Loader\LoaderInterface;
|
||||||
use Symfony\Component\Translation\Exception\NotFoundResourceException;
|
use Symfony\Component\Translation\Exception\NotFoundResourceException;
|
||||||
|
use Symfony\Component\Config\ConfigCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translator.
|
* Translator.
|
||||||
@ -33,6 +34,14 @@ class Translator implements TranslatorInterface
|
|||||||
*/
|
*/
|
||||||
protected $locale;
|
protected $locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $options = array(
|
||||||
|
'cache_dir' => null,
|
||||||
|
'debug' => false,
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
@ -58,15 +67,23 @@ class Translator implements TranslatorInterface
|
|||||||
*
|
*
|
||||||
* @param string $locale The locale
|
* @param string $locale The locale
|
||||||
* @param MessageSelector|null $selector The message selector for pluralization
|
* @param MessageSelector|null $selector The message selector for pluralization
|
||||||
|
* @param array $options An array of options
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException If a locale contains invalid characters
|
* @throws \InvalidArgumentException If a locale contains invalid characters
|
||||||
*
|
*
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
public function __construct($locale, MessageSelector $selector = null)
|
public function __construct($locale, MessageSelector $selector = null, array $options = array())
|
||||||
{
|
{
|
||||||
$this->setLocale($locale);
|
$this->setLocale($locale);
|
||||||
$this->selector = $selector ?: new MessageSelector();
|
$this->selector = $selector ?: new MessageSelector();
|
||||||
|
|
||||||
|
// check option names
|
||||||
|
if ($diff = array_diff(array_keys($options), array_keys($this->options))) {
|
||||||
|
throw new \InvalidArgumentException(sprintf('The Translator does not support the following options: \'%s\'.', implode('\', \'', $diff)));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->options = array_merge($this->options, $options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -282,7 +299,22 @@ class Translator implements TranslatorInterface
|
|||||||
return $messages;
|
return $messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @param string $locale
|
||||||
|
*/
|
||||||
protected function loadCatalogue($locale)
|
protected function loadCatalogue($locale)
|
||||||
|
{
|
||||||
|
if (null === $this->options['cache_dir']) {
|
||||||
|
$this->initializeCatalogue($locale);
|
||||||
|
} else {
|
||||||
|
$this->initializeCacheCatalogue($locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $locale
|
||||||
|
*/
|
||||||
|
protected function initializeCatalogue($locale)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->doLoadCatalogue($locale);
|
$this->doLoadCatalogue($locale);
|
||||||
@ -294,6 +326,75 @@ class Translator implements TranslatorInterface
|
|||||||
$this->loadFallbackCatalogues($locale);
|
$this->loadFallbackCatalogues($locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $locale
|
||||||
|
*/
|
||||||
|
private function initializeCacheCatalogue($locale)
|
||||||
|
{
|
||||||
|
if (isset($this->catalogues[$locale])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null === $this->options['cache_dir']) {
|
||||||
|
$this->initialize();
|
||||||
|
|
||||||
|
return parent::loadCatalogue($locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
$cache = new ConfigCache($this->options['cache_dir'].'/catalogue.'.$locale.'.php', $this->options['debug']);
|
||||||
|
if (!$cache->isFresh()) {
|
||||||
|
$this->initialize();
|
||||||
|
|
||||||
|
parent::loadCatalogue($locale);
|
||||||
|
|
||||||
|
$fallbackContent = '';
|
||||||
|
$current = '';
|
||||||
|
$replacementPattern = '/[^a-z0-9_]/i';
|
||||||
|
foreach ($this->computeFallbackLocales($locale) as $fallback) {
|
||||||
|
$fallbackSuffix = ucfirst(preg_replace($replacementPattern, '_', $fallback));
|
||||||
|
$currentSuffix = ucfirst(preg_replace($replacementPattern, '_', $current));
|
||||||
|
|
||||||
|
$fallbackContent .= sprintf(<<<EOF
|
||||||
|
\$catalogue%s = new MessageCatalogue('%s', %s);
|
||||||
|
\$catalogue%s->addFallbackCatalogue(\$catalogue%s);
|
||||||
|
|
||||||
|
|
||||||
|
EOF
|
||||||
|
,
|
||||||
|
$fallbackSuffix,
|
||||||
|
$fallback,
|
||||||
|
var_export($this->catalogues[$fallback]->all(), true),
|
||||||
|
$currentSuffix,
|
||||||
|
$fallbackSuffix
|
||||||
|
);
|
||||||
|
$current = $fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
$content = sprintf(<<<EOF
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\Translation\MessageCatalogue;
|
||||||
|
|
||||||
|
\$catalogue = new MessageCatalogue('%s', %s);
|
||||||
|
|
||||||
|
%s
|
||||||
|
return \$catalogue;
|
||||||
|
|
||||||
|
EOF
|
||||||
|
,
|
||||||
|
$locale,
|
||||||
|
var_export($this->catalogues[$locale]->all(), true),
|
||||||
|
$fallbackContent
|
||||||
|
);
|
||||||
|
|
||||||
|
$cache->write($content, $this->catalogues[$locale]->getResources());
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->catalogues[$locale] = include $cache;
|
||||||
|
}
|
||||||
|
|
||||||
private function doLoadCatalogue($locale)
|
private function doLoadCatalogue($locale)
|
||||||
{
|
{
|
||||||
$this->catalogues[$locale] = new MessageCatalogue($locale);
|
$this->catalogues[$locale] = new MessageCatalogue($locale);
|
||||||
|
Reference in New Issue
Block a user