In this article Emmanual shows us how to localise our PHP-driven websites...
- Simple Localization with PHP
- Listing setstring
- How it Works
- Extending setstring
- Versions History
- Requirements
- Download
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 (try me!)
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
1 ####################################
2 # setstring.inc - Version 1.0 - December 19 2002
3 # Copyright: Emmanuel M. Decarie - emm@scriptdigital.com - http://scriptdigital.com
4 # BSD License
5 # READ ME: http://www.scriptdigital.com/divers/phplocalization.html
6 # $Date: 2002/12/19 19:41:45 $ - $RCSfile: setstring.inc,v $ - $Revision: 1.1.1.1 $
7 ####################################
8
9 # start the session
10 session_start ();
11
12 # Set the default language.
13 $defaultlanguage = "fr";
14
15 # Set to 1 if you want to use a cookie.
16 $use_cookie = 1;
17
18 # Cookie expiration.
19 $expire_cookie = 3600 * 24 * 2; /* 2 days */
20
21
22 # Set $getlang to the requested key for the language if a GET arg 'lang' exists.
23 $getlang = $_GET['lang'];
24
25 # Set a cookie to the GET arg 'lang' if it exists.
26 # Set the SESSION key 'lang' to the 'lang' value of the cookie if it exits.
27 if ( $use_cookie == 1 ) {
28 if ( isset ($getlang) ) {
29 setcookie ('lang', $getlang, expire_cookie);
30 }
31
32 if ( isset ($_COOKIE['lang']) ) {
33 $_SESSION['lang'] = $_COOKIE['lang'];
34 }
35 }
36
37 # Destroy session and cookie.
38 if ( isset ($_GET['logoff']) ) {
39 session_destroy ();
40 if ( $use_cookie == 1 ) { setcookie ('lang',$getlang, -3600); }
41 header ("Location: http://" . $_SERVER['HTTP_HOST'] . "/" . $PHP_SELF);
42 }
43
44 # The main routine.
45 # It expect an array for argument: ('lang1', 'string', 'lang2', string').
46 function setstring () {
47 global $defaultlanguage;
48 global $getlang;
49 $lang = $_SESSION['lang'];
50 $args = func_get_args ();
51
52 # A newcomer.
53 if ( !isset ($lang) ) {
54 session_register ('lang');
55 $lang = $defaultlanguage;
56 }
57
58 # give $_GET['lang'] the choice to set $lang
59 if ( isset ($getlang) ) {
60 $lang = $getlang;
61 $_SESSION['lang'] = $lang;
62
63 }
64
65 # Now $lang have been set either by $languagedefautl, $getlang, or $_SESSION['lang'].
66 # Loop in the language array and return $string if $lang is found.
67 if ( count ($args) ) {
68 if ( in_array ($lang, $args) ) {
69 for ($i = 0; $i < count ($args); $i++) {
70 if ( $args[$i] == $lang ) {
71 return $args[$i + 1];
72 }
73 }
74 }
75 }
76 return "";
77 }
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"
<?= setstring ('schtroumph', 'Quelle schtroumphe est-il ?', 'klingon', "'arlogh Qoylu'pu'?") ?>
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 <meta> 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)
You set the 'lang' value in the GET request by a link like this so that the page will point to itself:
<?= "<a href='" . $PHP_SELF . "?lang=fr'>Français</a>" ?>
And will look like this after PHP has processed it:
<a href='/divers/phplocalization.html?lang=fr'>Français</a>
If the 'lang' value in the GET request is set and if $use_cookie == 1, we set a cookie for the 'lang' value.
- (2) the value of the lang keyword for a cookie set previously by setstring (line: 32)
This was set in (1) if the user has clicked on a link with '?lang=$lang'.
- (3) the global value $defaultlanguage (lines: 13, 55)
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ç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ç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') )?>
Versions 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". (This link will open a new window.)
Notes
Internationalization and Localization with PHP
by Adam Trachtenberg
http://www.onlamp.com/pub/a/php/2002/11/28/php_i18n.html?page=1
Gettext
by Joao Prado Maia
http://www.onlamp.com/pub/a/php/2002/06/13/php.html
|
DISCLAIMER:
The content provided in this article is not warranted or guaranteed by Developer Shed, Inc.
The content provided is intended for entertainment and/or educational purposes in order to
introduce to the reader key ideas, concepts, and/or product reviews. As such it is incumbent
upon the reader to employ real-world tactics for security and implementation of best practices.
We are not liable for any negative consequences that may result from implementing any information
covered in our articles or tutorials. If this is a hardware review, it is not recommended to open
and/or modify your hardware.
|
More PHP Articles
More By Emmanuel M. Decarie
developerWorks - FREE Tools!
|
Whether you are creating new applications or modifying existing ones, managing integration of new components with traditional z/OS elements is a critical part of building and deploying modern applications. Listen to this webcast to see how IBM can help you optimize your development process using an IDE like Rational Developer for System z that integrates with management tools, such as ClearCase to manage your application development on mainframes.
FREE! Go There Now!
|
|
|
|
IBM Lotus Notes 8 provides a wide range of developers the ability to provide customized, integrated user interfaces via composite applications and via custom sidebar and toolbar plug-ins. This webcast provides you with tips and techniques to use with out-of-the-box capabilities of Lotus Notes 8, and survey how you can share useful components within your own company and within a larger community.
FREE! Go There Now!
|
|
|
|
In this webcast, IBM Rational will discuss the importance of Web application security and will share techniques and best practices to introduce application security testing into current QA processes including: understanding common security vulnerabilities and techniques to integrate security testing with defect tracking and remediation systems in an effort to safeguard sensitive online information.
FREE! Go There Now!
|
|
|
|
WebSphere Process Server delivers a unique integration framework that simplifies existing IT resources. Often, as IT assets grow to support business demand, so too does their complexity and manageability. In this webcast, we’ll discuss how WebSphere Process Server helps deliver an SOA infrastructure that provides a common model to orchestrate, mediate, connect, map, and execute the underlying IT functions. Discover how WebSphere Process Server simplifies integration of business processes by leveraging existing IT assets as reusable services without the complexities of traditional integration methodologies.
FREE! Go There Now!
|
|
|
|
As organizations have grown increasingly dependent on online software, the risk of malicious attacks has also become far more serious. Fortunately, well-governed organizations can protect their Web applications by injecting vulnerability assessments and ethical hacks into their software development and delivery processes. This paper describes 12 of the most common hacker attacks and provides basic rules that you can follow to help create more hack-resistant Web applications.
FREE! Go There Now!
|
|
|
|
You can now evaluate IBM Rational Asset Manager V7.0 online without installing or configuring it on your own system! Rational Asset Manager helps create, modify, govern, find, and reuse any type of development assets, including SOA and systems development assets. Rational Asset Manager helps you reduce software development costs and improve quality by facilitating the reuse of all types of software development-related assets. Visit developerWorks to learn more about this product and register to explore its capabilities online.
FREE! Go There Now!
|
|
|
|
As businesses grow increasingly dependent upon Web applications, these complex entities grow more difficult to secure. Most companies equip their Web sites with firewalls, Secure Sockets Layer (SSL), and network and host security, but the majority of attacks are on applications themselves – and these technologies cannot prevent them. This paper explains what you can do to help protect your organization, and it discusses an approach for improving your organization’s Web application security.
FREE! Go There Now!
|
|
|
|
Attend this launch webcast with Scott Hebner, Vice President of IBM Rational Marketing and Strategy, for an overview of Rational’s new software offerings and resources to help modernize and accelerate software innovation on i on Power Systems – while ensuring past application investments are protected and continue to grow. Learn how these solutions are helping customers extend their core i5/OS solutions toward modern architectures such as SOA and web technologies to deliver business improvements that stand the test of time.
FREE! Go There Now!
|
|
|
|
Get a free trial download of the latest version of IBM Rational Functional Tester V7.0.1. Rational Functional Tester is an automated functional and regression testing solution for QA teams concerned with the quality of their Java, Microsoft Visual Studio .NET, and Web-based applications.
FREE! Go There Now!
|
|
|
|
As organizations integrate software into every aspect of business, they are constantly pressured to deliver faster, better, and cheaper results. Unfortunately, a “dis-integrated” software delivery approach reduces returns while increasing costs. This IBM Rational White Paper shows how Integrated Requirements Management aligns organizations around maximizing value and keeping pace with change.
FREE! Go There Now!
|
|
|
|
All FREE IBM® developerWorks Tools!
|