Multilingual interfaces [duplicate]

There is a desire to introduce a multilingual interface into your system, of course it’s still a hassle, but I would like to hear the opinion of experts which of the well-known methods they liked in practice and which not, or just ideas. There are many ways, sometimes they even form something like a dictionary, and then add symbols, almost their own language. But it seems to me not very convenient, and saving memory is very doubtful. But still, for any good ideas I will certainly bump pluses 🙂

Answer 1, authority 100%

Alternatively, it may be complicated, but there should be no problems with performance. If this is the interface and the data does not need to be translated or not within the framework of this task, you can compile templates for the language.

That is, let’s say we have the following template:

<? if (!defined('ALL_OK')) die('Access denied'); ?>
<ul id="adminmenu">
  <li><a href="/admin/"></a></li>
  <li><a href="/admin/data/"></a></li>
  <li><a href="/admin/users/"></a></li>
  <li><a href="/admin/?exit=1"></a></li>
<? echo $this->someText; ?>

Now we are looking for a template connection in the template engine code and change it to something like this

//$template = ROOT.'/templates/admin/menu.tpl.php';
$lang = $_SESSION['LANG'];
$template = compileTemplate($lang, ROOT.'/templates/admin/menu.tpl.php', !empty($_GET['clearcache'])); //  ,      
//    .

Picking the template:

<? if (!defined('ALL_OK')) die('Access denied'); ?>
<ul id="adminmenu">
  <li><a href="/admin/">[[L:menu-admin]]</a></li>
  <li><a href="/admin/data/">[[L:menu-data]]</a></li>
  <li><a href="/admin/users/">[[L:menu-users]]</a></li>
  <li><a href="/admin/?exit=1">[[L:menu-exit]]</a></li>
<? echo $this->someText; ?>


function compileTemplate($lang, $template, $forceUpdate = false) {
  $dest = ROOT.'/lng/'.$lang.'/'.md5($template).'.tpl.php';
  if (file_exists($dest) && !$forceUpdate)
    return $dest; //        , .
  $tplText = file_get_contents($template);
  $langArray = array('menu-admin' => ''); //     
  foreach ($langArray as $code => $value)
    if (strpos($tplText, '[[L:'.$code.']]') !== false)
      $tplText = str_replace('[[L:'.$code.']]', $value, $tplText); //       
  file_put_contents($dest, $tplText);
  return $dest;

In this way, the files will be collected “forever”, the php code in them will not suffer from this. Maximum performance, minimum memory consumption. Although yes, it should be used carefully and managers should not be allowed to make templates and translate ( ... echo '[[L:menu]]'; ...with "menu" => "<div style='float: left'>text</div>"will drop the code).

But, for example, Joomla authors didn’t steam at all – for each script run, several .ini are parsed and filed into the session) Sometimes 2 meters are dialed.

UPDThere is another way to approach label replacement. If the data is stored in the database, then you can first get all the tags

preg_match_all('/\[\[L\:([^\]]+)\]\]/', $tplText, $matches);
//   $matches   $codes   
$res = mysql_query('SELECT * FROM lng WHERE (`lang_id`="'.$lang.'" AND `word_id` IN ("'.implode('", "', $codes).'"));');
//         .
// , , ,  )

Answer 2, authority 100%

PHP has support for the standard unix application localization mechanism gettext, learn more. Wikipedia has a good overview of what gettext can do:

Answer 3, authority 67%

The easiest way is to use some function to get the translated text.

for example:

function _($key)
    $lang = $_SESSION['lang'];
    $row = mysql_get('select value from i18n where key='.quote($key).' and lang='.quote($lang));
    if ($row !== false) {
        return $row['value']
    mysql_insert('i18n', array('value' => '{'.$key.'}', 'key' => $key, 'lang' => $lang));
    return '{'.$key.'}';

The decision is controversial since caching can be applied (so that each translation does not go into the database, etc.)

The transfers themselves are carried out by replacing the data in the table + resetting the cache.

Dare, fantasize 🙂
PS: you can also pass the result through sprintf so that you can format dynamic strings. ala: _(‘we got %d items from %s’, 100, ‘USA’);
And of course, the translation should also contain % (“We got % of items from %”)

Answer 4, authority 33%

And I would make it more interesting 🙂

  • I would create, for example, a CSV, or, even better, a json file.
  • I would create an object of type in the site

lang: {
label: “Lab”,
menu: “Menu”,
options: “Options”,

  • Next, when generating the page, I would slip this json to it.

  • I would make a global function, for example, translate, in which I would describe which element to assign a value from the lans object.


1 Instant interface change.

2 Caching of such objects works great

I didn’t find any cons 🙂

P.S. As practice shows: If you say that this is a heavy page load – you are mistaken 🙂 Do not load at all. A much greater load on the server will unsubscribe each time one or another value depending on the translation + caching of standard html content will be difficult.