Search code examples
symfonycachingsymfony-2.8

Add translations that should not be cached from Controller


In my app, I have two sorts of translations:

  • Static wordings that are part of the template layout (like "Previous","Cancel"...)
  • Dynamic wordings that are extracted from database and can change for every request (like a blog article title that can vary in database)

I use the Symfony translator service to use static wording in my twig templates, with the trans filter. It works fine with static wordings, but with dynamic wordings things are getting difficult.

I add my dynamic wordings like that, inside a controller action:

    $trans = $this->get( 'translator' );

    $trans->addLoader('array', new ArrayLoader());
    $trans->addResource('array', array('BLOG_ARTICLE_TITLE'=>$article->getTitle('french')), 'fr', 'messages');

    // ...

    return new Response();

And then, I use it with trans on my templates or with BazingaJsTranslationBundle in my frontend app.

I guess I have an issue with the cache : for dynamic wordings, I often get the old wording or the translation key on the page - even when the adding is done on the controller before returning the Response.

But when I clear the cache (app/console clear:cache) and reload the page, I get the right wordings.

Is there a way to tell Symfony to not cache dynamically added wordings ? Or another translator method that suits more the dynamic addition of translations ?


Solution

  • Symfony Documentation:

    Translating Database Content

    The translation of database content should be handled by Doctrine through the Translatable Extension or the Translatable Behavior (PHP 5.4+). For more information, see the documentation for these libraries.

    Which is used like this:

    use Gedmo\Translatable\Translatable;
    
    // [...]
    class Article implements Translatable
    {
        /** @ODM\Id */
        private $id;
    
        /**
         * @Gedmo\Translatable
         * @ODM\String
         */
        private $title;
    
        /**
         * @Gedmo\Translatable
         * @ODM\String
         */
        private $content;
    
        /**
         * @Gedmo\Locale
         * Used locale to override Translation listener`s locale
         * this is not a mapped field of entity metadata, just a simple property
         */
        private $locale;
    

    For your specific problem:

    You can remove cache file manually Lexik translation bundle use this system. see their Translator.php class below

    public function removeLocalesCacheFiles(array $locales)
    {
        foreach ($locales as $locale) {
            $this->removeCacheFile($locale);
        }
        // also remove database.resources.php cache file
        $file = sprintf('%s/database.resources.php', $this->options['cache_dir']);
        if (file_exists($file)) {
            $this->invalidateSystemCacheForFile($file);
            unlink($file);
        }
        $metadata = $file.'.meta';
        if (file_exists($metadata)) {
            $this->invalidateSystemCacheForFile($metadata);
            unlink($metadata);
        }
    }
    /**
     * @param string $path
     *
     * @throws \RuntimeException
     */
    protected function invalidateSystemCacheForFile($path)
    {
        if (ini_get('apc.enabled')) {
            if (apc_exists($path) && !apc_delete_file($path)) {
                throw new \RuntimeException(sprintf('Failed to clear APC Cache for file %s', $path));
            }
        } elseif ('cli' === php_sapi_name() ? ini_get('opcache.enable_cli') : ini_get('opcache.enable')) {
            if (!opcache_invalidate($path, true)) {
                throw new \RuntimeException(sprintf('Failed to clear OPCache for file %s', $path));
            }
        }
    }