caching translations for 10days and changing translation url, when translations are changing --> saves server-roundtrip for each translation

This commit is contained in:
Ralf Becker 2014-01-09 15:32:07 +00:00
parent 13572c472a
commit 400240f1e4
7 changed files with 57 additions and 41 deletions

View File

@ -135,14 +135,14 @@ class etemplate_new extends etemplate_widget_template
{
if (!in_array($l_app, array($currentapp, 'custom')))
{
$langRequire[$l_app] = array('app' => $l_app, 'lang' => $lang);
$langRequire[$l_app] = array('app' => $l_app, 'lang' => $lang, 'etag' => translation::etag($l_app, $lang));
}
}
foreach(array($currentapp, 'custom') as $l_app)
{
if (isset(translation::$loaded_apps[$l_app]))
{
$langRequire[$l_app] = array('app' => $l_app, 'lang' => translation::$loaded_apps[$l_app]);
$langRequire[$l_app] = array('app' => $l_app, 'lang' => translation::$loaded_apps[$l_app], 'etag' => translation::etag($l_app, translation::$loaded_apps[$l_app]));
}
}

View File

@ -378,6 +378,9 @@ class config
}
}
}
// some things need on client-side which are not direct configs
$client_config['phpgwapi']['lang_ctimes_md5'] = md5(json_encode(self::$configs['phpgwapi']['lang_ctimes']));
return $client_config;
}

View File

