I18N - INTERNATIONALIZATION AND LOCALIZATION FOR PHP
This class will provide the user a way to have internationalization and
localization (I18N) strings coming from text files, or database. It offers
a way of grouping set of strings by Container, Section, and element name.
The choice to use text files or database tables as a source of strings is
transparent to the code using the class.
Installation of this package is fairly simple. First, the following files
should be available for any application that wishes to use this package:
They can be located anywhere that is accessible by the client PHP script.
If a database will be used to obtain the text elements, use the script located
at the file i18n.sql to create the necessary tables.
First of all, we need to include the necessary files:
Now, we should instantiate the I18N class:
$i18n =& new I18N();
At this point we should select which source will be used to obtain text elements:
database, or file. The I18N class expects a class that implements DataSource as
a source of data. To use a file based approach, we start by instantiating the
class FileDataSource, specifying the locatoin to the XML configuration file
(more about this file can be seen at the section "Text Based XML Configuration
$dataSource =& new FileDataSource('path/to/i18n.xml');
If we choose to use a database approach, we should first create a class that
extends and implements the methods declared in DatabaseConnectionManager.class.php.
To see an example implementation, look at the file DatabaseConnection.class.php.
Also, take into account that the I18N package will use the methods described in
DatabaseConnectionManager.class.php, so the database connection should be opened
before fetching any data from the source, and close after we are done.
// Instantiate and set up the database handler class
$databaseConnection =& new DatabaseConnection();
Now, we need to instantiate the class DatabaseDataSource passing the database
connection we just created as a parameter:
$dataSource =& new DatabaseDataSource($databaseConnection);
After we have the source defined, we pass its implementation to the I18N class:
Next, we should set which language (and optionally which locale) we'll be using:
$i18n->setLocale('uk'); // optional and can be omitted
Now, all that there's left to do is obtain the text elements. We have different
choices: we can fetch an entire container (fetching all sections and elements inside),
a section (with all its elements inside), or a particular text element. So first we
set the container that we'll be using:
And then we go on and fetch what we need:
$container =& $i18n->fetch();
$section =& $i18n->fetch('section');
$element =& $i18n->fetch('section', 'element');
The first two variables ($container and $section) will be indexed arrays, and the last
one will be a single string (since it is just an element we are fetching.)
$container is an array indexed by section, and elements, so to obtain an element called
'element' within the section 'section' we do:
$section, following this procedure, is an array indexed by elements. To obtain the
element called 'element' within this section, we do:
Finally, $element is a single string, which can be printed out as follows:
Also, we can get a list of languages and their locales:
$languages =& $i18n->fetchLanguages();
Which would also return an indexed array.
Text Based XML Configuration File
The XML configuration file for the file based data source will tell the I18N packages
mainly two things:
1. The path to locate the language files, and the extension that the language files
2. The list of languages and their locales.
You can see an example configuration file in i18n.xml.
Text Based Language Files
Language files can contain any extension defined within the XML configuration file,
and they follow the syntax of an INI configuration file:
1. Comments are started with a ; and end at the end of the line
2. Sections are identified between brackets: [section]
3. Values are defined as follows:
variable = "Value"
If we want to insert double quotes in the value, we use two single quotes:
variable = "Shakespeare said ''to be or not to be'', didn't he?"
Now, files should be named as follows:
For example, if we have a container called "language", and we set the extension to
".lang", if we want to define its language file for english we would do:
If we want to define it for the locale United Kingdom within english:
If we follow the database source approach, it is important to understand the database
structure that holds the data. Please see the file i18n.sql to get an idea of the
There, we can see that we have on the one side the tables:
i18n_language, i18n_language_name, i18n_locale, and i18n_locale_name
This will provide the I18N package with the list of languages and their locales.
Then, we have:
i18n_container, i18n_section, i18n_element, i18n_element_content
The i18n_element_content refers to the i18n_language and i18n_locale class, telling
us that an element content must be specified for a particular language, and can
optionally be set for a locale within that language (since it is optional, the
field for setting the locale in this class is not set to be a foreign key, and its
value should be NULL or 0 when defining a text content for a language, and no
This package not only handles internationalization, but localization as well. This allows
the client script to have string not only defined by main language (such as English or
Spanish) but also by locale (such as United States or United Kingdom, for English Language.)
When we set the locale (by using the setLocale() method), what the I18N will do is try to
obtain the requested resource (full container, full section, or particular element) defined
in that language, for that locale. If that resource is not available for that particular
locale, it will try to fetch it for the language itself.
In the case of file-based approach, if we're trying to obtain the container called 'language'
for English, United Kingdom, it will perform the following operations:
1. it will look for a file named:
2. If it is not available, it will then look for a file called:
3. If this is not available as well, it will try to obtain the first appareance of any locale
within the English language.
For database-based approach, it will follow the same procedure:
1. Obtain the requested resource for the language English, locale United States.
2. If it is not available, obtain the resource for the English language.
3. If it is not available, obtain the resource for the first locale available within the