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.
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.