@ -428,6 +428,29 @@ class translation
}
}
/**
* Get a state / etag for a given app's translations
*
* We currently only use a single state for all none-instance-specific apps depending on lang_ctimes.
*
* @param string $_app
* @param string $_lang
* @return string
*/
static function etag($_app, $_lang)
{
if (!in_array($_app, translation::$instance_specific_translations))
{
$etag = md5(json_encode($GLOBALS['egw_info']['server']['lang_ctimes']));
}
else
{
$etag = md5(json_encode(egw_cache::getCache(egw_cache::INSTANCE, __CLASS__, $_app.':'.$_lang)));
}
error_log(__METHOD__."('$_app', '$_lang') returning '$etag'");
return $etag;
}
/**
* Loads translations for an application direct from the lang-file(s)
*

View File

@ -20,7 +20,7 @@ egw.extend('config', egw.MODULE_GLOBAL, function() {
/**
* Clientside config
*
*
* @access: private, use egw.config(_name, _app="phpgwapi")
*/
var configs = {};
@ -28,7 +28,7 @@ egw.extend('config', egw.MODULE_GLOBAL, function() {
return {
/**
* Query clientside config
*
*
* @param string _name name of config variable
* @param string _app default "phpgwapi"
* @return mixed
@ -37,14 +37,14 @@ egw.extend('config', egw.MODULE_GLOBAL, function() {
{
if (typeof _app == 'undefined') _app = 'phpgwapi';
if (typeof configs[_app] == 'undefined') return null;
return configs[_app][_name];
if (typeof this.configs[_app] == 'undefined') return null;
return this.configs[_app][_name];
},
/**
* Set clientside configuration for all apps
*
*
* @param array/object
*/
set_configs: function(_configs)

View File

@ -25,7 +25,7 @@ egw.extend('lang', egw.MODULE_GLOBAL, function() {
/**
* Translations
*
*
* @access: private, use egw.lang() or egw.set_lang_arr()
*/
var lang_arr = {};
@ -34,7 +34,7 @@ egw.extend('lang', egw.MODULE_GLOBAL, function() {
return {
/**
* Set translation for a given application
*
*
* @param string _app
* @param object _message message => translation pairs
* @memberOf egw
@ -46,10 +46,10 @@ egw.extend('lang', egw.MODULE_GLOBAL, function() {
lang_arr[_app] = _messages;
}
},
/**
* Translate a given phrase replacing optional placeholders
*
*
* @param string _msg message to translate
* @param string _arg1 ... _argN
*/
@ -62,7 +62,7 @@ egw.extend('lang', egw.MODULE_GLOBAL, function() {
}
var translation = _msg;
_msg = _msg.toLowerCase();
// search apps in given order for a replacement
var apps = this.lang_order || ['custom', this.getAppName(), 'etemplate', 'common'];
for(var i = 0; i < apps.length; ++i)
@ -75,9 +75,9 @@ egw.extend('lang', egw.MODULE_GLOBAL, function() {
}
}
if (arguments.length == 1) return translation;
if (arguments.length == 2) return translation.replace('%1', arguments[1]);
// to cope with arguments containing '%2' (eg. an urlencoded path like a referer),
// we first replace all placeholders '%N' with '|%N|' and then we replace all '|%N|' with arguments[N]
translation = translation.replace(/%([0-9]+)/g, '|%$1|');
@ -116,9 +116,10 @@ egw.extend('lang', egw.MODULE_GLOBAL, function() {
{
if (typeof lang_arr[_apps[i].app] === "undefined")
{
jss.push(this.webserverUrl
+ '/phpgwapi/lang.php?app='
+ _apps[i].app + '&lang=' + _apps[i].lang);
jss.push(this.webserverUrl +
'/phpgwapi/lang.php?app=' + _apps[i].app +
'&lang=' + _apps[i].lang +
'&etag=' + (_apps[i].etag || this.config('lang_ctimes_md5')));
}
apps.push(_apps[i].app);
}
@ -138,7 +139,7 @@ egw.extend('lang', egw.MODULE_GLOBAL, function() {
{
// Require a "ready postpone token"
var token = ready.readyWaitFor();
// Call "readyDone" once all js files have been included.
files.includeJS(jss, function () {
ready.readyDone(token);

View File

@ -457,7 +457,7 @@ egw.extend('links', egw.MODULE_GLOBAL, function() {
this.value = '';
});
// need to load common translations for app-names
this.includeJS([this.webserverUrl+'/phpgwapi/lang.php?app=common&lang='+this.preference('lang')], function(){
this.langRequire(window, [{app: 'common', lang: this.preference('lang')}], function(){
select.append(jQuery(document.createElement('option')).attr('value', '').text(self.lang('Add')+' ...'));
var apps = self.link_app_list('add');
for(var app in apps)

View File

@ -30,23 +30,15 @@ $GLOBALS['egw_info'] = array(
include '../header.inc.php';
// use an etag with app, lang and a hash over the creation-times of all lang-files
if (!in_array($_GET['app'], translation::$instance_specific_translations))
{
$etag = '"'.$_GET['app'].'-'.$_GET['lang'].'-'.md5(serialize($GLOBALS['egw_info']['server']['lang_ctimes'])).'"';
}
else
{
translation::add_app($_GET['app'], $_GET['lang']);
if (!count(translation::$lang_arr))
{
translation::add_app($_GET['app'], 'en');
}
$etag = '"'.$_GET['app'].'-'.$_GET['lang'].'-'.md5(serialize(translation::$lang_arr));
}
$etag = '"'.$_GET['app'].'-'.$_GET['lang'].'-'.translation::etag($_GET['app'], $_GET['lang']).'"';
// tell browser/caches to cache for one day, we change url on real modifications
$expires = 864000; // 10days
// headers to allow caching of one month
Header('Content-Type: text/javascript; charset=utf-8');
Header('Cache-Control: public, no-transform');
Header('Cache-Control: public, no-transform, max-age='.$expires);
header('Expires: ' . gmdate('D, d M Y H:i:s', time()+$expires) . ' GMT');
Header('Pragma: cache');
Header('ETag: '.$etag);
@ -57,13 +49,10 @@ if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $
common::egw_exit();
}
if (!in_array($_GET['app'], translation::$instance_specific_translations))
translation::add_app($_GET['app'], $_GET['lang']);
if (!count(translation::$lang_arr))
{
translation::add_app($_GET['app'], $_GET['lang']);
if (!count(translation::$lang_arr))
{
translation::add_app($_GET['app'], 'en');
}
translation::add_app($_GET['app'], 'en');
}
$content = 'egw.set_lang_arr("'.$_GET['app'].'", '.json_encode(translation::$lang_arr).');';