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 ------------ Installation of this package is fairly simple. First, the following files should be available for any application that wishes to use this package: DatabaseConnectionManager.class.php DatabaseDataSource.class.php DataSource.class.php Dommer.class.php FileDataSource.class.php I18N.class.php 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. Usage ----- First of all, we need to include the necessary files: require_once('path/to/I18N.class.php'); 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 File"): $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 require_once('path/to/DatabaseConnection.class.php'); $databaseConnection =& new DatabaseConnection(); $databaseConnection->setDbDriver('mysql'); $databaseConnection->setDbHost('localhost'); $databaseConnection->setDbUser('root'); $databaseConnection->setDbPassword('password'); $databaseConnection->setDbName('test'); $databaseConnection->setDbTablePrefix(''); $databaseConnection->open(); 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: $i18n->setDataSource($dataSource); Next, we should set which language (and optionally which locale) we'll be using: $i18n->setLanguage('en'); $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: $i18n->setContainer('language'); 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: echo $container['section']['element']; $section, following this procedure, is an array indexed by elements. To obtain the element called 'element' within this section, we do: echo $section['element']; Finally, $element is a single string, which can be printed out as follows: echo $element; 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 have. 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: container.language_locale.extension 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: language.en.lang If we want to define it for the locale United Kingdom within english: language.en_uk.lang Database Structure ------------------ 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 structure. 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 particular locale.) About Localization ------------------ 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: language.en_uk.lang 2. If it is not available, it will then look for a file called: language.en.lang 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 English Language.