TinyButStrong - the PHP Template Engine
Categories > Your tips & tricks >

Multilanguage Applications

The forum is closed. Please use Stack Overflow for submitting new questions. Use tags: tinybutstrong , opentbs

By: Skrol29
Date: 2005-04-18
Time: 01:11

Multilanguage Applications

TinyButStrong has an easy technique for multilanguage support in your applications.
The MergeField() method enables you to merge a set of TBS fields by passing them to a user function.

Technique 1 for text retrieved by its id:
function f_translate1($id_label) {
  global $curr_language;
  return get_text_from_id($curr_language,$id_label);

Technique 2 for text directly in the field:
[ml;text='hello world']
function m_translate2($id_label,&$PrmLst) {
  global $curr_language;
  return translate_txt($curr_language,$PrmLst['text']);
By: khanhvu
Date: 2006-09-14
Time: 12:21

Re: Multilanguage Applications

Dear Skrol29 !

I have read your Tips & Tricks of Multilanguage Applications but I can not understand how to start with this.

I'm working on a project that have multilanguage, ofcouse building with TBS.

With Traditional PHP, I will make a language file and define language text string then showing in template like this: {WELCOME}

In english.php:

In French.php:

How can I do this with TBS ?

Thank you very much  Mr Skrol29 !
By: Skrol29
Date: 2006-09-15
Time: 00:52

Re: Multilanguage Applications


I think it is faster when you save multilanguage strings into PHP variables instead of constant.
However, if you'd like to kepp constants, you can marge them using the same technique as above but with a function like this:
function f_translate1($id_label) {
  return @constant($id_label);

By the way : constants will be mergable using special var fields in TBS version 3.2.0 which is available in beta yet (see some messages before).
By: khanhvu
Date: 2006-09-15
Time: 06:29

Re: Multilanguage Applications

Thanks Mr Skrol,

I have made this works:

In en.php:
$lang['WELCOME'] = 'WELCOME';

In fr.php
$lang['WELCOME'] = 'BONJOUR';

In PHP file:
$lang = array($lang);

In HTML file:

Is this way better ?

I understand your translatel function but I don't understand its usage.

I mean how you make lang file, code file and html file with your function.

Can you explain more.

Thank you.
By: sheepy
Date: 2006-09-28
Time: 01:03

Re: Multilanguage Applications

Yes currently I also use you solution, khanhvu.

Skrol29's technique 1 is good in the sense that it is called once for each language id, so you don't have to load the whole language table, useful if language resource is stored in database, with reasonable performance if sql query cache is enabled.

Technique 2 is good in the sense that you can have localisation resources embeded in template.  Whlie it's fast and simple IMHO it will make addition of language more painful, although for most sites this will never happens.

If you have to load the whole table anyway, like if you are storing them in php or like if I am storing them in csv, then the way we do it works just fine.
But if you want more control or additional functionality like safeguard for missing index, then user function is the way to go.

In term of performance, since you're storing the array in php, with php optimisation like APC (Alternative PHP Cache) or Zend Cache you will have nothing to worry about.  They should be installed by most if not every shared web host.
By: Pirjo Posio
Date: 2007-09-25
Time: 15:38

Re: Multilanguage Applications

Here's a solution, that can be used for internationalization purposes or just data in one language, where you can store variables embedded in the database records, if you wish. Or some records may contain variables, some not.
This technique I would like to call template swapping. (Have a temporary template).
Here we have a login form (I borrowed one of Skrol29's, thank you!) and below the login form there is a one line message, that comes from the database, with some embedded variables. The database field is represented here by just a string.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<title>TBS - LoginForm and a stringtemplate for a translation</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" >

<form name="form1" method="post" action="[var..script_name]" style="height:14px;">
  <input name="txt_login" type="text" id="txt_login" size="6">
  <input name="txt_password" type="text" id="txt_password" size="6">
  <input name="btn_ok" type="submit" id="btn_ok" value="Ok">

  <span style="color: #FF0000">Bad login or password.[onload;block=span;when [var.err_log]=1]</span>
And the PHP:
include_once('../../hidden/tbs_class_php5.php') ;
$TBS = new clsTinyButStrong;
//Some initial values
$show_result = false;    //true=show the merge result, false=store it in a variable
$msglang = '';

if (isset($_POST['btn_ok'])) {
  // Imagine we check the login/password...
    $err_log = 1;
} else {
    $err_log = 0;
//To give the translations for the variables in the next lang table record
$lang = 'fi';
$theword = 'password';
$langword = 'salasana';
//$my_string mimics the record pulled out from db table lang
$my_string = "The word '[var.theword]' is '[var.langword]' in language [var.lang].";

$TBS->LoadTemplate('translation.htm');    //The original template
$template = $TBS->Source;    //Let's store the original template for a while
$TBS->Source = $my_string; //This is a temporary template
$TBS->MergeField('var');    //TBS should merge the 'var' tags even without this
if ($show_result==true) {   //We show the merge results of the temporary template
} else {                                 //We will not show the result, put it in a variable instead
$TBS->Show(TBS_NOTHING);    //Do not show the results, nor exit
$msglang = $TBS->Source;    //Let's store the result of the temporary merge.
$TBS->Source = $template;    //The original template is restored

//Merging of the original template is done here.
$TBS->MergeField('var');    //TBS should merge the 'var' tags even without this

Thanks for help given by Skrol29 and TomH! I hope this helps someone else.
By: Pirjo Posio
Date: 2007-10-04
Time: 12:37

Variables embedded in variables in TBS templates

To make my post above more general:
If you have a need to merge a variable containing other php-variables try this:
<p>This is the main template, containing among other things:</p>

PHP program that makes a submerge to merge the variables embedded in the string that is to  make the contents of $msglang.
Afterwards, there is a merge as usual to merge the main template.
$TBS = new clsTinyButStrong;
//Here comes the source data for the submerge
$mystring = "The city [var.name] is in [var.country].";
$template = $TBS->Source;  //The orig_template is stored for a while
$TBS->Source = $mystring;  //This is the template for the submerge
$TBS->Show(TBS_NOTHING);  //Do not show the submerge results, nor quit the script

//Here we return the results of the submerge to the variable in orig_template
$msglang = $TBS->Source;
$TBS->Source = $template; //orig_template is back

$TBS->Merge ... //Merge your main template here
Hope this makes it more clear and suitable for general-purpose coding.
By: TomH
Date: 2010-09-18
Time: 23:26

Re: Variables embedded in variables in TBS templates

((Hello Ms. Pirjo, hope you are well))

I have been trying some new things (for me) and I searched this forum for related coding as a way to see if I was on track.

The code above by Pirjo has inspired me to to take the next step and make a function to do the dirty work.

In this application I want to be able to interrupt the TBS processing for the current page and do the following:
* read in a template having TBS blocks
* populate the blocks with db content
* save the merged template for later use
* resume TBS processing for the current page

Here's my first pass at a function to do  this -- it actually seems to be working - it does create the merged subtemplate. And it does expire and re-build the merged files as expected. I see no evidence "yet" that it is breaking the TBS for the current page. ((But this stuff really scares me!))

// ===========  function to do merging for cachenow ============
// assumes tbssql is configured and running
function cachenow_merged($cacheid, $dir, $mask, $maxage, $subtpl, $sql, $blockname){
global $TBS;
global $Db;
$template = file_get_contents($subtpl); //read html table (with TBS code blocks)
$TBS->Source = $template; // load the template see Manual property Source
$TBS->LoadTemplate(null) ;
$TBS->Render = TBS_OUTPUT;
$res = $Db->GetRows($sql);
$TBS->Render = TBS_NOTHING ;

$TBS->PlugIn(TBS_INSTALL, TBS_CACHE, $dir, $mask);
$TBS->PlugIn(TBS_CACHE, $cacheid,  TBS_CACHENOW );

return true;

// =================================================

Here's the function as it's being ussd in the page script
// set the var for the f()
$subtpl = "subtpl_letter_table_func.html";
//$subtpl = "subtpl_letter_table.html"; // switching tpl does prove it is working !!!
$sql = "SELECT DISTINCT left(lname,1) AS fletter from mycontacts ORDER BY lname";

$template = $TBS->Source; // insure TBS Source does not get contaminated

$filename = ABS_PATH."/merged_".$cacheid.".html"; // needed for evaluating whether to run cachenow_merged()

if((file_exists($filename)  && (time() - filectime($filename) > $maxage*60)) || !file_exists($filename)){
  cachenow_merged($cacheid, $dir, $mask, $maxage, $subtpl, $sql,$blockname);

$TBS->Source = $template; // recover previous TBS Source

I would greatly appreciate a critique of this approach -and- and warnings of weaknesses or outright errors.

You can see a protptype of this at
sometimes easier to understand code when the page can be seen.

Thanks very much for any guidance you can give.

And thanks for TBS every day,