Smarty Forum Index Smarty
WARNING: All discussion is moving to https://reddit.com/r/smarty, please go there! This forum will be closing soon.

Suggested small change to the smarty core

 
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Smarty Development
View previous topic :: View next topic  
Author Message
drbenway
Smarty n00b


Joined: 11 Jul 2010
Posts: 2

PostPosted: Sun Jul 11, 2010 10:51 am    Post subject: Suggested small change to the smarty core Reply with quote

I've been working on some translation tools. One problem we had was that we had many templates that were not actually being used. To remedy this problem I wrote a prefilter that, while a page is being loaded, grabs all the translatable text from a template and saves it along with a modified version of the template. But in order for this to work I needed to know the name of the template. I made a modified version of Smarty.class.php which adds this information as two class members: resource_name and (if the resource is a file) resource_file.

I implemented this in an older version of smarty: 2.6.25.


Last edited by drbenway on Sun Jul 11, 2010 10:57 am; edited 2 times in total
Back to top
View user's profile Send private message
drbenway
Smarty n00b


Joined: 11 Jul 2010
Posts: 2

PostPosted: Sun Jul 11, 2010 10:55 am    Post subject: Example usage: prefilter.extract.php Reply with quote

This prefilter extracts translatable text from a template and creates two files: a frame with text replaced by placeholders and a texts file with the removed texts.

Look for the reference to $smarty->resource_file towards the bottom

Code:

cat prefilter.extract.php

<?php
/**
 * extract texts from a template and save to a file ending .texts
 * replace with an array reference and save the modified
 * smarty to another file ending .frame
 */
function smarty_prefilter_extract($source,&$smarty) {
   Texts::reset($smarty->resource_name);

   $filtered = $source;
   $filtered = preg_replace_callback(
         '#(<?notrans>.*?</notrans)|((?:<?[^>]*>|^)\s*)([^<]+?)(\s*(?:</script|<|$))#is',
         '__html_extract',
         $filtered
      );

   $filtered = preg_replace_callback(
         '#((?:title|alt)\s*=\s*")([^"]*)#is',
         '__alt_extract',
         $filtered
      );

   $filtered = preg_replace('#({\s*)include#is', "$1".'showframe', $filtered);

   __save_filtered($filtered, $smarty);
   return $source;
}

class Texts {
   public static $res = '';
   public static $strings = array();
   public static $count = -1;
   public static $index = 0;
   public static $seen = array();

   public static function reset($resource_name) {
      self::$strings = array();
      self::$seen = array();
      self::$count = -1;
      self::$index = 0;
      self::$res = preg_replace(
         '#\W+#',
         "_",
         $resource_name
      );
   }

   public static function addString($string) {
      if (!isset(self::$seen[$string])) {
         self::$strings[++self::$count] = $string;
         self::$index = self::$count;
         self::$seen[$string] = self::$index;
      } else {
         self::$index = self::$seen[$string];
      }
   }
}

function __html_extract($matches) {
   # ignore some areas deliberately
   if (preg_match('#^notrans>#i',$matches[1])) return $matches[0];

   # ignore javascript blocks
   if (preg_match('#script#i',$matches[4])) return $matches[0];

   $strings = __strip_strings($matches[3]);
   $replaced = implode('',$strings);
   return $matches[2].$replaced.$matches[4];
}

function __alt_extract($matches) {
   $strings = __strip_strings($matches[2]);
   $replaced = implode('',$strings);
   return $matches[1].$replaced;
}

function __strip_strings($match) {
   $i = 0;
   $strings = array();
   // separate out {} tags from text
   foreach (str_split($match) as $c) {
      if ($c == '{') {
         if (count($strings)) $i++;
         $strings[$i] .= $c;
      } else if ($c == '}') {
         $strings[$i] .= $c;
         $i++;
      } else $strings[$i] .= $c;
   }
   for ($i = 0; $i < count($strings); $i++) {
      if (
         preg_match('#(?:^|\s)\w|\w(?:\s|$)#',$strings[$i])
         and !preg_match('#{#',$strings[$i])
         and !preg_match('#{php}#',$strings[$i-1])
      ) {
         # trim the whitespace but preserve it in the template
         preg_match('#^(\s*)(.*?)(\s*)$#s',$strings[$i],$m);
         Texts::addString($m[2]);
         $strings[$i] = $m[1].'{$texts.'.Texts::$res.'['.Texts::$index.']}'.$m[3];
      }
   }
   return $strings;
}

function __save_filtered($filtered, &$smarty) {
   global $textfiles;

   umask(octdec('0000'));
   $path = $smarty->resource_file;
   $path = preg_replace('#/templates/#','/frames/',$path);

   $dir = dirname($path);
   # if not check for the directory
   if (!is_dir($dir)) {
      if (!mkdir($dir)) die("can't make $path");
   }

   # always save the frame
   file_put_contents(
      "$path.frame",
      $filtered
   );

   # generate a string representation of the array
   $newtexts = var_export(Texts::$strings,true);
   # put a key in the statement so we can amalgamate
   # translations when we have more than one template
   $r = Texts::$res;
   $newtextscode = "<?php\n\$texts['$r'] = $newtexts;\n";

   $savetexts = true;
   # see if we've already processed this page before
   $tfile = "$path.texts";
   $textfiles[$tfile]++;
   if (is_file($tfile)) {
      $oldtextscode = file_get_contents($tfile);
      if ($oldtextscode == $newtextscode)
         $savetexts = false;
   }

   # save the texts only if they have changed
   if ($savetexts) {
      file_put_contents( $tfile, $newtextscode );
   }
}

Back to top
View user's profile Send private message
Display posts from previous:   
This forum is locked: you cannot post, reply to, or edit topics.   This topic is locked: you cannot edit posts or make replies.    Smarty Forum Index -> Smarty Development All times are GMT
Page 1 of 1

 
Jump to:  
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
Protected by Anti-Spam ACP