How to extend CFormatter, add i18n support to booleanFormat and use it in CDetailView

You are viewing revision #3 of this wiki article.
This is the latest version of this article.
You may want to see the changes made in this revision.

« previous (#2)

As you know, the CDetailView widget displays details of a single model. If no formatting is specified, boolean values that are stored in the database as 0 and 1, are represented in the detail view as 0 and 1. If formatted as boolean, they are represented as 'No' and 'Yes'. We want to add i18n support, so that Yes and No appear in the current language.

In the following example, 'Logged' is a boolean attribute. You can tell the widget to format the value of that attribute as a boolean so it will be either 'No' or 'Yes', like this:

$this->widget('zii.widgets.CDetailView', array(
	'data' => $model,
	'attributes' => array(
		'ID',
		'Logged:boolean',
	),
));

In this case, the formatBoolean() method of the class CFormatter will be applied to the attribute value (see the class reference for details). This essentially replaces 0 with a 'No', and 1 with a 'Yes', which looks much nicer.

To be exact: the class CFormatter has a public property named booleanFormat which defaults to array('No', 'Yes'). The formatBoolean() method replaces a 0 with its first element, and a 1 with its second element.

If the application language is different from english, say german, it would look much nicer if 0 became 'Nein' and 1 became 'Ja'. The first thing that comes to (my) mind is to override the booleanFormat property in the config file like this:

'components'=>array( //...
	'format'=>array(
		'booleanFormat'=>array(Yii::t('app','No'), Yii::t('app','Yes')),
	), // ...
),

Only, this doesn't work (I guess Yii::t() cannot be used in the config file). We could override it with array('Nein','Ja'), which would work, but we don't want to hardcode the german translations here to keep things flexible.

So we extend the CFormatter class. For this we create the file /protected/components/Formatter.php, override the function formatBoolean(), and add a new function while we're at it:

class Formatter extends CFormatter {
	public function formatBoolean($value){
			return $value ? Yii::t('app', $this->booleanFormat[1]) : Yii::t('app',$this->booleanFormat[0]);
	}

	public function formatHeadline($value) {
		return '<b>' . $value . '</b>';
	}
}

The new method formatHeadline() prints the value in bold.

Then we tell Yii to use this class in the config file like this:

'components'=>array( //...
	'format'=>array(
		'class'=>'application.components.Formatter',
	), // ...
),


The value of the 'ID' attribute in the following example will now be displayed in bold letters.

$this->widget('zii.widgets.CDetailView', array(
	'data' => $model,
	'attributes' => array(
		'ID:headline',
		'Name',
		'Logged:boolean',
	),
));


It is that easy to add new and more complicated formatters and simplify your CDetailView calls. Same goes for CGridView.