ZF-7787: cache not taking locale into id

Description

Someone replaced in private function _addTranslationData($data, $locale, array $options = array()) in Zend_Translate_Adapter:

$id = 'Zend_Translate_' . preg_replace('/[^a-zA-Z0-9_]/', '', $data) . '' . $locale . '_' . $this->toString();

with

$id = 'Zend_Translate_' . md5(serialize($data)) . '_' . $this->toString();

Now custom adapters that do not pass any locale info trough $data and using auto locale from browser, have same cache id for all languages (locales).

So I created my ($data = mysql) adapter but I can't use cache (+null $locales for auto locales detection) with it.

Comments

Internal caching is not done by locale but by given data (which is normally a filename). Otherwise caching for multilocale input like TMX or array files would not work.

Caching is a internal process. It has no effect on how translation works externally when the same data is provided.

It has effect. Lets say you use null $locale (browser determines locale) and you have mysql adapter for language. You can't put filename into $data since it is mysql. So $data = 'mysql' all the time.

Now someone enters with browser language EN - it gets saved in cache and next guest comes in with browser US (or other locale) it doesn't matter now since cache is loaded with EN for everyone until cache timeout. Id for EN and US locale is the same and locale is set in adapter if $locale = null.

So cache causes one language for all guests until cache timeout. Right now adapter acts as if there can only be files used to store translation. Other custom adapters will not work with cache and auto locale from browser.

When you say "regardless of what is called, it's always the same data"... then of course also cache expects that data is always the same.

With the actual aproach I see no problem even to use the old (errorous) behaviour when you are doing an individual adapter. You define within your adapter yourself what's being delivered to _addTranslationData and how it should behave.

The actual implementation works when single languages are seperated in multiple sources. It works when single languages are in single sources. And it works when multiple language are in single sources. Actually I see no single usecase where it does not work.

Beside that you are free to define what's written within cache and used as basis for caching. This is on your own implementation.

Look here:

bootstrap:

Zend_Translate::setCache($cache); $translate = new Zend_Translate('My_Translate_Adapter_Mysql', 'mysql', null, array('scan' => Zend_Translate::LOCALE_DIRECTORY, 'disableNotices' => true));

adapter:

<?php

class My_Translate_Adapter_Mysql extends Zend_Translate_Adapter { public function __construct($data, $locale = null, array $options = array()) { parent::__construct($data, $locale, $options); }

protected function _loadTranslationData($data, $locale, array $options = array())
{
       $this->_data = array();

//here i get translation data from mysql!

    if (!isset($this->_data[$locale])) {
        $this->_data[$locale] = array();
    }

    $this->_data[$locale] = array_merge($this->_data[$locale], $mysql_translated);  

    return $this->_data;
}

public function toString()
{
    return "Mysql";
}

}

Now tell me that "And it works when multiple language are in single sources." You can't. Cache will cause guests to see only ONE language that is currently cached.

I have fixed this by disabling cache in bootstrap and using standard cache in my adapter. But it will not cache options and other translations (in forms).

No reason to get angry.

Why are you not reading all translations into the cache (as it should be done) but instead only single translations ?

Example: The user says - I want only english - then you load only english and say english is the only supported language...

Why don't you, eighter load all languages at once, or load the languages on demand when you see they are not loaded ?

Well why would I want to load 3 times more data and process it every time someone opens page?

All that data is serialized must be loaded etc. Zend is slow enough - dont want to add to it. And I don't want to limit size of the translation database. There will be much multilanguage content. I also use per page translations - loading all at once is no fun.

Problem is only with cache id that is not using $locale. Only this that was working before is standing in my way to happines :P

The caching algorithm will can not be changed to use the locale as target. This would reintroduce several bugs and break several things.

But you could still load the translations on demand like described before.

Something like this mock example:


if (!$translate->isAvailable($locale)) {
    $translate->addTranslation($data, $locale, array('reload' => true));
}