Issues

ZF-3930: When using caching with zend_tanslate it appears that no translation at all is performed

Description

When using caching with zend_tanslate it appears that no translation at all is performed


    function indexAction(){
        require_once 'Zend/Locale.php';
        require_once 'Zend/Translate.php';
        $config = Zend_Registry::get('config');
        $this->locale = new Zend_Locale($config->setup->defaultLocale);
        Zend_Registry::set('locale', $this->locale);
        Zend_Translate::setCache(Zend_Registry::get('cache'));
        Zend_Registry::set('Zend_Translate', new Zend_Translate('gettext', './Application/Locale/pl/default.mo', 'pl'));
    }

removing Zend_Translate::setCache(Zend_Registry::get('cache')); - makes app work fine

Comments

test case

I tried to work this into a more succinct use case:


<?php
$translations = array(
    'foo' => 'Foo Bar!',
    'boo' => 'Boo Hoo!',
);

$cacheOptions = array(
    'frontend' => array(
        'automatic_serialization' => true,
        'lifetime' => 3,
    ),
    'backend' => array(
        'cache_db_complete_path' => dirname(__FILE__) . '/translate.db',
    ),
);
$cache = Zend_Cache::factory('Core', 'Sqlite', $cacheOptions['frontend'], $cacheOptions['backend']);

$local = new Zend_Locale('en_US');
Zend_Translate::setCache($cache);
$translate = new Zend_Translate('array', $translations, 'en_US');

echo $translate->translate('foo');
echo $translate->translate('foo');
sleep(3);
echo $translate->translate('foo');
sleep(3);
echo $translate->translate('foo');

However, this worked fine. It may be an issue with the gettext adapter specifically, and I'll try that next.

The adapter classes themself have no access to the cache. They only read the data and connect them to the abstract class.

The behaviour of the cache is completly independent of the used adapter.

Okay, I tried the following now:


<?php
$cacheOptions = array(
    'frontend' => array(
        'automatic_serialization' => true,
        'lifetime' => 3,
    ),
    'backend' => array(
        'cache_db_complete_path' => dirname(__FILE__) . '/translate.db',
    ),
);
$cache = Zend_Cache::factory('Core', 'Sqlite', $cacheOptions['frontend'], $cacheOptions['backend']);

$locale = new Zend_Locale('en');
Zend_Translate::setCache($cache);
$translate = new Zend_Translate('gettext', dirname(__FILE__) . '/testcase/translate/Application/Locale/pl.mo', 'pl');

echo $translate->translate('o_object_added');
sleep(3);
echo $translate->translate('o_object_added');
sleep(3);
echo $translate->translate('o_object_added');
sleep(3);
echo $translate->translate('o_object_added');

I now get the following exception:


PHP Fatal error:  Uncaught exception 'Zend_Translate_Exception' with message 'Error opening translation file '/home/matthew/tmp/testcase/translate/Application/Locale/pl.mo'.' in /home/matthew/lib/framework-full/trunk/library/Zend/Translate/Adapter/Gettext.php:88

I get this error with or without caching. At this point, I cannot reproduce unless we get a valid translation file to test against.

default pl po file

Question:

Are you changing the locale when using the same cache ? Because actually caching is only done for the complete adapter...

When you set the cache and want to load another language afterwards it will not be recognised. Caching is only done for the complete adapter at initiation.

You should add all languages/files once.

There exists already an issue (ZF-3071) which will add this behaviour (caching on file-basis/adding translations afterwards to the cache). But it is not implemented for now.

The actual solution is to use a locale-based cache.

polish mo file

A po file will not be recognised by Zend_Translate... you should add the related binary gettext file (*.mo)

I've run the reproduce case I posted in an earlier comment against the .mo file linked in the issue, and it works both with and without caching.

Is the string you wanted to translate available in the mo file ? Try to use isTranslated() to verify.

Is the right data loaded ? Try to use getList() and getMessages() to verify.

Try the translation itself without application as showed by Matthew to verify if it works or not.


<?php
set_include_path('.' . PATH_SEPARATOR . './Library/'
. PATH_SEPARATOR . './Application/'
. PATH_SEPARATOR . get_include_path());
require 'Zend/Registry.php';
require 'Zend/Cache.php';
$cache = Zend_Cache::factory('Core', 'File' , array('automatic_serialization' => true, 'lifetime' => 3 ), array('cache_dir' =>'./Cache'));
Zend_Registry::set('cache',$cache);
require 'Zend/Controller/Front.php';
$frontController = Zend_Controller_Front::getInstance();
require_once 'Zend/Locale.php';
require_once 'Zend/Translate.php';
$locale = new Zend_Locale('pl');
Zend_Registry::set('locale', $locale);
Zend_Translate::setCache(Zend_Registry::get('cache'));
Zend_Registry::set('Zend_Translate', new Zend_Translate('gettext', './Application/Locale/pl/default.mo', 'pl'));
echo Zend_Registry::get('Zend_Translate')->translate('mainOptions');
?>

simplified test case

Running your testcode I get returned:

Ustawienia główne

Which seems to me like all is translated as required.

As noted on IRC, I've tried the above simplified test case, varying the cache lifetime as well as looping and setting random wait durations before translating -- in each case, I get the translated strings. This is looking like a caching issue.

the fix for the issue

on translate/adapter.php line 98:

add:

if($locale){$this->setLocale($locale); }

fixes the issue for me.

Fixed with r10915

Updating for the 1.6.0 release.