Skip to page content or skip to Accesskey List.
Search evolt.org
evolt.org login: or register

Work

Main Page Content

Simple Localization with PHP

Rated 3.68 (Ratings: 3) (Add your rating)

Log in to add a comment
(5 comments so far)

Want more?

 
Picture of emm

Emmanuel Décarie

Member info | Full bio

User since: December 23, 2002

Last login: February 23, 2007

Articles written: 1

On PHP DevCenter, Adam Trachtenberg and Joao Prado Maia have described interesting ways to localize web sites with PHP. In this article I've offered another alternative, which should be easy for non-programmers to use. We will take advantage of the user function setstring function:

setstring ( $lang, $string, [$lang, $string])

Here's a working example of a login page in French and English, which could easily be turned into a template:

Example 1: The Login Page

Example 1

The HTML Source of the Login Page

<? include_once ("./setstring.inc") ?>

<?= "<a href='" . $PHP_SELF . "?lang=fr'>Français</a>" ?> |
<?= "<a href='" . $PHP_SELF . "?lang=en'>English</a>" ?> |
<?= "<a href='" . $PHP_SELF . "?logoff=1'>Logoff</a>" ?>

<form method="post" action="<?=$PHP_SELF?>">
    <p>
        <b><?=setstring ( 'fr', 'Enregistrement requis', 'en', 'Login required')?></b>
    </p>
    <p>
        <?=setstring ('fr', 'Nom de login:', 'en', 'Login')?><br><input type="text" name="uid" size="8">
    </p>
    <p>
        <?=setstring ( 'fr', 'Mot de passe:', 'en', 'Password')?><br><input type="password" name="pwd" size="8">
    </p>
    <p>
        <input type="submit" name="processlogin" value=" <?= setstring ( 'fr', 'Confirmer', 'en', 'Submit') ?> ">
    </p>
</form>

As you can see, this simple function can be useful when you don't want a web interface for non-programmers to manage different language versions (which the two articles cited above imply). This is ideal in situations where you don't need to display a large amount of content, as is the case of the login page example. (Well, this is not completely accurate as we will see later.)

The setstring function is easy to manage. It uses session variables to maintain the language preference of the user, and possibly a cookie to maintain state after the session finishes. Let's look at the code now, and I'll explain it in detail below.

The setstring Listing

####################################
# setstring.inc - Version 1.0 - December 19 2002
# Copyright: Emmanuel M. Decarie - emm@scriptdigital.com - http://scriptdigital.com
# BSD License
# READ ME: http://www.scriptdigital.com/divers/phplocalization.html
# $Date: 2002/12/19 20:44:01 $ - $RCSfile: setstring.inc,v $ - $Revision: 1.2 $
####################################


# start the session
session_start ();

# Set the default language.
$defaultlanguage = "fr";


# Set to 1 if you want to use a cookie.
$use_cookie = 1;

# Cookie expiration.
$expire_cookie = 3600 * 24 * 2; /* 2 days */
  


# Set $getlang to the requested key for the language if a GET arg 'lang' exists.
$getlang = $_GET['lang'];
 
# Set a cookie to the GET arg 'lang' if it exists.
# Set the SESSION key 'lang' to the 'lang' value of the cookie if it exits.
if ( $use_cookie == 1 ) {

 	if ( isset ($getlang) ) {
 		setcookie ('lang', $getlang, expire_cookie);
 	}
  	
 	if ( isset ($_COOKIE['lang']) ) {
 		$_SESSION['lang'] = $_COOKIE['lang'];

  	}
 }
  
