I’ve been lucky enough to have my book, “Beginning PHP and MySQL 5, Second Edition“, translated into several languages, among them Chinese, Czechoslovakian, Polish and Russian. Further, the English version is available via a variety of outlets in many other countries, France and Germany among them. While my ability to effectively promote the book within these markets is largely negated due to the obvious geographical barriers, the book’s support site presents a great opportunity to at least communicate with these readers in their native language.
Of course, despite my best attempts I’m unable to speak this array of languages, but as a Web developer I wanted to create the most efficient means for hosting a multi-lingual support site, and then work with native speakers to translate the English material. Because the support site runs the Zend Framework, naturally I wondered whether some sort of translation component was available, and sure enough a quick perusal of the Zend Framework website turned up Zend_Translate. In this brief tutorial I’ll document how I’m using the Zend Framework to make my website available to the world.
Introducing Zend_Translate
Web frameworks offer developers an amazingly efficient way to build websites, cleanly separating the logic from the view in a way that greatly reduces the time required to both create and manage the site. Not to mention their ability to automate the request and response process in a way that provides you with some great features such as user-friendly URLs. However, the basic features aren’t suffice to manage a multi-lingual website, because copies of each page template (view) would need to be made in order to render that page in multiple languages. Recognizing this drawback, the Zend Framework developers were quick to devise a solution which presented the ability to manage a multi-lingual website without having to make such concessions, and the fruits of their labor is packaged in the Zend_Translate component.
Zend_Translate works by referring a series of source files which contain the language-specific text found throughout the website. The framework will look to the appropriate source file based on the user’s desired language, retrieve the text, and insert it into the requested page. At present Zend_Translate supports a variety of source file formats, including PHP arrays, CSV, Gettext, Qt, TMX, and Xliff. The Zend Framework manual offers a great breakdown of the advantages of each format. In the future users will be able to use other sources such as an SQL database.
While I’ve used Gettext in the past with great success, it requires you install some additional utilities, in addition to store the final source files in a machine-readable only format (created using the aforementioned required utilities). Because I wanted to keep this project as simple as possible, I decided to use CSV. Creating the CSV files are easy; just create a text file with the .csv extension, using the appropriate locale identifier for the file name, and add the strings you’d like to translate, concluding each with a semi-colon. The translated string should follow that semi-colon. Here’s a sampling of the it.csv file, used to manage the Italian version of the site. To begin, let’s translate the book’s table of contents:
# Table of contents Table of Contents;Tabella di contenuti Chapter 1. An Introduction to PHP;Introduzione a PHP Chapter 2. Installing Apache and PHP;Installazione di Apache e PHP Chapter 3. PHP Basics;Fondamenti di PHP Chapter 4. Functions;Funzioni Chapter 5. Arrays;Arrays
The Zend Framework doesn’t require these files to be placed in any one single rigorous directory structure, nonetheless you should take care to standardize the repository for easy management and access. I simply created a directory named languages within the website’s root directory, and placed the source files there.
Translating the Website
All that remains is to modify the website to recognize the requested language, and update the text accordingly. This is done using the Zend_Translate component. The following script uses Zend_Translate to update the table of contents text according to the user’s desired language:
<?php require_once("Zend/Translate.php"); $translate = new Zend_Translate('csv', "c:apache2htdocslanguagesit.csv", 'it'); print "<h4>".$translate->_("Table of Contents")."</h4>"; print $translate->_("Chapter 1. An Introduction to PHP")."<br />"; print $translate->_("Chapter 2. Installing Apache and PHP")."<br />"; print $translate->_("Chapter 3. PHP Basics")."<br />"; print $translate->_("Chapter 4. Functions")."<br />"; print $translate->_("Chapter 5. Arrays")."<br />"; ?>
Adding this script to a Zend Framework-driven website and executing it produces the following output:
<h4>Tabella di contenuti</h4> Capitolo 1. Introduzione a PHP<br /> Capitolo 2. Installazione ed configurazione di PHP<br /> Capitolo 3. Fondamenti di PHP<br /> Capitolo 4. Funzioni<br /> Capitolo 5. Arrays<br />
What’s particularly useful about Zend_Translate is it won’t produce errors should a string identified for translation not have a corresponding translation in the appropriate source file. For instance, suppose the following line was found in the above file yet didn’t have a corresponding match in it.csv:
print $translate->_("Chapter 6. Object-oriented PHP")."<br />";
Rather than output an error complaining about the lack of a corresponding translation for this string, PHP will simply output the original language version, resulting in the following output:
<h4>Tabella di contenuti</h4> Capitolo 1. Introduzione a PHP<br /> Capitolo 2. Installazione ed configurazione di PHP<br /> Capitolo 3. Fondamenti di PHP<br /> Capitolo 4. Funzioni<br /> Capitolo 5. Arrays<br /> Chapter 6. Object-Oriented PHP<br />
This behavior allows the team to gradually translate the website over time, while giving users hailing from other languages the opportunity to take advantage of whatever text has been translate d at any given point in time.
Allowing the User to Dynamically Switch Languages
In order to take full advantage of this feature, you need to provide the user with a way to select the desired language. This is very easily done by creating links that pass along an easily identifiable parameter and corresponding locale, like so:
http://www.beginningphpandmysql.com/toc/lang/it/
To retrieve the lang = it parameter, just add the following line to the appropriate controller method:
$lang = $this->_request->getParam('lang');
Then modify the Zend_Translate constructor call used earlier in this chapter to read like so:
$translate = new Zend_Translate('csv', "c:apache2htdocslanguages$lang.csv", '$lang');
This approach allows the reader to choose a desired language simply by clicking on an appropriate link. Alternatively, if your users register for the site, you could provide them with the opportunity to choose a default language, storing it within a database, and subsequently retrieving that value and placing it within a session variable once the user logs in.
Where to Go From Here?
Zend_Translate is just one feature at your disposal when creating websites for the world. For instance, the Zend_Locale component greatly reduces the complexity of localizing dates, numbers, currency, and calendars. The Zend_Measure component helps you convert data such as temperature and velocity, the units of which vary widely among nations.
I’d love to hear of anything you do with what was covered in this article! Please email me at the address found in the below bio!
About the Author
W. Jason Gilmore is Apress’ Open Source Editorial Director, and co-founder of IT Enlightenment. He’s the author of several books, including the best-selling “Beginning PHP and MySQL 5: Novice to Professional, Second Edition” (Apress, 2006. 913pp.). Jason loves receiving e-mail; so don’t hesitate to write him at wjATwjgilmore.com.