Internationalize! (the basics)

Internationalize!

For code to be usable with different languages, it must first be ' internationalized'. This mainly involves using the _t(...) method where-ever there's a bit of text to be displayed in the CMS or on the website. Unfortunately not all of the (third party) SilverStripe modules have been prepared for this. It's just not high priority for everyone, but for us 'outlanders' it is often a matter of use/don't use :-( I usually try to internationalize right from the start, as it can be one hell of a job later on...

This page had slowly become a couple of meters long, so I decided to split it up in a couple of sections. This section covers the basics. The real stuff can be found here:

  • Translating static variables, fields and labels
  • Autogenerate a languagefile using i18nTextCollector - overview and issues
  • i18nEnum - a translatable Enum class

i18n - the basics

i18n stands for internationalization: preparing your code for use with different languages:

  • enabling different language profiles in the CMS Backend
  • enabling sites in different languages using your modules
  • enabling the use of Translatable to create multi-lingual websites

Within SilverStripe the basics are simple. There are three elements that make up the language system: the locale, the language file and the _t( … ) function. This goes for PHP classes and templates, but also, in a similar way, for JavaScript.

Silverstripe docs on i18n

The locale

The locale basically tells SilverStripe what language we use. The default locale in SilverStripe is en_US or Amarican English. If you want to create a website in an other language, you can set the locale in your mysite/_config.php:

// Set the locale to en_US or any other locale of your choice
i18n::set_locale('de_DE');

Locale in Translatable

When using Translatable to create a multi-lingual site, setting the locale in _config.php is not enough. Obviously the locale will change depending on the current language. This means that on every page you have to make sure the correct locale is loaded. You can do this by adding the following to your Page_Controller's init() function:

public function init() {

	parent::init();

	if($this->dataRecord->hasExtension('Translatable')) {
		i18n::set_locale($this->dataRecord->Locale);
	}
	...
}

The language file

Within SilverStripe each module should have its own language file that will always live in the /lang/ directory. The default locale for SilverStripe is en_US, so the en_US.php language file will serve as a 'blue-print' for translating a module into other languages. Basically a language file is nothing more than an array of available translations in the following way:

/lang/en_US.php

<?php

global $lang;

$lang['en_US']['namespace']['ENTITY'] = 'translated string';
...
  • namespace:  reference to the class or template where this specific translation is used
  • entity: identifies the specific entity for which this translation is to be used

The _t( … ) function

Instead of hardcoding a string, use the _t( … ) function to make SilverStripe seacrch the lanuage files for a proper translation. This function can be used from within PHP code as well as from within templates. The function accepts four parameters: $entity, $string, $priority and $context. They are explained extensively in the SilverStripe docs.

Most of the time just using the first two will do: _t('namespace.IDENTFIER', 'The string to be translated'). In a SilverStripe class:

class MyClass extends DataObject {

	function someFunction() {

		// don't do this:
		$title = 'A basic example';

		// but do this (use the classname (MyClass) as 'namespace'):
		$title = _t('MyClass.TITLE', 'A basic example');
		...
	}

Using the classname as namespace is a convention: as the same namespace will be used in the language file, it will be easy to link the translation to the class file where it is used. In a SilverStripe Template MyClass.ss:

<% _t('READMORE','Read more') %>

In a template you can leave out the namespace - SilverStripe will automatically add the template name (MyClass.ss - including the .ss extension). Again: a convention. In reality you can add anything you want for a namespace!

Beware: Letting SilverStripe add the namespace for a template doesn't always work so well for nested templates: SilverStripe might add the correct namespace, and then look for it using the namespace of the parent template!! If your translation doesn't work that might be the reason!

Beware: in a template there must be no whitespace after the comma. That might even result in displaying the function itself in the template instead of the translation!

If a translation can't be found...
If SilverStripe cannot find the translation file for the current Locale (or a specific translation in it), it will revert to the original string in the _t(...) function. In sapphire languagefiles you'll find that the en_US.php version is always included just in case, but you don't have to do that if all your _t(...) funtions have their string.

Using sprintf to create dynamic translations

You might want to add a variable to a translation, as for example in 'We found 23 results for your query'. In that case you would use the sprintf format:

$number = 23;

$result = sprintf( _t('MyClass.RESULT, 'We found %d results for your query '), $number);

You can do the same from a template, but beware that you can only use one argument here, and there can be no whitespaces between arguments!

<% sprintf( _t('RESULT, 'We found %d results for your query '), $number); %>

xxx

Comments

Het versturen van reacties is uitgeschakeld.

RSS feed voor reacties op deze pagina