mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-12 04:23:19 +00:00
Add cached translation loader
This commit is contained in:
@@ -110,8 +110,8 @@ use Alchemy\Phrasea\Exception\InvalidArgumentException;
|
||||
use Alchemy\Phrasea\Twig\JSUniqueID;
|
||||
use Alchemy\Phrasea\Twig\Camelize;
|
||||
use Alchemy\Phrasea\Twig\BytesConverter;
|
||||
use Alchemy\Phrasea\Utilities\CachedTranslator;
|
||||
use FFMpeg\FFMpegServiceProvider;
|
||||
use JMS\TranslationBundle\Translation\Loader\Symfony\XliffLoader;
|
||||
use Neutron\Silex\Provider\ImagineServiceProvider;
|
||||
use MediaVorus\MediaVorusServiceProvider;
|
||||
use MediaVorus\Utils\RawImageMimeTypeGuesser;
|
||||
@@ -130,7 +130,7 @@ use Silex\Application\TranslationTrait;
|
||||
use Silex\Provider\FormServiceProvider;
|
||||
use Silex\Provider\MonologServiceProvider;
|
||||
use Silex\Provider\SessionServiceProvider;
|
||||
use Silex\Provider\TranslationServiceProvider;
|
||||
use Alchemy\Phrasea\Core\Provider\TranslationServiceProvider;
|
||||
use Silex\Provider\TwigServiceProvider;
|
||||
use Silex\Provider\SwiftmailerServiceProvider;
|
||||
use Silex\Provider\UrlGeneratorServiceProvider;
|
||||
@@ -138,8 +138,6 @@ use Silex\Provider\ValidatorServiceProvider;
|
||||
use Silex\Provider\ServiceControllerServiceProvider;
|
||||
use Symfony\Bridge\Twig\Extension\TranslationExtension;
|
||||
use Symfony\Component\Translation\Loader\MoFileLoader;
|
||||
use Symfony\Component\Translation\Loader\PoFileLoader;
|
||||
use Symfony\Component\Translation\Translator;
|
||||
use Unoconv\UnoconvServiceProvider;
|
||||
use XPDF\PdfToText;
|
||||
use XPDF\XPDFServiceProvider;
|
||||
@@ -311,10 +309,13 @@ class Application extends SilexApplication
|
||||
|
||||
$this->register(new TranslationServiceProvider(), [
|
||||
'locale_fallbacks' => ['fr'],
|
||||
'translator.cache-options' => [
|
||||
'debug' => $this['debug'],
|
||||
'cache_dir' => $this['root.path'].'/tmp/translations'
|
||||
],
|
||||
]);
|
||||
|
||||
$this['translator'] = $this->share($this->extend('translator', function(Translator $translator, $app) {
|
||||
$translator->addLoader('xliff', new XliffLoader());
|
||||
$this['translator'] = $this->share($this->extend('translator', function(CachedTranslator $translator, $app) {
|
||||
$translator->addResource('xliff', __DIR__.'/../../../resources/locales/messages.fr.xliff', 'fr', 'messages');
|
||||
$translator->addResource('xliff', __DIR__.'/../../../resources/locales/validators.fr.xliff', 'fr', 'validators');
|
||||
$translator->addResource('xliff', __DIR__.'/../../../resources/locales/messages.en.xliff', 'en', 'messages');
|
||||
|
@@ -53,6 +53,7 @@ class Uninstaller extends Command
|
||||
foreach ([
|
||||
$root.'/tmp/serializer',
|
||||
$root.'/tmp/cache_twig',
|
||||
$root.'/tmp/translations',
|
||||
$root.'/tmp/cache_minify',
|
||||
$root.'/tmp/download',
|
||||
$root.'/tmp/locks',
|
||||
|
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Phrasea\Core\Provider;
|
||||
|
||||
use Alchemy\Phrasea\Utilities\CachedTranslator;
|
||||
use Silex\Application;
|
||||
use Silex\ServiceProviderInterface;
|
||||
use Symfony\Component\Translation\MessageSelector;
|
||||
use Symfony\Component\Translation\Loader\ArrayLoader;
|
||||
use JMS\TranslationBundle\Translation\Loader\Symfony\XliffLoader;
|
||||
|
||||
class TranslationServiceProvider implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['translator.cache-options'] = array();
|
||||
|
||||
$app['translator'] = $app->share(function ($app) {
|
||||
$app['translator.cache-options'] = array_replace(
|
||||
array(
|
||||
'debug' => $app['debug'],
|
||||
), $app['translator.cache-options']
|
||||
);
|
||||
|
||||
$translator = new CachedTranslator($app, $app['translator.message_selector'], $app['translator.cache-options']);
|
||||
|
||||
// Handle deprecated 'locale_fallback'
|
||||
if (isset($app['locale_fallback'])) {
|
||||
$app['locale_fallbacks'] = (array) $app['locale_fallback'];
|
||||
}
|
||||
|
||||
$translator->setFallbackLocales($app['locale_fallbacks']);
|
||||
|
||||
$translator->addLoader('array', new ArrayLoader());
|
||||
$translator->addLoader('xliff', new XliffLoader());
|
||||
|
||||
foreach ($app['translator.domains'] as $domain => $data) {
|
||||
foreach ($data as $locale => $messages) {
|
||||
$translator->addResource('array', $messages, $locale, $domain);
|
||||
}
|
||||
}
|
||||
|
||||
return $translator;
|
||||
});
|
||||
|
||||
$app['translator.message_selector'] = $app->share(function () {
|
||||
return new MessageSelector();
|
||||
});
|
||||
|
||||
$app['translator.domains'] = array();
|
||||
$app['locale_fallbacks'] = array('en');
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
{
|
||||
}
|
||||
}
|
106
lib/Alchemy/Phrasea/Utilities/CachedTranslator.php
Normal file
106
lib/Alchemy/Phrasea/Utilities/CachedTranslator.php
Normal file
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Silex framework.
|
||||
*
|
||||
* (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 Alchemy\Phrasea\Utilities;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Silex\Translator;
|
||||
use Symfony\Component\Config\ConfigCache;
|
||||
use Symfony\Component\Translation\MessageSelector;
|
||||
|
||||
/**
|
||||
* Translator that gets the current locale from the Silex application
|
||||
* and cache the translations on filesystem.
|
||||
*/
|
||||
class CachedTranslator extends Translator
|
||||
{
|
||||
protected $app;
|
||||
protected $options = array(
|
||||
'cache_dir' => null,
|
||||
'debug' => false,
|
||||
);
|
||||
|
||||
public function __construct(Application $app, MessageSelector $selector, array $options = array())
|
||||
{
|
||||
$this->app = $app;
|
||||
|
||||
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($app, $selector);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function loadCatalogue($locale)
|
||||
{
|
||||
if (isset($this->catalogues[$locale])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (null === $this->options['cache_dir']) {
|
||||
return parent::loadCatalogue($locale);
|
||||
}
|
||||
|
||||
$cache = new ConfigCache($this->options['cache_dir'].'/catalogue.'.$locale.'.php', $this->options['debug']);
|
||||
if (!$cache->isFresh()) {
|
||||
parent::loadCatalogue($locale);
|
||||
|
||||
$fallbackContent = '';
|
||||
$current = '';
|
||||
foreach ($this->computeFallbackLocales($locale) as $fallback) {
|
||||
$fallbackSuffix = ucfirst(str_replace('-', '_', $fallback));
|
||||
|
||||
$fallbackContent .= sprintf(<<<EOF
|
||||
\$catalogue%s = new MessageCatalogue('%s', %s);
|
||||
\$catalogue%s->addFallbackCatalogue(\$catalogue%s);
|
||||
|
||||
|
||||
EOF
|
||||
,
|
||||
$fallbackSuffix,
|
||||
$fallback,
|
||||
var_export($this->catalogues[$fallback]->all(), true),
|
||||
ucfirst(str_replace('-', '_', $current)),
|
||||
$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;
|
||||
}
|
||||
}
|
@@ -312,6 +312,7 @@ class appbox extends base
|
||||
$finder->in([
|
||||
$this->app['root.path'] . '/tmp/cache_minify/',
|
||||
$this->app['root.path'] . '/tmp/cache_twig/',
|
||||
$this->app['root.path'] . '/tmp/translations/',
|
||||
$this->app['root.path'] . '/tmp/cache/profiler/',
|
||||
$this->app['root.path'] . '/tmp/doctrine/',
|
||||
$this->app['root.path'] . '/tmp/serializer/',
|
||||
|
@@ -37,6 +37,7 @@ class module_console_systemClearCache extends Command
|
||||
->in([
|
||||
$this->container['root.path'] . '/tmp/cache_minify/',
|
||||
$this->container['root.path'] . '/tmp/cache_twig/',
|
||||
$this->container['root.path'] . '/tmp/translations/',
|
||||
$this->container['root.path'] . '/tmp/cache/profiler/',
|
||||
$this->container['root.path'] . '/tmp/doctrine/',
|
||||
$this->container['root.path'] . '/tmp/serializer/',
|
||||
|
@@ -337,6 +337,76 @@ class ApplicationTest extends \PhraseanetPHPUnitAbstract
|
||||
$this->assertInstanceOf('MediaAlchemyst\Alchemyst', $app['media-alchemyst']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider transProvider
|
||||
*/
|
||||
public function testCachedTranslator($key, $locale, $expected)
|
||||
{
|
||||
$tempDir = __DIR__ . '/temp-trans';
|
||||
$this->cleanupTempDir($tempDir);
|
||||
|
||||
$app = $this->getPreparedApp($tempDir);
|
||||
|
||||
$this->assertInstanceOf('Alchemy\Phrasea\Utilities\CachedTranslator', $app['translator']);
|
||||
|
||||
$result = $app['translator']->trans($key, array(), null, $locale);
|
||||
|
||||
$this->assertEquals($expected, $result);
|
||||
$this->assertFileExists($tempDir.'/catalogue.'.($locale ?: 'en').'.php');
|
||||
}
|
||||
|
||||
public function transProvider()
|
||||
{
|
||||
return array(
|
||||
array('key1', 'de', 'The german translation'),
|
||||
array('test.key', 'de', 'It works in german'),
|
||||
);
|
||||
}
|
||||
|
||||
protected function getPreparedApp($tempDir)
|
||||
{
|
||||
$app = new Application('test');
|
||||
$app['translator.cache-options'] = [
|
||||
'debug' => false,
|
||||
'cache_dir' => $tempDir,
|
||||
];
|
||||
|
||||
$app['translator.domains'] = array(
|
||||
'messages' => array(
|
||||
'en' => array (
|
||||
'key1' => 'The translation',
|
||||
'key_only_english' => 'Foo',
|
||||
'key2' => 'One apple|%count% apples',
|
||||
'test' => array(
|
||||
'key' => 'It works'
|
||||
)
|
||||
),
|
||||
'de' => array (
|
||||
'key1' => 'The german translation',
|
||||
'key2' => 'One german apple|%count% german apples',
|
||||
'test' => array(
|
||||
'key' => 'It works in german'
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return $app;
|
||||
}
|
||||
|
||||
private function cleanupTempDir($dir)
|
||||
{
|
||||
if (!is_dir($dir)) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (new \DirectoryIterator($dir) as $fileinfo) {
|
||||
if ($fileinfo->isFile()) {
|
||||
unlink($fileinfo->getPathname());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function getAppThatReturnLocale()
|
||||
{
|
||||
$app = new Application('test');
|
||||
|
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Tests\Phrasea\Core\Provider;
|
||||
|
||||
/**
|
||||
* @covers Alchemy\Phrasea\Core\Provider\TranslatorServiceProvider
|
||||
*/
|
||||
class TranslatorServiceProvidertest extends ServiceProviderTestCase
|
||||
{
|
||||
public function provideServiceDescription()
|
||||
{
|
||||
return [
|
||||
['Alchemy\Phrasea\Core\Provider\TranslationServiceProvider', 'translator', 'Alchemy\Phrasea\Utilities\CachedTranslator'],
|
||||
];
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user