# Destroy session and cookie.
if ( isset ($_GET['logoff']) ) {
 	session_destroy ();

 	if ( $use_cookie == 1 ) { setcookie ('lang',$getlang, -3600); }
 	header ("Location: http://" . $_SERVER['HTTP_HOST'] . "/" . $PHP_SELF);
 }

 # The main routine.

 function setstring () {
 	global $defaultlanguage;
 	global $getlang;
 	$lang = $_SESSION['lang'];
 	$args = func_get_args ();
	

 	# A newcomer.	
 	if ( !isset ($lang) ) {
 		session_register ('lang');
 		$lang = $defaultlanguage;
 	}
 	

 	# give $_GET['lang'] the choice to set $lang 
 	if (  isset ($getlang) ) { 
 		$lang = $getlang;
 		$_SESSION['lang'] = $lang;
		
 	}

 	
 	# Now $lang have been set either by $languagedefautl, $getlang, or $_SESSION['lang'].
 	# Loop in the language array and return $string if $lang is found.
 	if ( count ($args) ) {
 		if ( in_array ($lang, $args) ) {
 			for ($i = 0; $i < count ($args); $i++) {

 				if ( $args[$i] == $lang ) {
 					return $args[$i + 1];
 				}
 			}
 		}
 	}

 	return "";
 }

How it Works

Before looking at the script itself, it is important to note that you'll need to put your include statement (the include ("./setstring.inc") call) before any HTML output. This is because setstring can use cookies; see setcookie in the PHP manual for details.

At the beginning of the script (lines: 12 - 19) we set the configurations for $defaultlanguage, $use_cookie and $expirecookie. The value of the $defaultlanguage is for newcomers that don't have a cookie or that didn't set the language by clicking on a link. The value of the default language can be anything, as the names of the languages. You can use something like this if you like:

$defaultlanguage = "schtroumph"

&lt;?= setstring ('schtroumph', 'Quelle schtroumphe est-il ?', 'klingon', "'arlogh Qoylu'pu'?") ?&gt;

Don't forget to escape your quotes inside the string returned by the function. This will not work: ('klingon', ''arlogh Qoylu'pu'?') but this will: 'klingon', ('\'arlogh Qoylu\'pu\'?'). You can also change single quote to double quotes as in the example above.

Also, don't forget to use HTML entities to escape non-ASCII text. If you use languages like Arabic, Chinese or Hebrew, and depending if you use UTF-8 for text encoding or another variety of encoding that is not based on Unicode (like, for example, GB-2312 for Simplified Chinese), you can use directly this encoding with the setstring function. But you have to set the http-equiv in the &lt;meta&gt; tag like this:

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

or

<meta http-equiv="Content-Type" content="text/html; charset=gb2312">

You set $use_cookie to 1 if you want your users to keep their language setting after the session finishes, and set $expirecookie to the number of seconds you want the cookie to last. In the example, $expirecookie is set to expire in 2 days.

The language which the function returns is determined by order of priority:

  1. The value of the lang argument in the GET request (lines: 23, 58)
  2. You set the 'lang' value in the GET request by a link like this so that the page will point to itself:
    &lt;?= "&lt;a href='" . $PHP_SELF . "?lang=fr'&gt;Fran&amp;ccedil;ais&lt;/a&gt;" ?&gt;

    And will look like this after PHP has processed it:
    &lt;a href='/divers/phplocalization.html?lang=fr'&gt;Fran&amp;ccedil;ais&lt;/a&gt;</a>

    If the 'lang' value in the GET request is set and if $use_cookie == 1, we set a cookie for the 'lang' value.

  3. The value of the lang keyword for a cookie set previously by setstring (line: 32)
  4. This was set in (1) if the user has clicked on a link with '?lang=$lang'.

  5. The global value $defaultlanguage (lines: 13, 55)
  6. If nothing happened at (1) or (2), use the $defaultlanguage value to set the language.

When the $lang keyword is found, setstring loop in the array that was pass to it (lines: 65 -75) and returns the value of the element (which is the $string parameter) after the element that matches the value of $lang. Here's a snippet of code that illustrate the above.

$lang = 'en';
setstring ('fr', 'Allo', 'en', 'Hello');

