Internationalisation (i18n) of PHP/Smarty applications

I want to present a way in which it is possible to have multiple language versions of a php application which uses the Smarty (http://smarty.php.net) template engine. I give lots of credit to André Rabold (http://smarty.incutio.com/?page=SmartyMultilanguageSupport).

Goal:

  • Strings, which should be translated, have @@-tags
  • The translation files are separate and can easily be adapted
  • The translation function can also be called internally by php

//array which holds the tokens is created:
$i18n_tokens = array();
//First, an outputfilter for smarty has to be registered after the creation of the Smarty-class:
$smarty = new Smarty;
$smarty->register_outputfilter("i18n_substitute_text");
function i18n_get_language()
   // language which is selected by user (defined in the browser settings)
    {
        $lang_variable = substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2);
        if (empty($lang_variable)) {
            $lang_variable = 'en';   
        }               
        return $lang_variable;      
    }    
function i18n_substitute_text_token($token) 
// substitutes a single token
    {
        global $i18n_tokens;
        $a = trim($token);
        if (isset($i18n_tokens[$a]))
//found
            return $i18n_tokens[$a];
        else {
//not found, new entry in language file is created
            $f = 'i18n/lang_' . i18n_get_language() . '.php';        
            if (file_exists($f) && is_writeable($f)) {
                $s = file_get_contents($f);
                eval($s);
            } else {
                echo "No file access for" . $f . " von " . __FILE__ . "<br>";
                return $token;
            }    
            if (isset($i18n_tokens[$a])) {
                return $i18n_tokens[$a];  
            }      
            $i18n_tokens[$a] = $a;       
            $s = '$i18n_tokens' . "['" . $a . "']" . "='" . $a . "'; //neu" . PHP_EOL;
            if ($handle = fopen($f, 'a')) {                
                fwrite($handle, $s);   
                fclose($handle);                
            }                    
            return $a;
        }        
    }        	
function i18n_substitute_text($tpl_output, &$smarty)
// Smarty-output filter, it reads a file and parses it contents
// all contents starting and ending with @@ are replaced
{
        global $i18n_tokens;	    
        $f = 'i18n/lang_' . i18n_get_language() . '.php';
        if (file_exists($f) && is_readable($f)) {
            $s = file_get_contents($f);
            eval($s);
        } else {
            echo "No file access" . $f . " for " . __FILE__;
        }
        return preg_replace_callback('/@@(.+?)@@/', '_i18n_substitute_text_token', $tpl_output);       
}

The content of the i18n/lang_en.php file could be:

$i18n_tokens['Benutzer bearbeiten']='Edit user';
$i18n_tokens['Benutzer']='User';
$i18n_tokens['Benutzergruppe']='User group';
$i18n_tokens['Benutzergruppen']='User groups'; 
$i18n_tokens['Benutzerverwaltung']='User management';