|
Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon. |
|
View previous topic :: View next topic |
Author |
Message |
felic Smarty Rookie
Joined: 22 Jul 2003 Posts: 9
|
Posted: Tue Mar 13, 2012 5:41 pm Post subject: Substitute for Smarty_Compiler reference |
|
|
Hi,
i currently upgrading from 2 -> 3. I have a compile plugin (which implements i18n gettext translation) that needs a reference to the origin smarty compiler (class Smarty_Compiler). That is because i like to interpolate template vars thru a helper class (Smarty_GettextHelper) which handles the translate and mapping stuff.
Former syntax is fine with Smarty 2:
Code: |
/**
* Smarty {i18n} compiler function plugin
*
* Type: compiler function
* Name: i18n
* Purpose: Translate string into requested language using gettext
*
* @param string containing var-attribute and value-attribute
* @param Smarty_Compiler
* @return Template code
*/
function smarty_compiler_i18n ($tag_attrs, &$compiler)
{
// make sure that we have access to the smarty compiler
// within Smarty_GettextHelper, because we need it to interpolate
// the template vars.
if (!(Smarty_GettextHelper::$compiler instanceof Smarty_Compiler)) {
Smarty_GettextHelper::$compiler = &$compiler;
}
/* ... quit few further code ... */
}
|
As there is no longer a dedicated Smarty_Compiler class in the current version of smarty, i am not sure how to substitute this. Hopefully there is a simple solution without a plugin rewrite from scratch. It seems i quit miss the spot where to look at within the new API.
Any hints are much appreciated.
greets
Olaf |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Tue Mar 13, 2012 6:19 pm Post subject: |
|
|
Smarty3 internals work completely different.
Without knowing what Smarty_GettextHelper and the rest of the plugin does I can't give hints. |
|
Back to top |
|
felic Smarty Rookie
Joined: 22 Jul 2003 Posts: 9
|
Posted: Tue Mar 13, 2012 7:53 pm Post subject: |
|
|
As the source code is well commented, i just post the two related files. Thanks for digging in.
Code: |
File: compiler.i18.php
/**
* Smarty {i18n} compiler function plugin
*
* Type: compiler function
* Name: i18n
* Purpose: Translate string into requested language using gettext
*
* @param string containing var-attribute and value-attribute
* @param Smarty_Compiler
* @return Template code
*/
function smarty_compiler_i18n ($tag_attrs, &$compiler)
{
// make sure that we have access to the smarty compiler
// within Smarty_GettextHelper, because we need it to interpolate
// the template vars.
if (!(Smarty_GettextHelper::$compiler instanceof Smarty_Compiler)) {
Smarty_GettextHelper::$compiler = &$compiler;
}
// skip processing if tag_attrs is empty
if (empty($tag_attrs)) {
$smarty->trigger_error("i18n: No message supplied", E_USER_WARNING);
return false;
}
if (preg_match(SMARTY_GETTEXT_REGEX_PLURAL_MATCH, $tag_attrs, $matches)) {
// import found strings to translate
$singular_string = $matches[1];
$plural_string = $matches[3];
$count = $matches[5];
// substitute escaped pipes
$singular_string = str_replace('\|', '|', $singular_string);
$plural_string = str_replace('\|', '|', $plural_string);
// do the first preg_replace run. we can go over the whole string, because the translator
// callback survives not used template vars.
preg_replace_callback(SMARTY_GETTEXT_REGEX_PLURAL_SUBSTITUTION, array("Smarty_GettextHelper",
"preg_collector_callback"), $tag_attrs);
// prepare first part of template code. we have to keep a serialized copy
// of the var map, because we don't have access to the compiler from the compiled
// template.
$template_code = "
\$map = '".addslashes(serialize(Smarty_GettextHelper::$map))."';
Smarty_GettextHelper::\$map = unserialize(stripslashes(\$map));
\$printf_args = array();
";
// now we need to write all variable->value mappings down, so that
// they can be used in vprintf(). we have to do that now, because
// otherwise it's impossible to access the template vars from the compiled
// template without using eval.
foreach (Smarty_GettextHelper::$map as $_key => $_value) {
$template_code .= "\$printf_args[".$_value['counter']."] = ".$_value['value'].";";
}
// last but not least we can complete the required code for the ngettext() call
// and for the variable substitution.
$template_code .= "
\$translated = ngettext(stripslashes('".addslashes($singular_string)."'),
stripslashes('".addslashes($plural_string)."'), ".$compiler->_parse_var_props($count).");
\$prepared = preg_replace_callback('".SMARTY_GETTEXT_REGEX_PLURAL_SUBSTITUTION."',
array('Smarty_GettextHelper', 'preg_translator_callback'), \$translated);
ksort(\$printf_args);
vprintf(\$prepared, \$printf_args);
";
// reset the map and the counter in our gettext helper class. if we don't do
// that, we'll waste resources and get weired results.
Smarty_GettextHelper::$map = array();
Smarty_GettextHelper::$counter = 1;
//return the created template code to the compiler
return $template_code;
} else {
// it's time to do our first preg_replace run to find all template vars we
// have to substitute and to create the map for the substitution that can
// be used by the compiled template.
preg_replace_callback(SMARTY_GETTEXT_REGEX_SINGULAR_SUBSTITUTION, array("Smarty_GettextHelper",
"preg_collector_callback"), $tag_attrs);
// prepare first part of template code. we have to keep a serialized copy
// of the var map, because we don't have access to the compiler from the compiled
// template.
$template_code = "
\$map = '".addslashes(serialize(Smarty_GettextHelper::$map))."';
Smarty_GettextHelper::\$map = unserialize(stripslashes(\$map));
\$printf_args = array();
";
// now we need to write all variable->value mappings down, so that
// they can be used in vprintf(). we have to do that now, because
// otherwise it's impossible to access the template vars from the compiled
// template without using eval.
foreach (Smarty_GettextHelper::$map as $_key => $_value) {
$template_code .= "\$printf_args[".$_value['counter']."] = ".$_value['value'].";";
}
// last but not least we can complete the required code for the gettext() call
// and for the variable substitution.
$template_code .= "
\$translated = gettext(stripslashes('".addslashes($tag_attrs)."'));
\$prepared = preg_replace_callback('".SMARTY_GETTEXT_REGEX_SINGULAR_SUBSTITUTION."',
array('Smarty_GettextHelper', 'preg_translator_callback'), \$translated);
ksort(\$printf_args);
vprintf(\$prepared, \$printf_args);
";
// reset the map and the counter in our gettext helper class. if we don't do
// that, we'll waste resources and get weired results.
Smarty_GettextHelper::$map = array();
Smarty_GettextHelper::$counter = 1;
// return the created template code to the compiler
return $template_code;
}
}
|
Code: |
File: Smarty_GettextHelper.class.php
/**
* Regex constant for Smarty::Gettext defining the match regex for plural forms
*
* @var string
*/
define('SMARTY_GETTEXT_REGEX_PLURAL_MATCH',
'=^((.*?)[^\x5c])\|((.*?)[^\x5c])\|\W*([0-9]+|\$[a-z0-9_.\x7c]+)$=im');
/**
* Regex constant for Smarty::Gettext defining the search pattern for template
* variables in singular phrases.
*
* @var string
*/
define('SMARTY_GETTEXT_REGEX_SINGULAR_SUBSTITUTION', '=`%([a-z0-9_.\x3a]+?)`=i');
/**
* Regex constant for Smarty::Gettext defining the search pattern for template
* variables in plural phrases.
*
* @var string
*/
define('SMARTY_GETTEXT_REGEX_PLURAL_SUBSTITUTION', '=`%([a-z0-9_.\x3a]+?)`=i');
class Smarty_GettextHelper
{
/**
* Smarty_Compiler instance
*
* @var object
*/
public static $compiler = null;
/**
* Temporary map for template vars
*
* @var array
*/
public static $map = array();
/**
* Template var counter
*
* @var int
*/
public static $counter = 1;
/**
* Callback for preg_replace_callback(). Searches preg matches for template vars.
* Found vars will be added to the template var map. Takes array with preg matches
* as first argument.
*
* @param array Preg matches
*/
public static function preg_collector_callback ($matches)
{
// make sure we add a var only once
if (!array_key_exists($matches[0], Smarty_GettextHelper::$map)) {
$matches[1] = str_replace(':', '|', $matches[1]);
Smarty_GettextHelper::$map[$matches[0]] = array(
'counter' => Smarty_GettextHelper::$counter,
'value' => Smarty_GettextHelper::$compiler->_parse_var_props('$'.$matches[1])
);
Smarty_GettextHelper::$counter++;
}
}
/**
* Callback for preg_replace_callback(). Searches preg matches for template vars
* and replaces them with sprintf() placeholders. Takes array with preg matches
* as first argument, returns string.
*
* @param array Preg matches
* @return string
*/
public static function preg_translator_callback ($matches)
{
return ' %'.Smarty_GettextHelper::$map[$matches[0]]['counter'].'$s';
}
}
| [/quote] |
|
Back to top |
|
U.Tews Administrator
Joined: 22 Nov 2006 Posts: 5068 Location: Hamburg / Germany
|
Posted: Tue Mar 13, 2012 10:21 pm Post subject: |
|
|
As I see it you needed the compiler to for the passed attribute values as Smarty 2 did pass the complete source string.
Smarty 3 works different for compiled plugins. you will receive an array of attributes where the parameter ´values are already precompiled.
template example:
Code: | {example foo=$bar buh="something"} |
Smarty 3 compiler.example.php
Code: | function smarty_compiler_example($params, $smarty)
{
var_dump($params);
return '<?php echo '.$params['foo'].';?>';
} |
The var_dump will show the precompiled attribute values like:
array(2) { ["foo"]=> string(36) "$_smarty_tpl->tpl_vars['bar']->value" ["buh"]=> string(11) ""something"" }
The returned compiled output will be:
'<?php echo $_smarty_tpl->tpl_vars['bar']->value;?>'
So there should be no need to access the compiler itself in Smarty 3. |
|
Back to top |
|
felic Smarty Rookie
Joined: 22 Jul 2003 Posts: 9
|
Posted: Wed Mar 14, 2012 5:36 pm Post subject: |
|
|
Thanks a lot for your answer. Marvelous, this spares a lot of code at least
And if i quote the string like that
i get nearly the same portions of source strings which fits the .mo translation strings.
Thx again, greets |
|
Back to top |
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|
|