11

First of all, I know that there is a lot of answers about multi-language functionality, I didn't find the answer for what I want.

I thought about three ways that I can work with. I need to create the languages files using PHP each time I'm adding a new value to a web form interface.

The first two are kind of similar - using arrays or defines in a specific language file and include it on the start of the run. But in this case I might load thousands of definitions or arrays just to use a few in each page.

The third way is to create function that is called each time with the keyword or the full phrase and using IF-s or switch to choose the right term (or returning the key called if no match).

What is the best way to do that? I decided to do some tests. I tried three different ways and measured the time and memory took for it:

  1. I defined an array (22 values) with and run over it from 1 to 1,000,000 - checked for calling value - 1 of three by using the % operator to choose what to use and just setting it on a variable

    • Time took: 0.476591110229 second
    • Memory: 6536 bytes
  2. I used the same array (22 values) and called it using function - return $arr[$string]; (just for convenient way to work and the ability to change it to different way if I'll need)

    • Time took: 0.960635185242 second
    • Memory: 6704 bytes
  3. I created a function with list of strings and using switch-->case I chose the returning string

    • Time took: 1.46953487396 second
    • Memory: 848 bytes

Well, now the question is what's the right choice - preferring time or preferring memory.

And in case that the sites are big and it would take a lot of memory - I couldn't change it because it is built with arrays - If it works with function I can always change it.

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
Joe Polico
  • 111
  • 1
  • 1
  • 6
  • 2
    Possible duplicate: http://stackoverflow.com/questions/2790952/php-localization-best-practices-gettext – Justin ᚅᚔᚈᚄᚒᚔ Sep 26 '11 at 18:09
  • 3
    possible duplicate of [How to make a Multilanguage website in php and Mysql](http://stackoverflow.com/questions/2487171/how-to-make-a-multilanguage-website-in-php-and-mysql) – JJJ Sep 26 '11 at 18:11
  • http://php.net/manual/en/function.gettext.php – Imre L Sep 26 '11 at 18:20
  • I thought I wrote that - but now I see that I've forget - I didn't liked the gettext, I need something that is more easy to work with, though the way it works seems nice - I didn't checked it but it seems something like my third way – Joe Polico Sep 26 '11 at 18:47
  • Having in mind discussion under my answer, I think it's important to add to the question: what scale you are running on, and how many strings you are talking about? And are you talking about translating interface or translating user-entered content? Those are 2 different things... – Maxim Krizhanovsky Sep 26 '11 at 19:11
  • I'm talking about the interface, the management interface and the whole website. I'm aiming for the fastest way for the PHP because I don't know the sizes of the websites (might be small, but it's wrong to go with that line of thought) – Joe Polico Sep 26 '11 at 19:17

3 Answers3

7

In terms of code, something like this will be great to you. It must be based in the choice of the user (Choosing a language from a button or menu) or based on the browse language (it is not the best aprouch).

index.php

<?php

// verify the user's choice
if ($_POST[lang] == "en") 
{
    include_once("en_language.php");
}

if ($_POST[lang] == "pt") 
{
    include_once("pt_language.php");
}

// calling a lable in your page
echo LABEL_MENU;


// the rest of your file
...
?>

en_language.php

<?php
// ENGISH Language file
define('LABEL_MENU','Main Menu');

// the whole file with the labels of your system

?>

pt_language.php

<?php
// PORTUGUESE Language file
define('LABEL_MENU','Menu Principal');

// the whole file with the labels of your system

?>

complementing

If you wish use array type than Constant values with define(), but I'm not sure what is faster than..

$arrays = array("MAIN_MENU" => "Main Menu", "LEFT_MENU" => "Left Menu"); 
echo $arrays["MAIN_MENU"];
devasia2112
  • 5,844
  • 6
  • 36
  • 56
  • As I said - I thought about that (or using arrays), but still - I can define a lots of strings that I won't use at all and when a website is getting alot of visits it became kind of heavy (I think) – Joe Polico Sep 26 '11 at 18:51
  • @Joe Polico - Great, it is the easy way. – devasia2112 Sep 26 '11 at 18:53
  • But I'm searching for the both - the easiest way and the fastest way (for the server) to work with. And truly, for the easy way it's better to use a function the manage all the language strings – Joe Polico Sep 26 '11 at 18:58
  • I think nothing is so easy on this way that you are looking for, perheps is better you choose to use a Framework like ZEND or whatever flavor of php framework you prefer, 'cause they all treat languages of the basis of it's work. But I will tell you, it is not so easy, especially if you had never used a framework before. – devasia2112 Sep 26 '11 at 19:23
  • I don't think I can start changing all my way of work to work with some framework. But can you tell me what of the both is better - creating function with `switch`->`case` structure or using arrays/definitions? – Joe Polico Sep 26 '11 at 19:29
  • Yes. In this case use an Array type to create ordered maps and associate your keywords to values. It is faster. Since switch case is a condition statement and Array is a data type. See my complementing in the answer. – devasia2112 Sep 26 '11 at 19:40
2

Group your strings into categories - one global and the other - corresponding to the views you have in the web site (for example lang_global, lang_profile, lang_something_else) Include the global file and the file corresponding to the current view. In this way you won't load the entire translation, but only a subset of it. And it is more managable, and you can provide context, having different translations on the same string.

Maxim Krizhanovsky
  • 26,265
  • 5
  • 59
  • 89
  • I need it for a CMS - it's kind of problem to divide it to multiple parts - the system can change on each site and the language strings can be called from anywhere.. it's too complicated to mess with the position of each string in the functions/files any time I want to call them – Joe Polico Sep 26 '11 at 18:45
  • 1
    You still have entities in the CMS. And entities can have separate language files. And each module/plugin can have a language file as well. – Maxim Krizhanovsky Sep 26 '11 at 18:47
  • It's still to complicated to work with.. the system is only the base and needed to change on each website, trying to define each time where to place the current string is not so simple way to work – Joe Polico Sep 26 '11 at 18:55
  • Then put in the database. Create a dynamic cache - all strings used by the current page, recorded by string, translation, pagepath, so on subsequent requests you query by pagepath (indexed field) and get translations, instead of calling string by string... – Maxim Krizhanovsky Sep 26 '11 at 18:57
  • And if I have a string that shows up in every category on my gallery? It might have multiple paths – Joe Polico Sep 26 '11 at 19:00
  • What's the problem with that? It will have multiple records in the cache table, so what? – Maxim Krizhanovsky Sep 26 '11 at 19:02
  • It's not helping my functionality - basically using the database, even with cache, makes too many requests for any big website, and saving multiple rows for one string makes it worse – Joe Polico Sep 26 '11 at 19:07
  • arrays are actually faster than define but there is a very small difference – Kilise Jan 26 '13 at 00:39
0

there's some useful answer here, but i would also recommend symfony/translation if you are using composer as a dependency manager.

lang/messages.fr.yaml :

Hello, %name%!: Bonjour, %name%!
Goodbye: Goodbye!

lang/messages.en.yaml :

Hello, %name%!: Hello, %name%!

file.php :

<?php
use Symfony\Component\Translation\Translator;
use Symfony\Component\Translation\Translator\Loader\YamlFileLoader;

require_once __DIR__ . '/vendor/autoload.php';

$translator = new Translator();

$translator->addLoader('yaml', new YamlFileLoader());
$translator->addResource('yaml', __DIR__ . 'lang/messages.en.yaml', 'en');
$translator->addResource('yaml', __DIR__ . 'lang/messages.fr.yaml', 'fr');

$translator->setFallbackLocales(array('en'));

$translator->setLocale('en');

echo $translator->translate('Hello, %name%!', ['name' => 'saif']); // Hello, saif!

$translator->setLocale('fr');

echo $translator->translate('Hello, %name%!', ['name' => 'saif']); // Bonjour, saif!
// Goodbye isn't set in the "fr" file, translator uses the fallback locale instead
echo $translator->translate('Goodbye'); // Goodbye !

read more on how to use the symfony translator component here.

azjezz
  • 3,827
  • 1
  • 14
  • 35