Search code examples
phpstringinternationalizationmultilingual

Methods for multi-language web applications in PHP


I am trying to build a web application with multiple languages, just for my leisure/study. I am wondering if there's a better way than this.

Environment

  • PHP only. no framework or library so far.

Situation

English and Japanese sentences have different order of words, so I don't think simple concatenation like $user_name . 'decapitated' . $enemy. will work.

So I am thinking of saving all the sentences to database.

+----+------------------------------------+-----------------------------------+ | id | en | ja | +----+------------------------------------+-----------------------------------+ | 1 | $username has decapitated $enemy. | $username は $enemy の首をはねた! | +----+------------------------------------+-----------------------------------+

Texts inside have some variables like $username to be replaced with str_replace() later.

$result = str_replace('$username', $username, $db->select('SELECT ja FROM `tb_language` WHERE id = 1;'))

Questions

  • I tried to find smarter way to expand variables in database text but I could not. Any suggestion?
  • The procedure above inevitably repeat str_replace() as many as variables and it seems not efficient. Any suggestion?

Any suggestions are welcome and thanks in advance.


Solution

  • Use the printf()/sprintf() family of functions.

    printf, sprintf, vsprintf, (and so on...) functions are used for formatting strings and as such they enable you to utilize a pretty standardized set of placeholder logic.


    What you want to have stored in your database is something like this:

    %s has decapitated %s.

    In PHP you can format this using, for example, the printf() function (which directly outputs the result) or the sprintf() function (which returns the result).

    $translated = sprintf("%s has decapitated %s.", "red", "blue");
    echo $translated;
    
    red has decapitated blue.
    

    If you need to specify the order of the arguments passed in, you can do it by specifying the position. Ie. in english $format = "%1$s has decapitated %2$s." and in some other language something like $format = "%2$s has been decapitated by %1$s.".

    You can use this when you want to have different order of inserted words, but you want to keep the order same in your source code.

    Both of the these $format strings will be correctly formatted via the same sprintf($format, "red", blue") call:

    • red has decapitated blue.
    • blue has been decapitated by red.

    Possible formatting options are nicely presented here: http://php.net/manual/en/function.sprintf.php