for ($i = 0; $i < count ($args); $i++) {
    if ( $args[$i] == $lang ) {                 # $lang == 'en'
        return $args[$i + 1];                   # return 'Hello'
    }

Extending setstring

If you have repetitive text, you could use setstring with constants, and here's how to do it for the login example above. First, create a file for each language and define the same constants.

french.inc

<?
####################################
# french.inc
# $Date$ - $RCSfile$ - $Revision$
####################################

define ('LOGIN_REQUIRED', "Enregistrement requis");
define ('LOGIN', "Nom de login");
define ('PASSWORD', "Mot de passe");
?>

english.inc

<?
####################################
# english.inc
# $Date$ - $RCSfile$ - $Revision$
####################################

define ('LOGIN_REQUIRED', "Login Required");
define ('LOGIN', "Login");
define ('PASSWORD', "Password");
?>

Then, you just have to use setstring once to build different languages versions. Here, we use setstring to pass the right language file to include.

Example 2: The Login Page

<? include_once ("./setstring.inc") ?>

<? include ( setstring ( 'fr', './french.inc', 'en', './english.inc') )?>

<?= "<a href='" . $PHP_SELF . "?lang=fr'>Fran&ccedil;ais</a>" ?> |
<?= "<a href='" . $PHP_SELF . "?lang=en'>English</a>" ?> |
<?= "<a href='" . $PHP_SELF . "?logoff=1'>Logoff</a>" ?>

<form method="post" action="<?=$PHP_SELF?>">
	<p>
		<b><?=LOGIN_REQUIRED?></b>
	</p>
	<p>
		<?=LOGIN?><br><input type="text" name="uid" size="8">
	</p>
	<p>
		<?=PASSWORD?><br><input type="password" name="pwd" size="8">
	</p>
	<p>
		<input type="submit" name="processlogin" value=" <?= SUBMIT ?> ">
	</p>
</form>

If you have a lot of text you can use an include function with setstring. You create a file for each language as above, and then use the include function:

Example 3: include and setstring

<? include_once ("./setstring.inc") ?>

<?= "<a href='" . $PHP_SELF . "?lang=fr'>Fran&ccedil;ais</a>" ?> |
<?= "<a href='" . $PHP_SELF . "?lang=en'>English</a>" ?> |
<?= "<a href='" . $PHP_SELF . "?logoff=1'>Logoff</a>" ?>

<? include ( setstring ( 'fr', './filefrench.inc', 'en', './fileenglish.inc') )?>

Version History

Version 1.0

First release: December 19 2002.
Open Source (BSD license).
A big thanks to Hans Zaunere, Jim Byrne, Jaz-Michael King, and Deke Smith for reviewing this text.

Requirements

PHP greater than 4.1.x

Download

Save this page to your disk as "setstring.inc".

Notes

Emmanuel Décarie live in Montréal (Québec, Canada) and specialize in content management system (CMS) and custom build web applications. If you need a consultant for your projects (Perl, PHP, Radio UserLand, Manila), please, have a look at http://scriptdigital.com.

multilingual pages

Submitted by Junglee on January 6, 2003 - 09:35.

In many cases, with multilngual websites, some pages are not available for certain languages.

for example you could have :

/script?item=23&amp;lang=en
in english, but in french
/script?item=23&amp;lang=fr
may not be a valid page -- do you handle such a scenario ?

login or register to post comments

Re: multilingual pages

Submitted by emm on January 6, 2003 - 10:15.

See example 3 for such a scenario. You just have to point to the same page for both languages. HTH -Emmanuel

login or register to post comments

Just a reminder: registered_globals

Submitted by sasha22 on January 6, 2003 - 14:56.

In PHP 4.2.x and up, registerd_globals are off by default. If registered_globals are off, $PHP_SELF will need to be $_SERVER['PHP_SELF'].

login or register to post comments

working on it

Submitted by flaimo on January 7, 2003 - 17:22.

actually i'm working on a i18n class since a couple of weeks. supports simple inc-translation files or gettext. you can take a look at it at https://sourceforge.net/projects/php-flp/

login or register to post comments

Warning: setcookie() expects ....

Submitted by maxmendez on April 7, 2004 - 13:14.

Hi im getting Warning: setcookie() expects parameter 3 to be long, string given in c:\apache\Apache\htdocs\LANGUAGETRY\setstring.inc on line 34 at the top of my page. anyone know why?

login or register to post comments

The access keys for this page are: ALT (Control on a Mac) plus:

evolt.orgEvolt.org is an all-volunteer resource for web developers made up of a discussion list, a browser archive, and member-submitted articles. This article is the property of its author, please do not redistribute or use elsewhere without checking with the author.