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

My multilang solution

 
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 -> Tips and Tricks
View previous topic :: View next topic  
Author Message
fabhren
Smarty Rookie


Joined: 29 Jun 2003
Posts: 9

PostPosted: Fri Aug 01, 2003 9:03 am    Post subject: My multilang solution Reply with quote

Greetz y'all,

I decided to 'share my lovin`' and show what a mess i made with AZTEK b-e-a-u-t-i-f-u-l-l multilang solution.

Put up a dir called xmlang. All files are [template_name]_[lang_initials].xml (eg index_de.xml).

And it goes:
Code:

<?xml version="1.0" encoding="utf-8" ?>
<xmlang lang="de">
   <header>
      <project>Project Name</project>
      <create>2003-01-12 17:24-0500</create>
      <revise>2003-01-15 19:15-0500</revise>
      <trans>Your Name - Your Email</trans>
      <lang>Deutsch</lang>
   </header>
   <message>
      <id>10190</id>
      <string>Vorwort</string>
   </message>
</xmlang>


As you can see, I indexed all translations. It gets complicated to do a decent translation when working with larger translation blocks. This way I can make an app that gets all english xml and give the option for one to build a new language.

Here goes the tpl:

Code:

<!-- 1o index.php -> header.tpl -->
<HTML>
<HEAD>
{popup_init src="$sJsDir/overlib.js"}
<TITLE>{#sTitle#}</TITLE>
<META content="{#sAuthor#} © {#sYear#}" name='Author'>
<META content="v1.0 ¤ 29-6-2003 " name='Template Version'>
{include file="css_style.tpl"}
</HEAD>
<BODY leftMargin="0" topMargin="0" MARGINHEIGHT="0" MARGINWIDTH="0" bgcolor="#ffffff">

<HR ALIGN="LEFT" WIDTH="100%"></DIV><DIV CLASS="PREFACE"><A NAME="PREFACE">{translate mlIndex=10190 mlPage=$mlPage mlLang=$mlLang}Preface{/translate}</A><P>
</BODY>
</HTML>


As you can see, and I believe herein lies the major difference, I keep the translation because designers can see it. I pass on the index, the multipage (index) and the language I want it translated to (de).

Here is the block.translate.php:

Code:

<?php

/*
 * Smarty plugin
 * -------------------------------------------------------------
 * File:     block.translate.php
 * Type:     block
 * Name:     translate
 * Purpose:  translate a block of text
 * Author: John (AZTEK) Downey
                http://delusive.dyn.ee
                http://sage.dev.box.sk
                http://blacksun.box.sk
 * Revised: Fabhren (erocha@fiveq.pt)
 * -------------------------------------------------------------
 */

$xml = array();

function smarty_block_translate($params, $content, &$smarty) {
   foreach($params as $key => $value) {
      $params["%$key"] = $value;
      unset($params[$key]);
   }
   if (!is_null($content)) print(t($content,$params));
}

function t($string, $args = array()) {
   global $xml;

   if(empty($xml)) {
      $xmlfile = SITE_LANG.$args["%mlPage"]."_".$args["%mlLang"].".xml";
      if(file_exists($xmlfile)) {
         $xml = getXmlTree($xmlfile);
      } else {
         return strtr($string, $args);
      }
   }

   foreach($xml[0]['children'] as $tag) {
      if($tag['tag'] == "MESSAGE") {
         if($tag['children'][0]['value'] == $args['%mlIndex']) {
            if($tag['children'][1]['value'] != "") {
               return strtr($tag['children'][1]['value'], $args);
            }
         }
      }
   }

   return strtr($string, $args);
}

function getChildren($vals, &$i) { 
   $children = array(); 
   
   if(!isset($vals[$i]['attributes'])) {
      $vals[$i]['attributes'] = "";
   }
   
   while(++$i < count($vals)) {
      if(!isset($vals[$i]['attributes'])) {
         $vals[$i]['attributes'] = "";
      }

      if(!isset($vals[$i]['value'])) {
         $vals[$i]['value'] = "";
      }

      switch ($vals[$i]['type']) {
      case 'complete':
         array_push($children, array('tag' => $vals[$i]['tag'], 'attributes' => $vals[$i]['attributes'], 'value' => $vals[$i]['value']));
         break;
      case 'open':
         array_push($children, array('tag' => $vals[$i]['tag'], 'attributes' => $vals[$i]['attributes'], 'children' => getChildren($vals, $i)));
         break;
      case 'close':
         return $children;
         break;
      }
   }

   return $children;
}

function getXmlTree($file) { 
   $data = implode("", file($file));
   $xml  = xml_parser_create();
   xml_parser_set_option($xml, XML_OPTION_SKIP_WHITE, 1);
   xml_parse_into_struct($xml, $data, $vals, $index);
   xml_parser_free($xml);

   $tree = array();
   $i = 0;
   array_push($tree, array('tag' => $vals[$i]['tag'], 'attributes' => $vals[$i]['attributes'], 'children' => getChildren($vals, $i)));

   return $tree;
}
?>


Here ! Hope someone finds it useful.

Bye
[/code]
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Fri Aug 01, 2003 9:37 am    Post subject: Reply with quote

I also like Azteks approach, although i never used it. There is just one thing that joscha mentionend ages ago ( http://www.phpinsider.com/smarty-forum/viewtopic.php?t=84&p=327#327 ) that should not be underestimated: the use of a prefilter for translation.

if the translation is done in a prefilter (with distinct compile_ids for each language) the translation can be done at compile-time of the template and not at display-time (like with a block-function). this is neglibible if you employ caching on your site, but if not, a prefilter would boost performance tremendously: the xml-files don't even have to be loaded and parsed anymore when displaying the page, once it was compiled.

just my 2c.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
fabhren
Smarty Rookie


Joined: 29 Jun 2003
Posts: 9

PostPosted: Fri Aug 01, 2003 11:33 am    Post subject: Reply with quote

I've checkec joscha solution but when you're dealing with heavy hitting db's like oracle, and you'll have to dump a bundle o'dough in extra language packs Evil or Very Mad , i'd rather build a small library of languages in xml, even if it takes the extra time to compile Confused .

As I am thinking of cacheing most of the scripts, those that are heavy on text are always cached, while the dynamic one's have less text to translate Wink .

In any case, xml to db is always a possibility ( when we can pay up for the extra functionality Rolling Eyes )
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Fri Aug 01, 2003 12:25 pm    Post subject: Reply with quote

maybe i misunderstand you or you misunderstood me.

i suggested a prefilter that does merely the same as your (or azteks (?)) block.translate.php . it should use the same xml-files and, if doable, use the same syntax in the templates as block.translate.php does.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
fabhren
Smarty Rookie


Joined: 29 Jun 2003
Posts: 9

PostPosted: Fri Aug 01, 2003 1:22 pm    Post subject: my bad Reply with quote

You're right messju I completely misunderstood you. That was, in fact, what I had in mind. I would keep the same structure but filter it a lot faster and having the complementary advantage to compile with a different compile_id for each language.

But I am just a small shrimp Embarassed in this ocean of smartiness Shocked . I am just beggining to grasp the extensiability of it all.

If anyone already has this whole prefilter business sorted out Very Happy , it would make my life a whole lot easier Cool

Thanx
Fabhren
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Fri Aug 01, 2003 2:30 pm    Post subject: Reply with quote

okay, some lunchbreak-hacking:

(i took azteks stuff from http://www.phpinsider.com/smarty-forum/viewtopic.php?p=326#326
to have functiont t() etc. )

[php:1:08301de9da]
<?php


function smarty_pcallback_translate($match) {
global $__compiler;

$_ld = $__compiler->left_delimiter;
$_rd = $__compiler->right_delimiter;

$string = $match[2];
$attrs = $__compiler->_parse_attrs($match[1]);
$params = array();
foreach ($attrs as $key=>$value) {
$params["%$key"] = $_ld . 'php' . $_rd
. ' echo ' . $value . '; '
. $_ld . '/php' . $_rd ;
}
return t($string, $params);
}


function smarty_prefilter_translate($source, $compiler) {
require_once($compiler->_get_plugin_filepath('shared', 'translate'));
$GLOBALS['__compiler'] =& $compiler;

$_pld = preg_quote($compiler->left_delimiter, '!');
$_prd = preg_quote($compiler->right_delimiter, '!');
$source = preg_replace_callback("!${_pld}translate(.*)$_prd(.*)$_pld/translate$_prd!Us",
'smarty_pcallback_translate', $source);

unset($GLOBALS['__compiler']);
return $source;
}

?>
[/php:1:08301de9da]

i know i won't win a price for beauty with it and there are some questionable design-issues with the one above, but aztek's example is working with it and maybe it's a starter for somebody who is in need of this Smile

greetings
messju
Back to top
View user's profile Send private message Send e-mail Visit poster's website
fabhren
Smarty Rookie


Joined: 29 Jun 2003
Posts: 9

PostPosted: Sat Aug 02, 2003 3:19 pm    Post subject: prefilter cant read template vars Reply with quote

Hyia messju,

Been fiddling witcha code and no can work Crying or Very sad , although it was an awesome solution Very Happy , but only in a postfilter stage.

If you check in the beginning I was sending the language by php to the template. If this is a prefilter, it parses BEFORE Shocked the var gets any value and afterwards he'll try to get the xml and it'll crash and burn Mad .

Do you have a hint to make it a postfilter Laughing ?

Thanx a lot in advance Cool
Fabhren
Back to top
View user's profile Send private message
messju
Administrator


Joined: 16 Apr 2003
Posts: 3336
Location: Oldenburg, Germany

PostPosted: Sat Aug 02, 2003 6:41 pm    Post subject: Reply with quote

hmm, making it a postfilter won't gain you anything.

as a hint: look at the results of $compilter->_parse_attrs();
you'll get a hash array with the attribute-name as a array-key and the php-code to obtain the attribute-value as the array-value.

if (you don't need compatibility to php5 yet and) do "$this =& $__compiler;" you can eval the array-values and should get the correct results (i hope i didn't spoil and hinted too much now). but this only works if the values where assigned from php and not within a template.

another way would be using $__compiler->compile_id to get the $lang and $__compiler->_current_file to get the template-name.

HTH and have a nice weekend Smile
messju
Back to top
View user's profile Send private message Send e-mail Visit poster's website
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 -> Tips and Tricks 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