I'd like to get your feedback over the way I implemented multi-language support on my PHP MVC web app. That's how I did:
- in the /app folder I created a /languages folder which contains one file per language (english.php, spanish.php, etc.)
- each file contains a serie of variables with the same names in each files, containing the texts to render in the views
- these variables are then echoed in the different views
- a "language" cookie variable is updated when the user changes the language
- in the controller of each view, I include a language file on the following format:
include $_SERVER['DOCUMENT_ROOT'] . "/app/languages/" . $_COOKIE["language"] . ".php";
Sounds pretty neat to me. Would you have any negative thoughts about this method?
As you're on PHP 5.3.2 I'd definitely recommend checking out the intl extension if you can. It's full of handy functions and classes to assist in i18n. For instance you can use the following snippet to generate a "best-fit" language for your visitor from those you have available:
$langs = array('en', 'fr', 'de');
$preferences = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE']);
$locale = Locale::lookup($langs, $preferences);
There's also a lot more to think about than straight word-for-word replacements. Different languages have different formatting conventions. There's a lot of information in this Zend article that might prove useful.
My code uses XSL for templating so personally, when it comes to translations I use XML language files and XPath queries so that the language file can be understood directly by templates but is also available to PHP for formatting strings with MessageFormatter.
I'd avoid using the database as a store to be honest, simply for performance.
You could also parse the accept-language header to help decide what do do.
Accept-Language:en-GB,en-US;q=0.8,en;q=0.6
Mine looks like that. It's not fool proof, but it could be a way to set the appropriate cookie automatically.
As you are just having data in the language files, I would recommend using GetText. It is a port of the standard GetText of C++ for internationalization, there are tons of tools to build up the language files and is very fast due to compiled files during runtime.
You essentially build up your data-files (e.g. fr.po, en.po) with a kind-of INI-file format and compile those files to specialized .mo-files (fr.mo, en.mo, ...) and simply echo the internationalized strings with the static function _()
, e.g. echo _("Hello World");
would produce the german output Hallo Welt
or (if no translation is available in the .mo-files) the default string Hello World
.
As for choosing the right language: that depends on your requirements. As already pointed out, you should use the Accept-language
-Header of the browser and might want to add support for an overwrite through session-information.