Skip to content
This repository has been archived by the owner on Nov 28, 2023. It is now read-only.

Multilingual applications

fballiano edited this page Aug 31, 2012 · 1 revision

P4A has a great multilingual and multilocale support and allows you to create multilingual and multilocale applications.

The P4A_LOCALE constant

This is the most important localization configuration, you've to set this constant (in the index.php file of your application, before requiring p4a.php) to your locale:

define("P4A_LOCALE", "it_IT"); // for italian users

the default value is

define("P4A_LOCALE", "en_US");

Setting P4A_LOCALE will automatically make P4A output every message translated in your language (P4A supports more than 40 languages). If you don't set P4A_LOCALE in your index.php you can still change the locale of your application, read the next section to understand how.

Changing locale within the application lifecycle

Within any part of your application simply:

p4a::singleton()->i18n->setLocale("it_IT"); // replace it_IT with your locale

Retrieving currently used language/country/locale

$locale = p4a::singleton()->i18n->getLocale(); // eg: en_US
$language = p4a::singleton()->i18n->getLanguage(); // eg: en
$country = p4a::singleton()->i18n->getCountry(); // eg: US

P4A core messages and application messages

P4A contains a lot of messages that are already translated in many languages, these messages are used by P4A's core components and widgets and that's the reason why we provide them already translated.

Developing your application you'll surely add more messages (just think about the fiels names of a table) that's won't be translated until you manually provide P4A the translations.

How to add translated messages to your application

All components within P4A will call the p4a::singleton()->i18n->translate() method when a translated string in needed. This method looks within P4A's internal dictionary for the translation, if it doesn't find any it simply returns the original string.

Developing your application you'll need to fill P4A's internal dictionary with your own translations.

Reading and parsing your translation files is completely up to you, this gives maximum flexibility, in facts you can use a simple array to store your translations (if you're developing a little application) or use on of the Zend_Translate components or build your own solution.

Let's take a look at a simple example to fill P4A's internal dictionary

$msg = array();
$msg['Message number 1'] = 'Translated message 1';
$msg['Message number 2'] = 'Translated message 2';
p4a::singleton()->i18n->mergeTranslation($msg);

Obviously defining the $msg array within the source code is not a best practice, you surely want (at least) to have it in an external file, something like:

@include(P4A_APPLICATION_DIR . '/i18n/' . $this->i18n->getLanguage() . '.php');
if (isset($msg)) $this->i18n->mergeTranslation($msg);

A complete example

Check products_catalogue application's source code, it's bundled with P4A's default download package. This sample contains different languages and also a mask where user is allowed to choose his preferred language, clicking on the apply button the application will change P4A's locale and load the news translations.

Tracking translations (available since P4A 3.0.3)

Most of the times you write your application in your natural language (or better in English), but after some time you need to add multilingual support and you need to send all the messages to the translators.

How can you gather all messages that need to be translated?

P4A helps you with the ontranslate event. Intercept it with a code like this (in your main application class, the one that extends P4A itself):

$this->implement("ontranslate", $this, "traslationsTrack");

than create the traslationsTrack method, that will look like:

public function traslationsTrack($o, $string, $translation, $translated)
{
	$this->TO_TRANSLATE[$string] = $translation; // continuously fills a temporary array with all strings
}

We've four parameters, the first is always the object triggering the event (simply don't look at it, you don't need it here), but you've three important parameters here:

  • $string: the original string that needs to be translated
  • $translation: the available translation
  • $translated: boolean, is string translated or not?

If you want to gather only untranslated strings just change the traslationsTrack method this way:

public function traslationsTrack($o, $string, $translation, $translated)
{
	if ($translated) return; // discard translated strings
	$this->TO_TRANSLATE[$string] = $translation; // continuously fills a temporary array with all strings
}

Now you can simply browse your applications, opening masks, saving, creating data etc. Every string that needs translation will be gathered, when you're done you can change the traslationsTrack method this way:

public function traslationsTrack($o, $string, $translation, $translated)
{
	foreach ($this->TO_TRANSLATE as $a) {
		print '$msg["'.$a.'"] = "";' . "<br>";
	}
	die();
}

Now hit the refresh button on your browser. This action will print all the strings in an array form, ready for a cut&paste operation.

Obviously you can change the traslationsTrack method as you like, saving to a database or whatever, you've endless possibilities.