// fixed parsing and display for back office translations

// die2Exception in AdminTranslationsController
This commit is contained in:
mMarinetti
2011-11-20 23:35:21 +00:00
parent 6d6645b761
commit ac6cc5f13e
2 changed files with 200 additions and 52 deletions
@@ -26,6 +26,7 @@
<h2>{l s='Language'} : {$lang} - {$translation_type}</h2> <h2>{l s='Language'} : {$lang} - {$translation_type}</h2>
{l s='Expressions to translate'} : <b>{$count}</b>. {l s='Click on the titles to open fieldsets'}.<br /><br /> {l s='Expressions to translate'} : <b>{$count}</b>. {l s='Click on the titles to open fieldsets'}.<br /><br />
<p>{l s='total missing expresssions:'} {$missing_translations|array_sum} </p>
{$limit_warning} {$limit_warning}
{if !$suoshin_exceeded} {if !$suoshin_exceeded}
<form method="post" action="{$url_submit}" class="form"> <form method="post" action="{$url_submit}" class="form">
@@ -36,36 +37,32 @@
<br /><br /> <br /><br />
{foreach $tabsArray as $k => $newLang} {foreach $tabsArray as $k => $newLang}
{if !empty($newLang)} {if !empty($newLang)}
{$occurrences = $newLang|array_count_values}
{if isset($occurrences[''])}
{$missing_translations = $occurrences['']}
{else}
{$missing_translations = 0}
{/if}
<fieldset> <fieldset>
<legend style="cursor : pointer" onclick="$('#{$k}-tpl').slideToggle();">{$k} - <font color="blue">{$newLang|count}</font> {l s='expressions'} (<font color="red">{$missing_translations}</font>)</legend> <legend style="cursor : pointer" onclick="$('#{$k}-tpl').slideToggle();">
<div name="{$type}_div" id="{$k}-tpl" style="display:{if $missing_translations}block{else}none{/if}"> {$k} - <font color="blue">{$newLang|count}</font> {l s='expressions'}
<table cellpadding="2"> {if isset($missing_translations[$k])}(<font color="red">{$missing_translations[$k]} {l s='missing'}</font>){/if}
{foreach $newLang as $key => $value} </legend>
<tr> <div name="{$type}_div" id="{$k}-tpl" style="display:{if isset($missing_translations[$k])}block{else}none{/if}">
<td style="width: 40%">{$key|stripslashes}</td> <table cellpadding="2">
<td>= {foreach $newLang as $key => $value}
{if $key|strlen < $textarea_sized} <tr>
<input type="text" <td style="width: 40%">{$key|stripslashes}</td>
style="width: 450px" <td>= {*todo : md5 is already calculated in AdminTranslationsController*}
name="{if $type == 'front' || $type == 'fields'}{$k}_{$key|md5}{else}{$k}{$key|md5}{/if}" {if $key|strlen < $textarea_sized}
value="{$value|regex_replace:'#"#':'&quot;'|stripslashes}" /> <input type="text"
{else} style="width: 450px"
<textarea rows="{($key|strlen / $textarea_sized)|intval}" name="{if in_array($type, array('front', 'fields'))}{$k}_{$key|md5}{else}{$k}{$key|md5}{/if}"
style="width: 450px" value="{$value|htmlentitiesUTF8}" />
name="{if $type == 'front' || $type == 'fields'}{$k}_{$key|md5}{else}{$k}{$key|md5}{/if}"> {else}
{$value|regex_replace:'#"#':'&quot;'|stripslashes} <textarea rows="{($key|strlen / $textarea_sized)|intval}"
</textarea> style="width: 450px"
{/if} name="{if in_array($type, array('front', 'fields'))}{$k}_{$key|md5}{else}{$k}{$key|md5}{/if}"
</td> >{$value}</textarea>
</tr> {/if}
{/foreach} </td>
</table> </tr>
{/foreach}
</table>
</div> </div>
</fieldset><br /> </fieldset><br />
{/if} {/if}
+174 -23
View File
@@ -735,19 +735,26 @@ class AdminTranslationsControllerCore extends AdminController
if (count($this->_errors) == 0) if (count($this->_errors) == 0)
Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$this->token.$params_redirect); Tools::redirectAdmin(self::$currentIndex.'&conf=4&token='.$this->token.$params_redirect);
} }
/** include file $dir/$file and return the var $var declared in it.
* This create the file if not exists
* @param string $dir
* @param string $file
* @param string $var var to return (_LANGADM, _LANG, _FIELDS, _ERRORS)
* return array
*/
public function fileExists($dir, $file, $var) public function fileExists($dir, $file, $var)
{ {
${$var} = array(); ${$var} = array();
if (!file_exists($dir)) if (!file_exists($dir))
if (!mkdir($dir, 0700)) if (!mkdir($dir, 0700))
die('Please create the directory '.$dir); throw new PrestashopException('Directory '.$dir.' cannot be created.');
if (!file_exists($dir.'/'.$file)) if (!file_exists($dir.DIRECTORY_SEPARATOR.$file))
if (!file_put_contents($dir.'/'.$file, "<?php\n\nglobal \$".$var.";\n\$".$var." = array();\n\n?>")) if (!file_put_contents($dir.'/'.$file, "<?php\n\nglobal \$".$var.";\n\$".$var." = array();\n\n?>"))
die('Please create a "'.$file.'" file in '.$dir); throw new PrestashopException('File "'.$file.'" doesn\'t exists and cannot be created in '.$dir);
if (!is_writable($dir.'/'.$file)) if (!is_writable($dir.DIRECTORY_SEPARATOR.$file))
$this->displayWarning(Tools::displayError('This file must be writable:').' '.$dir.'/'.$file); $this->displayWarning(Tools::displayError('This file must be writable:').' '.$dir.'/'.$file);
include($dir.'/'.$file); include($dir.DIRECTORY_SEPARATOR.$file);
return ${$var}; return ${$var};
} }
@@ -851,6 +858,7 @@ class AdminTranslationsControllerCore extends AdminController
public function initFormFront($lang) public function initFormFront($lang)
{ {
$missing_translations = array();
$_LANG = $this->fileExists(_PS_THEME_DIR_.'lang', Tools::strtolower($lang).'.php', '_LANG'); $_LANG = $this->fileExists(_PS_THEME_DIR_.'lang', Tools::strtolower($lang).'.php', '_LANG');
$str_output = ''; $str_output = '';
@@ -861,7 +869,7 @@ class AdminTranslationsControllerCore extends AdminController
foreach ($templates AS $template) foreach ($templates AS $template)
if (preg_match('/^(.*).tpl$/', $template) AND (file_exists($tpl = _PS_THEME_DIR_.$template) OR file_exists($tpl = _PS_ALL_THEMES_DIR_.$template))) if (preg_match('/^(.*).tpl$/', $template) AND (file_exists($tpl = _PS_THEME_DIR_.$template) OR file_exists($tpl = _PS_ALL_THEMES_DIR_.$template)))
{ {
$template2 = substr(basename($template), 0, -4); $prefix_key = substr(basename($template), 0, -4);
$newLang = array(); $newLang = array();
$fd = fopen($tpl, 'r'); $fd = fopen($tpl, 'r');
$content = fread($fd, filesize($tpl)); $content = fread($fd, filesize($tpl));
@@ -879,12 +887,22 @@ class AdminTranslationsControllerCore extends AdminController
$newLang[$key] = ''; $newLang[$key] = '';
} }
else else
{ {
$key2 = $template2.'_'.md5($key); // Caution ! front has underscore between prefix key and md5, back has not
$newLang[$key] = (key_exists($key2, $_LANG)) ? html_entity_decode($_LANG[$key2], ENT_COMPAT, 'UTF-8') : ''; if (isset($_LANG[$prefix_key.'_'.md5($key)]))
// @todo check if stripslashes is needed, it wasn't present in 1.4
$newLang[$key] = stripslashes(html_entity_decode($_LANG[$prefix_key.'_'.md5($key)], ENT_COMPAT, 'UTF-8'));
else
{
$newLang[$key] = '';
if (!isset($missing_translations[$prefix_key]))
$missing_translations[$prefix_key] = 1;
else
$missing_translations[$prefix_key]++;
}
} }
} }
$tabsArray[$template2] = $newLang; $tabsArray[$prefix_key] = $newLang;
$count += sizeof($newLang); $count += sizeof($newLang);
} }
@@ -892,6 +910,7 @@ class AdminTranslationsControllerCore extends AdminController
$tpl->assign(array( $tpl->assign(array(
'lang' => Tools::strtoupper($lang), 'lang' => Tools::strtoupper($lang),
'translation_type' => $this->l('Front-Office translations'), 'translation_type' => $this->l('Front-Office translations'),
'missing_translations' => $missing_translations,
'count' => $count, 'count' => $count,
'limit_warning' => $this->displayLimitPostWarning($count), 'limit_warning' => $this->displayLimitPostWarning($count),
'suoshin_exceeded' => $this->suhosin_limit_exceed, 'suoshin_exceeded' => $this->suhosin_limit_exceed,
@@ -909,8 +928,10 @@ class AdminTranslationsControllerCore extends AdminController
{ {
$_LANGADM = $this->fileExists(_PS_TRANSLATIONS_DIR_.$lang, 'admin.php', '_LANGADM'); $_LANGADM = $this->fileExists(_PS_TRANSLATIONS_DIR_.$lang, 'admin.php', '_LANGADM');
$str_output = ''; $str_output = '';
/* List templates to parse */ // count will contain the number of expressions of the page
$count = 0; $count = 0;
$missing_translations = array();
// parsing .php files
$tabs = scandir(_PS_ADMIN_CONTROLLER_DIR_); $tabs = scandir(_PS_ADMIN_CONTROLLER_DIR_);
$tabs[] = '../../classes/AdminController.php'; $tabs[] = '../../classes/AdminController.php';
$files = array(); $files = array();
@@ -919,19 +940,36 @@ class AdminTranslationsControllerCore extends AdminController
if (preg_match('/^(.*)\.php$/', $tab) AND file_exists($tpl = _PS_ADMIN_CONTROLLER_DIR_.$tab)) if (preg_match('/^(.*)\.php$/', $tab) AND file_exists($tpl = _PS_ADMIN_CONTROLLER_DIR_.$tab))
{ {
// -4 becomes -14 to remove the ending "Controller.php" from the filename // -4 becomes -14 to remove the ending "Controller.php" from the filename
$tab = basename(substr($tab, 0, -14)); $prefix_key = basename(substr($tab, 0, -14));
// @todo this is retrcompatible, but we should not leave this
if( $prefix_key == 'Admin')
$prefix_key = 'AdminTab';
$fd = fopen($tpl, 'r'); $fd = fopen($tpl, 'r');
$content = fread($fd, filesize($tpl)); $content = fread($fd, filesize($tpl));
fclose($fd); fclose($fd);
$regex = '/this->l\(\''._PS_TRANS_PATTERN_.'\'[\)|\,]/U'; $regex = '/this->l\(\''._PS_TRANS_PATTERN_.'\'[\)|\,]/U';
preg_match_all($regex, $content, $matches); preg_match_all($regex, $content, $matches);
foreach ($matches[1] AS $key) foreach ($matches[1] AS $key)
$tabsArray[$tab][$key] = stripslashes(key_exists($tab.md5($key), $_LANGADM) ? html_entity_decode($_LANGADM[$tab.md5($key)], ENT_COMPAT, 'UTF-8') : ''); {
$count += isset($tabsArray[$tab]) ? sizeof($tabsArray[$tab]) : 0; // Caution ! front has underscore between prefix key and md5, back has not
if (isset($_LANGADM[$prefix_key.md5($key)]))
$tabsArray[$prefix_key][$key] = stripslashes(html_entity_decode($_LANGADM[$prefix_key.md5($key)], ENT_COMPAT, 'UTF-8'));
else
{
$tabsArray[$prefix_key][$key] = '';
if (!isset($missing_translations[$prefix_key]))
$missing_translations[$prefix_key] = 1;
else
$missing_translations[$prefix_key]++;
}
}
$count += isset($tabsArray[$prefix_key]) ? sizeof($tabsArray[$prefix_key]) : 0;
} }
foreach (array('header.inc', 'footer.inc', 'index', 'login', 'password', 'functions') AS $tab) foreach (array('header.inc', 'footer.inc', 'index', 'login', 'password', 'functions') AS $tab)
{ {
$prefix_key = 'index';
$tab = _PS_ADMIN_DIR_.'/'.$tab.'.php'; $tab = _PS_ADMIN_DIR_.'/'.$tab.'.php';
$fd = fopen($tab, 'r'); $fd = fopen($tab, 'r');
$content = fread($fd, filesize($tab)); $content = fread($fd, filesize($tab));
@@ -939,10 +977,83 @@ class AdminTranslationsControllerCore extends AdminController
$regex = '/translate\(\''._PS_TRANS_PATTERN_.'\'\)/U'; $regex = '/translate\(\''._PS_TRANS_PATTERN_.'\'\)/U';
preg_match_all($regex, $content, $matches); preg_match_all($regex, $content, $matches);
foreach ($matches[1] AS $key) foreach ($matches[1] AS $key)
$tabsArray['index'][$key] = stripslashes(key_exists('index'.md5($key), $_LANGADM) ? html_entity_decode($_LANGADM['index'.md5($key)], ENT_COMPAT, 'UTF-8') : ''); {
// Caution ! front has underscore between prefix key and md5, back has not
if (isset($_LANGADM[$prefix_key.md5($key)]))
$tabsArray[$prefix_key][$key] = stripslashes(html_entity_decode($_LANGADM[$prefix_key.md5($key)], ENT_COMPAT, 'UTF-8'));
else
{
$tabsArray[$prefix_key][$key] = '';
if (!isset($missing_translations[$prefix_key]))
$missing_translations[$prefix_key] = 1;
else
$missing_translations[$prefix_key]++;
}
}
$count += isset($tabsArray['index']) ? sizeof($tabsArray['index']) : 0; $count += isset($tabsArray['index']) ? sizeof($tabsArray['index']) : 0;
} }
/* List templates to parse */
$templates = $this->listFiles(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes'.DIRECTORY_SEPARATOR.'template');
foreach ($templates AS $template)
if (preg_match('/^(.*).tpl$/', $template))
{
//$tpl = _PS_ADMIN_DIR_.'/themes/template/'.$template;
$tpl = $template;
// get controller name instead of file name
$prefix_key = Tools::toCamelCase(str_replace(_PS_ADMIN_DIR_.DIRECTORY_SEPARATOR.'themes'.DIRECTORY_SEPARATOR.'template'.DIRECTORY_SEPARATOR, '', $tpl), true);
$prefix_key = 'Admin'.substr($prefix_key, 0, strpos($prefix_key, DIRECTORY_SEPARATOR));
// @todo retrompatibility : we assume here than files directly in template/
// use the prefix "AdminTab (like old php files 'header', 'footer.inc', 'index', 'login', 'password', 'functions'
if( $prefix_key == 'Admin')
$prefix_key = 'AdminTab';
// and helpers in helper
$newLang = array();
$fd = fopen($tpl, 'r');
$content = fread($fd, filesize($tpl));
/* Search language tags (eg {l s='to translate'}) */
$regex = '/\{l s=\''._PS_TRANS_PATTERN_.'\'( js=1)?\}/U';
preg_match_all($regex, $content, $matches);
/* Get string translation for each tpl file */
foreach($matches[1] AS $english_string)
{
if(empty($english_string))
{
$this->_errors[] = $this->l('Error in template - Empty string found, please edit:').' <br />'.$tpl;
$newLang[$english_string] = '';
}
else
{
$trans_key = $prefix_key.md5($english_string);
if (isset($_LANGADM[$trans_key]))
{
$newLang[$english_string] = html_entity_decode($_LANGADM[$trans_key], ENT_COMPAT, 'UTF-8');
}
else
{
$newLang[$english_string] = '';
if(!isset($missing_translations[$prefix_key]))
$missing_translations[$prefix_key] = 1;
else
$missing_translations[$prefix_key]++;
}
}
}
if( isset($tabsArray[$prefix_key]))
$tabsArray[$prefix_key] = array_merge($tabsArray[$prefix_key], $newLang);
else
$tabsArray[$prefix_key] = $newLang;
$count += sizeof($newLang);
}
// with php then tpl files, order can be a mess
asort($tabsArray);
// @todo : something to make differences between .php and .tpl
$tpl = $this->context->smarty->createTemplate('translations/translation_form.tpl'); $tpl = $this->context->smarty->createTemplate('translations/translation_form.tpl');
$tpl->assign(array( $tpl->assign(array(
'lang' => Tools::strtoupper($lang), 'lang' => Tools::strtoupper($lang),
@@ -954,6 +1065,7 @@ class AdminTranslationsControllerCore extends AdminController
'toggle_button' => $this->displayToggleButton(), 'toggle_button' => $this->displayToggleButton(),
'auto_translate' => $this->displayAutoTranslate(), 'auto_translate' => $this->displayAutoTranslate(),
'tabsArray' => $tabsArray, 'tabsArray' => $tabsArray,
'missing_translations' => $missing_translations,
'textarea_sized' => TEXTAREA_SIZED, 'textarea_sized' => TEXTAREA_SIZED,
'type' => 'back' 'type' => 'back'
)); ));
@@ -1551,6 +1663,7 @@ class AdminTranslationsControllerCore extends AdminController
} }
return $array_files; return $array_files;
} }
public function initFormModules($lang) public function initFormModules($lang)
{ {
global $_MODULES; global $_MODULES;
@@ -1624,6 +1737,7 @@ class AdminTranslationsControllerCore extends AdminController
{ {
$lang = Tools::strtolower(Tools::getValue('lang')); $lang = Tools::strtolower(Tools::getValue('lang'));
$_LANG = array(); $_LANG = array();
$missing_translations = array();
$str_output = ''; $str_output = '';
if (!Validate::isLangIsoCode($lang)) if (!Validate::isLangIsoCode($lang))
@@ -1642,16 +1756,16 @@ class AdminTranslationsControllerCore extends AdminController
@include($i18n_file); @include($i18n_file);
$files = array(); $files = array();
$count = 0; $count = 0;
$tab = 'PDF'; $prefix_key = 'PDF';
$tabsArray = array($tab=>array()); $tabsArray = array($prefix_key=>array());
$regex = '/self::l\(\''._PS_TRANS_PATTERN_.'\'[\)|\,]/U'; $regex = '/self::l\(\''._PS_TRANS_PATTERN_.'\'[\)|\,]/U';
// need to parse PDF.php in order to find $regex and add this to $tabsArray // need to parse PDF.php in order to find $regex and add this to $tabsArray
// this has to be done for the core class, and eventually for the override // this has to be done for the core class, and eventually for the override
foreach (glob(_PS_CLASS_DIR_.'pdf/'."*.php") as $filename) foreach (glob(_PS_CLASS_DIR_.'pdf/'."*.php") as $filename)
{ {
$tabsArray = $this->_parsePdfClass($filename, $regex, $_LANGPDF, $tab, $tabsArray); $tabsArray = $this->_parsePdfClass($filename, $regex, $_LANGPDF, $prefix_key, $tabsArray);
if (file_exists(_PS_ROOT_DIR_.'/override/classes/pdf/'.basename($filename))) if (file_exists(_PS_ROOT_DIR_.'/override/classes/pdf/'.basename($filename)))
$tabsArray = $this->_parsePdfClass(_PS_ROOT_DIR_.'/override/classes/pdf/'.basename($filename), $regex, $_LANGPDF, $tab, $tabsArray); $tabsArray = $this->_parsePdfClass(_PS_ROOT_DIR_.'/override/classes/pdf/'.basename($filename), $regex, $_LANGPDF, $prefix_key, $tabsArray);
} }
// parse pdf template // parse pdf template
@@ -1661,11 +1775,23 @@ class AdminTranslationsControllerCore extends AdminController
{ {
preg_match_all($regex, file_get_contents($filename), $matches); preg_match_all($regex, file_get_contents($filename), $matches);
foreach ($matches[1] as $key) foreach ($matches[1] as $key)
$tabsArray[$tab][$key] = stripslashes(key_exists($tab.md5(addslashes($key)), $_LANGPDF) ? html_entity_decode($_LANGPDF[$tab.md5(addslashes($key))], ENT_COMPAT, 'UTF-8') : ''); {
// Caution ! front has underscore between prefix key and md5, back has not
if (isset($_LANGPDF[$prefix_key.md5($key)]))
// @todo check key : md5($key) was initially md5(addslashes($key))
$tabsArray[$prefix_key][$key] = (html_entity_decode($_LANGPDF[$prefix_key.md5($key)], ENT_COMPAT, 'UTF-8'));
else
{
$tabsArray[$prefix_key][$key] = '';
if (!isset($missing_translations[$prefix_key]))
$missing_translations[$prefix_key] = 1;
else
$missing_translations[$prefix_key]++;
}
}
} }
$count += isset($tabsArray[$tab]) ? sizeof($tabsArray[$tab]) : 0; $count += isset($tabsArray[$prefix_key]) ? sizeof($tabsArray[$prefix_key]) : 0;
$tpl = $this->context->smarty->createTemplate('translations/translation_form.tpl'); $tpl = $this->context->smarty->createTemplate('translations/translation_form.tpl');
$tpl->assign(array( $tpl->assign(array(
@@ -1680,6 +1806,7 @@ class AdminTranslationsControllerCore extends AdminController
'textarea_sized' => TEXTAREA_SIZED, 'textarea_sized' => TEXTAREA_SIZED,
'type' => 'pdf', 'type' => 'pdf',
'tabsArray' => $tabsArray, 'tabsArray' => $tabsArray,
'missing_translations' => $missing_translations,
)); ));
return $tpl->fetch(); return $tpl->fetch();
} }
@@ -1698,4 +1825,28 @@ class AdminTranslationsControllerCore extends AdminController
closedir($dir); closedir($dir);
return isset($themes) ? $themes : array(); return isset($themes) ? $themes : array();
} }
/** recursively list files in directory $dir
*
*/
public function listFiles($dir, $list = array())
{
$fileext = 'tpl';
$res = true;
$dir = rtrim($dir,'/').DIRECTORY_SEPARATOR;
$toParse = scandir($dir);
// copied (and kind of) adapted from AdminImages.php
foreach ($toParse AS $file)
{
if ($file!='.' AND $file != '..' AND $file != '.svn')
{
if (preg_match('#'.preg_quote($fileext,'#').'$#i',$file))
$list[] = $dir.$file;
else if (is_dir($dir.$file))
$list = $this->listFiles($dir.$file, $list);
}
}
return $list;
}
} }