Native Language Support
PHP (PHP training PHP tutorial) is a great the language for developing dynamic Web sites. Some does it for fun while others for business. It is true, a great part of the web was in 中文版. However, if you were targeting a worldwide audience, then neither 中文版 nor Esperanto alone is an option.
If you need to deliver the content in several languages, it's a good idea to explore several alternatives. However, some alternatives may is suitable for dynamic websites. Added to, there are the overhead of time spent in maintenance. To further complicate things, your needs if not being totally in line with the resources of you has at your disposal. Therefore, it's advisable to choose a alternative that suits your best.
I found myself in positions which required me-deliver content in both 中文版 and Spanish, and in one project a third L Anguage. Here is the possibilities I explored:
Explicit links for each language
Use Apache ' s mod_negotiation
Use GNU Gettext support in PHP
Write your own
This article gives a brief introduction to the first three possibilities, and then we'll go about the fourth solution WH Ich suited the requirements best, given the set of constraints. I am assuming that the reader was at least familiar with PHP programming and the use of PHP classes.
Principles of content negotiation
Before we go to exploring the various options, we should understand the basics of content negotiation and how that appli ES to the development framework. Then, you'll be able to develop a Web application that can deliver it content in the language of choice of your visitor .
By simply configuring the Web browser, the user can set it up in a-a-the-he or her preferred language was used when AVA Ilable. Several languages can be specified in a prioritized list, by setting up the preferences or option of the browser.
ANDs this list of preferred languages on every request made to the site. This action was totally transparent to the user, as the information gets a sent in the header of the Accept-language, for example:
Accept-language:bg, ES, en-US, fr
Here we visitor has chosen Bulgarian, US 中文版, Spanish and French in that order. Notice that can even specify regional variants. The first and characters is a language code as specified in an ISO standard. This language code is followed by a dash and a region code.
As an example, if the request arrives to a website whose content are entirely in Russian, then the list is exhausted and th E visitor would get Russian text whether (s) he likes it or not. Now, assuming the website have both 中文版 and Spanish content (the 2nd and 3rd options), then the visitor would receive PA Ges in Spanish. Why? Simply because here Spanish had higher priority with respect to 中文版.
Sometimes, the Web server itself can manage the content negotiation, if configured to does so. Otherwise, the request for a particular language is ignored. Alternatively, the application that delivers the content takes the decision of which language it's to use. This is exactly the what we'll do later.
Before going further, I would like-to-point out, the content negotiation are not just dealing with human languages. For example, it also negotiates the kind of information the client can take by means of MIME types, but that's beyond the Scope of this article.
Explicit Links
Many multi-lingual websites present the content in various languages, and does so by placing a link on the document. There would is one link for each of the supported languages. This was a very simplistic approach and should only being used if you need to has multi-lingual content, but does not have the Resources of a scripting language or dynamic content.
If A document is moved, or a new language was added or removed from the repertoire and then the webmaster would has to edit, Add or remove links in each of the affected documents. This can is quite tedious.
Apache ' s content negotiation
The Apache Web server can manage language-sensitive content delivery by using the information from the content negotiation Headers. Then, the webmaster must provide the static pages for each language and name them properly. For example if the Welcome page was available in Spanish and 中文版, the webmaster would has these files:
welcome.html.es Welcome.html.en
When the Web server was well configured, it would deliver the appropriate Web page based on the language code according to T He priority list.
This works perfectly for static pages. However, if you have a dynamic website where a great deal of the pages are generated based on queries and then this approach W Ill not work. Another disadvantage is so you need to know how to does it and may or may not have access to the configuration files. My experience was, it was a bit tricky and it didn't have an offer enough flexibility for my purposes.
An advantage of this method is, the negotiation is between the browser and the Apache server. You need provide the static content.
GNU Gettext with PHP
This internationalization tool had been around for some time for C programmers. There is also a VARIANT used on other un*x, such as HP. Both is very good and is easy-to-use.
This extension have been available in PHP since version 3.0.6 and also in 4.0. The Gettext extension is easy-to-use, and was good if you are generating your webpages dynamically. The only thing left here would is the PHP code that generates the content and a set of message catalogs. Supporting a new language is as easy as generating a new catalog with the translations and dropping the file in the Approp Riate directory. Therefore, assuming you has a PHP application named "myphp" and that the appropriate message catalogs exist and is Insta Lled, then the application would has something like this:
/* Initialization of GetText in myphp */
Putenv ("lang= $language");
Bindtextdomain ("myphp", "./locale");
Textdomain ("myphp");
/* Print Some messages in the native language */
Echo GetText ("Hello new user");
echo _ ("You have no new messages");
?>
My provider had recently upgraded from PHP 3.0RC5 to a PHP4.0 Beta 2 installation. While PHP4 does has support for the Gettext extension, my provider does not compile the PHP4 module with Gettext support. However, even if they had, moving to another provider without Gettext would become a major headache.
Ctnls-national Language Support
Have considered various alternatives, I wrote down a set of requirements for the NLS module:
It had to is simple, and based in PHP
Easy-to-use
Allow the user the freedom of choosing or mixing NLS methods
As a result, I developed a PHP class that would allow the user to set up a multi-lingual website. With this class, the developer can emulate the Apache approach of one file per language, without reconfiguring Apache. Additionally, it is possible-a PHP script that generates the output in the appropriate language by means of message Catalogs.
A Real life application of the This class are on my website at Http://www.coralys.com/The Main Page was available in 中文版 (E n), Spanish (es) and Dutch (NL).
Using Ctnls
This is the very easy-to-use. The application would has something like this and its initialization code:
Include (' ctnls.class.php ');
$nls = new Ctnls;
?>
At this point, the class had detected the choice of languages suggested by the user behind the browser. What happens next depends in which method the application uses to provide multi-lingual content.
For static web pages, the approach are similar to the Apache convention. The name of the webpage comprises three parts:the base name, the language extension (both letter code per ISO standard) an d the extension which would typically be ". html". For example a welcome page would be:
Welcome.en.html welcome.es.html
Notice that each page contains a different language. At this point, your PHP application would serve the file in the appropriate language, by specifying the whole name without The language Id/code. The Ctnls class inserts the appropriate id/code:
$nls->loadpage ("welcome.html");
?>
Here's can specify any filename that's valid to the PHP virtual () function, which are how LoadPage () delivers the Conten T to the browser.
Another-deliver the content in various languages are by using message catalogs. In this case, the there is one PHP file for each language. It must be a valid PHP file because the message catalog was nothing more than a collection of PHP constants, each referring to a particular message. The reasons why we use constants and is not variables is twofold. First, the message does not change and by definition it is a constant. Second and most important, was that in PHP, constants was accessible at any place, even within functions. Whereas, if we use variables for the messages, we would has to resort to using a ' global ' declaration for each message us Ed within a function.
The Catalogdir class variable specifies the location of all message catalogs. It is a absolute path within the server, where each application'll has its message catalog. The name of each catalog file have three parts:the application ID, the language code and a valid PHP extension so it Can is include () Ed by Ctnls.
Now, assuming we have a application called "MyApp," we could use the following code at the initialization part:
$nls->loadmessages ("MyApp");
?>
This, as-well as LoadPage (), can is used after you has created a new instance of the Ctnls object. This method expects at least one file, with the default language, in the message catalog. In this case, myapp.en.php, and inside, it must has valid constant declarations for each message. For example:
Language:english
file:path/to/nls/myapp.en.php
Define ("Msg_welcome", "WELCOME to our site");
Define ("msg_redirected", "You is being redirected to our new site");
?>
Language:spanish
file:path/to/nls/myapp.es.php
Define ("Msg_welcome", "Bienvenido a Nuestras paginas");
Define ("msg_redirected", "Esta siendo Redireccionado a Nuestro".
"Nuevo Sitio de web");
?>
Only one of these'll is loaded, depending on the language priority assigned by the user. Then, somewhere in the PHP application, you can generate output as this:
Echo Msg_welcome. "
";
Echo msg_redirected;
?>
Auxiliary functions
The Ctnls class has several auxiliary member functions. These is not normally used, but can come in handy.
The Setcatalogpath function overrides the path to the catalog directory given in the configuration part of the Ctnls class .
Setdefaultlanguage does just that. It sets the code of the language to being tried in case all else fails. This is normally 中文版.
Setlanguageid and Getlanguageid set and return the Id/code of the first language to check. This language was checked before any of those found in the user preferences. Upon initialization, it is the same as the first language in the user list. Once LoadPage () or loadmessages () is invoked, Getlanguageid () would return the ID of the language it was used in deliver ing the content to the browser. It is also useful if the user have stored his/her preference in a cookie.
How it actually works
We have already explained what happens during the content negotiation phase. The browser sends the user ' s choice of languages in the Accept-language header. This information was available to any PHP script in the $HTTP _accept_language global variable.
When you create a new instance of the Ctnls object, the constructor function Ctnls () takes control. In turn, it initializes some internal settings and calls SetLanguage (). This internal member function goes through the list of languages in $HTTP _accept_language (delimited by commas), by using Only the language code and stripping the region code. The language code is for selecting the appropriate file. In this process, we convert the list to a array, but preserve the language priority.
When an application invokes either LoadPage () or loadmessages (), these methods would call the internal search () function.
The search () member function walks the language preference array from start to finish and if all of them fail to produce R Esults, it checks for the default language. This function keeps track of which languages it tried so that the attempts is not doing on the same language.
The GetFile () member function is called every time the search () function generates a new language candidate. It does this by passing it a base name, a language candidate and optionally a file extension.
By passing the base name, the language code and the file extension in that order, the getFile () function generates a list of candidate file names. If we are using the Loadmessages () and pass it an empty extension name, it produces a list by using the all known valid PHP script Extensions by prefixing them, with the path to the catalog directory. These PHP extension names is currently ". PhP3" and ". php". If, on the other hand, we pass the file extension to the function, then, we reduce the list of candidate file names to one .
GetFile () then continues by walking through the list of candidate file names until it finds one that exists. Based on this, we determine the current language and the object reads in that file.
Support for native language in PHP