Zend Framework and locales
Last night I spent a couple of hours with Zend Framework and especially Zend_Form. I discovered, and now also reported as ZF-6175, a bug in Zend_Validate_Float when using a locale with a decimal point other than “.”. There are unit tests but none that test Zend_Validate_Float under a different locale.
It is important to know that floats are actually locale aware in PHP. I’m not sure if that have always been the case. The below code will actually output 10,5 as Swedish use “,” as decimal point.
setlocale(LC_ALL, 'sv_SE.UTF-8'); echo 10.5;
The test in Zend_Validate_Float looked like
$locale = localeconv();
$valueFiltered = str_replace($locale['thousands_sep'], '', $valueString);
$valueFiltered = str_replace($locale['decimal_point'], '.', $valueFiltered);
if (strval(floatval($valueFiltered)) != $valueFiltered) {
$this->_error();
return false;
}
Under the Swedish locale mentioned above this will result in a comparison between two strings; “10,5″ and “10.5″.
I have proposed the following solution.
$locale = localeconv();
$valueFiltered = str_replace($locale['thousands_sep'], '', $valueString);
$valueFiltered = str_replace($locale['decimal_point'], '.', $valueFiltered);
list($num, $dec) = explode('.', $valueFiltered);
if (strval(intval($num)) != $num || strval(intval($dec)) != $dec) {
$this->_error();
return false;
}
But I just realized that it can be further simplified.
$locale = localeconv();
$valueFiltered = str_replace($locale['thousands_sep'], '', $valueString);
list($num, $dec) = explode($locale['decimal_point'], $valueFiltered);
if (strval(intval($num)) != $num || strval(intval($dec)) != $dec) {
$this->_error();
return false;
}
If you enjoyed this post, please consider to leave a comment or subscribe to the feed and get future articles delivered to your feed reader.
Comments
4 Responses to “Zend Framework and locales”Trackbacks
Check out what others are saying about this post...-
[...] a new post to his blog Danne Lundqvist take a look at using locales in the Zend Framework and a [...]

I think its hopeless to ask libraries to play nice with set_locale(). Just wait for PHP6, until then either dont use set_locale() or if you must do it in your own code and revert it back to standard the second you call other peoples code.
Hopeless? Well if no one reports errors the of course no one will fix them…
And why I would wait for PHP 6 I don’t know. This particular problem is in Zend Framework. Not PHP.
Aaah, this behavior has bitten me too! I was in a hurry to fix it, so my “fix” was to remove Zend_Locale and use str_replace and number_format instead (It’s an app that will never have another locale than de_DE). Great to see that it is indeed a bug und not my misunderstanding of I18N.
@Lucas If you can wait for PHP 6 that’s a great luxury I don’t have. I have customers that want to have apps to display their prices NOW. Not using set_locale is not an option because of encoding requirements. Reverting to the default locale would be ok (but would produce long code with each formatting and conversion of a number taking 3 lines instead of 1), but if this patch fixes the behavior in a future-proof way I am very thankful.