Language Detection and Internationalization
PHP Tutorial

Language Detection and Internationalization

Language Detection and Internationalization


In this article, we’ll show you how to use language files and deliver your site in alternate languages.

In your application, any text that you want to deliver in multiple languages needs to be wrapped with a gettext marker. In PHP, it’s a special function that uses the underscore character as its name.

// Correct internationalization method.
echo _("This text will be automatically replaced.");

// Correct internationalization with variables.
$text = _("text");
echo _(sprintf("This %s will be automatically replaced.", $text));

// Not gonna work the way you think.
echo _("This $text will be automatically replaced.");

Don’t worry – even if nothing else is setup, string wrapped in the gettext function will still show up in their original format.

Next, you’ll need a bit of extra software – POEdit. This is a cross-platform program that lets you create and manage gettext catalogs, which are the things you’ll need to store your translated text.

When you run POEdit and create a new catalog (I recommend creating a Languages/ folder inside your application for them), you can select the language this catalog will be used for (each catalog is for a single file) and the location of your PHP files. POEdit will automatically parse your application looking for the gettext functions and show you a window listing every string in the original language (within your PHP files) and a blank text area where you can add the translated version of that string. Fancy, eh? Once you save your catalog, POEdit will automatically created a compiled version in the same folder, ending with an .mo extension.

Note: Your compiled message catalog must be in a folder named like follows (assuming a root of Languages/): Languages/it_IT.UTF8/LC_MESSAGES/, where myapp is the name of the text domain being used

Now that you have a catalog compiled and in your Languages/ folder, you need to tell your app to use it – if it’s needed.

// Use Italian/Italy.
$locale = "it_IT";

// Create an environment variable for the new locale.
// This will only live as long as the request.
putenv("LC_ALL=" . $locale);

// Sets the PHP locale to the first match given. The empty string will use the system default if nothing else is matched.
setlocale(LC_ALL, "$locale.utf8", $locale, "");

// Create a new text domain and point it to our language folder.
bindtextdomain("myapp", "./Languages");

// Set the codepage to use for text.
bind_textdomain_codeset("myapp", "UTF-8");

// Select the new text domain for looking up text.

// In this example, the catalog must be located at:
// Languages/it_IT.UTF8/LC_MESSAGES/

Finally, how do you tell what the user wants the language to be? Your best bet is to use the browser’s ACCEPT_LANGUAGE header. In PHP 5.3 and newer, there is a built-in function to handle this. If you are using an older version, you’ll need some extra code to figure it out.

* Returns the best-choice locale string for the current request.
* @return string Browser's preferred language if available, or "en_US" if not.
function getLanguage() {
// Set a default return value in case nothing else is found.
$return = "en_US";
// In PHP 5.3 and newer, we can use this function
if (function_exists("locale_accept_from_http")) {
$return = Locale::acceptFromHttp($_SERVER["HTTP_ACCEPT_LANGUAGE"]);
// In PHP 5.2 and older, we need to do this the hard way.
else {
$langs = explode(",", $_SERVER["HTTP_ACCEPT_LANGUAGE"]);
$lang = array();
foreach ($langs as $val) {
$matches = array();
if (FALSE !== preg_match("/(.*);q=([0-1]{0,1}\.\d{0,4})/i", $val, $matches)) {
$lang[$matches[1]] = (float)$matches[2];
else {
$lang[$val] = 1.0;
$qval = 0.0;
$pref = NULL;
foreach ($lang as $key => $value) {
if ($value > $qval) {
$qval = (float)$value;
$pref = $key;
if (TRUE === isset($pref)) {
$pref = explode("-", $pref);
if (FALSE === is_array($pref)) {
$pref = explode("_", $pref);
if (TRUE === is_array($pref)) {
if (TRUE === isset($pref[0])) {
$pref[0] = mb_strtolower($pref[0]);
if (TRUE === isset($pref[1])) {
$pref[1] = mb_strtoupper($pref[1]);
$return = implode("_", $pref);
return $return;

So to sum up, create folders for your languages, use POEdit to create and manage catalogs for each language used by your app, always check for the language to use during a request (although if you allow users to set their language preference, that should take precedence over the browser header), and wrap any text you want to be delivered in multiple languages with the _() function.

Have fun and good luck!

Leave a Reply

Your email address will not be published. Required fields are marked *