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

11 followers

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.

Total 3 comments

#15824 report it
ametad at 2013/12/20 05:38am
Yii supports i18n formatting since version 1.14
#12931 report it
DZ-015 at 2013/04/21 03:29pm
How about just extending the array - just for the boolean values?

I just added a __construct() function to wrap the array elements with the translate function. Is this a good practice?

class Formatter extends CFormatter {
    public function __construct() {
         $this->booleanFormat=array(Yii::t('app', $this->booleanFormat[0]),Yii::t('app', $this->booleanFormat[1]));
    }
}

Because this allows me to add simple dropdown filters in GridView as well:

...
   'filter'=>  Yii::app()->format->booleanFormat
...
#7048 report it
yiqing95 at 2012/02/21 09:07am
a general way to change the core component class !

@c@cba great works ! here you can see a general method to change the yii's core components to our own class(just extends the subclass of CApplicationComponet includes the some core compoent: request , db etc..). thanks to the ioc tech , the CWebApplication is a components container and a huge object factory , we refer the component instance from it (eg: Yii::app()->someComponetId ; ) thus we can change most components of Yii cores .

Leave a comment

Please to leave your comment.

Write new article