I am a bit unhappy how formatting values is currently being handled by Yii. While this is straightforward in most cases, setting custom formatters in place is less than ideal: If I’d want to format e.g. filesizes and money values, I would have to write a custom MyFormatter class and set it in place instead of CFormatter. This absolutely has to be an all-purpose class, which makes sharing formatters between projects/branches quite hard. Also: Setting CFormatter up for i18n is a bit tedious. So can we please:
[list=1]
[*]Have a CFormatter class that respects the locale setting?
[*]Have a better way of registering custom single-purpose formatters? My current idea were to have a CFormatter.customFormatters array holding a list of custom formatters. If a CFormatter.formatXyz method isn’t present, CFormatter would check that list in order for formatters with such a method.
[/list]
I opened an issue on this about a year ago, I did my own CLocaleFormater that uses Yii format functions, and it was very straightforward to write.
Are you referring to ticket #892?
I might be asking for a bit much … But would it be possible to have some locale-aware wrappers for CNumberFormatter? A formatFloat() would be a nice-to-have as well. I’m afraid the current i18n data won’t be sufficient for that, though.
For referece, here is my CLocaleFormatter, it is very simple:
/**
* CLocaleFormatter class file.
*
* @author Rangel Reale <rangelreale@gmail.com>
* @link http://www.yiiframework.com/
* @copyright Copyright © 2008-2010 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* CLocateFormatter formats using the current locale.
*
* @author Rangel Reale <rangelreale@gmail.com>
* @version $Id$
* @package system.utils
* @since 1.1.1
*/
class CLocaleFormatter extends CFormatter
{
/**
* @var string the format width to be used to format a date using CDateFormatter formatDateTime function. Defaults to 'medium'.
*/
public $dateFormatWidth='medium';
/**
* @var string the format width to be used to format a time using CDateFormatter formatDateTime function. Defaults to 'medium'.
*/
public $timeFormatWidth='medium';
/**
* Formats the value as a date.
* @param mixed the value to be formatted
* @return string the formatted result
* @see dateFormatWidth
*/
public function formatDate($value)
{
return Yii::app()->dateFormatter->formatDateTime($value, $this->dateFormatWidth, null);
}
/**
* Formats the value as a time.
* @param mixed the value to be formatted
* @return string the formatted result
* @see timeFormatWidth
*/
public function formatTime($value)
{
return Yii::app()->dateFormatter->formatDateTime($value, null, $this->timeFormatWidth);
}
/**
* Formats the value as a date and time.
* @param mixed the value to be formatted
* @return string the formatted result
* @see dateFormatWidth
* @see timeFormatWidth
*/
public function formatDatetime($value)
{
return Yii::app()->dateFormatter->formatDateTime($value, $this->dateFormatWidth, $this->timeFormatWidth);
}
/**
* Formats the value as a number using the locale.
* @param mixed the value to be formatted
* @return string the formatted result
*/
public function formatNumber($value)
{
return Yii::app()->locale->numberFormatter->formatDecimal($value, '');
}
/**
* Formats the value as a currency using the locale.
* @param mixed the value to be formatted
* @return string the formatted result
* @see numberFormat
*/
public function formatCurrency($value, $currency='')
{
return Yii::app()->locale->numberFormatter->formatCurrency($value, '');
}
/**
* Formats the value as a percentage using the locale.
* @param mixed the value to be formatted
* @return string the formatted result
* @see numberFormat
*/
public function formatPercentage($value)
{
return Yii::app()->locale->numberFormatter->formatPercentage($value, '');
}
/**
* Formats the value as a percentage using the locale.
* @param mixed the value to be formatted
* @return string the formatted result
* @see numberFormat
*/
public function formatStatistical($value)
{
return Yii::app()->locale->numberFormatter->formatStatistical($value, '');
}
/**
* Parses the value as a date.
* @param mixed the value to be parsed
* @return string the parsed result
* @see dateFormatWidth
*/
public function parseDate($value)
{
if ($value!==null && $value!='')
return CDateTimeParser::parse($value, Yii::app()->locale->getDateFormat($this->dateFormatWidth));
return null;
}
/**
* Parses the value as a time.
* @param mixed the value to be parsed
* @return string the parsed result
* @see timeFormatWidth
*/
public function parseTime($value)
{
if ($value!==null && $value!='')
return CDateTimeParser::parse($value, Yii::app()->locale->getTimeFormat($this->timeFormatWidth));
return null;
}
/**
* Parses the value as a date and time.
* @param mixed the value to be parsed
* @return string the parsed result
* @see dateFormatWidth
* @see timeFormatWidth
*/
public function parseDatetime($value)
{
if ($value!==null && $value!='')
{
$dtformat=strtr(Yii::app()->locale->dateTimeFormat,array('{0}'=>Yii::app()->locale->getTimeFormat($this->timeFormatWidth),'{1}'=>Yii::app()->locale->getDateFormat($this->dateFormatWidth)));
return CDateTimeParser::parse($value, $dtformat);
}
return null;
}
/**
* Parse the value as a number formatted by the PHP number_format() function.
* @param mixed the value to be parsed
* @return string the parsed result
* @see numberFormat
*/
public function parseNumber($value)
{
$nparse=new CNumberParser(Yii::app()->locale);
return $nparse->parseDecimal($value);
}
/**
* Parses the value as a currency using PHP number_format() function.
* @param mixed the value to be parsed
* @return string the parsed result
* @see numberFormat
*/
public function parseCurrency($value, $currency='')
{
$nparse=new CNumberParser(Yii::app()->locale);
return $nparse->parseCurrency($value, $currency);
}
/**
* Parses the value as a percentage using PHP number_format() function.
* @param mixed the value to be parsed
* @return string the parsed result
* @see numberFormat
*/
public function parsePercentage($value)
{
$nparse=new CNumberParser(Yii::app()->locale);
return $nparse->parsePercentage($value);
}
/**
* Parses the value as a percentage using PHP number_format() function.
* @param mixed the value to be parsed
* @return string the parsed result
* @see numberFormat
*/
public function parseStatistical($value)
{
$nparse=new CNumberParser(Yii::app()->locale);
return $nparse->parseStatistical($value);
}
}
Hm, convenient. Thanks for sharing. I know, it isn’t up to par, but have my formatter for filesizes in return 
class FilesizeFormatter extends CFormatter{
public $suffixes=array(
'B',
'KB',
'MB',
'GB',
'TB',
'PB',
);
public function formatFilesize($value)
{
$e=(int)floor(log($value, 1024));
if($e > 0 && array_key_exists($e, $this->suffixes))
return sprintf('%.2f', $value/pow(1024, $e)).$this->suffixes[$e];
else
return $this->formatNumber($value).'B';
}
}