ZF-3423: Validate_Float doesn't work with local than doesn't have a dot as decimal separator

Issue Type: Bug Created: 2008-06-09T14:10:58.000+0000 Last Updated: 2008-12-19T04:02:41.000+0000 Status: Resolved Fix version(s): - 1.8.0 (30/Apr/09)

Reporter: Jérémy Lajotte (pengu) Assignee: Thomas Weidner (thomas) Tags: - Zend_Validate

Related issues: - ZF-4000

Attachments: - Zend_Validate.patch


The php function strval use the decimal point character that is defined in the script's locale (category LC_NUMERIC), so depending on the local set in PHP.

For instance, strval(1.2) return "1,2" in "fr_FR.utf8" locale.

So basicaly the isValid() function of the Zend_Validate_Float class does this :

<pre class="highlight">
        $locale = localeconv();
        $valueFiltered = str_replace($locale['thousands_sep'], '', $valueString);
        $valueFiltered = str_replace($locale['decimal_point'], '.', $valueFiltered);
        if (strval(floatval($valueFiltered)) != $valueFiltered) {
          /* only true if the $locale['thousands_sep'] is already '' and $locale['decimal_point'] is already '.' */

Here, the code replace the locale decimal point by '.' and remove the locale thousand separator and then compare this string to the same string, convertred to float and displayed using that same locale decimal point and locale thousand separator ... well, the only chance for this to work is if the locale decimal point IS already a '.' and the locale thousand separator is ''.

I think this should be enough to test if a value is a float :

<pre class="highlight">
if (false===ereg('^[0-9]*\.[0-9]+$', $valueFiltered)){
  /* not a float */


Posted by Thomas Weidner (thomas) on 2008-06-10T11:34:18.000+0000

Attention: You should also take in account that users may have set Zend_Locale to a different locale than the one from setlocale (setlocale is not threadsave).

So we could have system set to french and user setting arabic. Validate should be able also to verify such.

Easiest solution: Allow a locale to be set Use Zend_Locale to normalize the value.

Posted by Adam Kusmierz (raistlin) on 2008-09-10T15:21:18.000+0000

This should be resolve this issue. It matches old value with converted from string to float and again to string old value.

Posted by Thomas Weidner (thomas) on 2008-12-09T00:45:15.000+0000

The patch does not work when the user is using Zend_Form with an application locale. Input could be "1,2" even it system locale is set to "en" because the application locale is set to "fr".

The validation would still fail. Therefor this fix does not solve the problem, only part of it.

Posted by Adam Kusmierz (raistlin) on 2008-12-10T12:25:00.000+0000

And what with this:… ?

Posted by Thomas Weidner (thomas) on 2008-12-10T12:56:50.000+0000

This is the same patch which I commented... there is no difference.

Posted by Sven Franke (snefit) on 2008-12-10T23:12:05.000+0000


I use this 'solution'. Maybe it isn't a correct one but it works for me in the application.

<pre class="literal">

class Application_Validate_Float extends Zend_Validate_Float {
    const NOT_FLOAT = 'notFloat';

     * Message templates.
     * @var array
    protected $_messageTemplates = array(
        self::NOT_FLOAT => "'%value%' does not appear to be a float"

     * Locale
     * @var Zend_Locale
    protected $_locale;
     * Constructor
     * @param string|Zend_Locale|null $locale
    public function __construct($locale = null) {
     * Returns the locale option
     * @return string|Zend_Locale|null
    public function getLocale()
        return $this->_locale;

     * Sets the locale option
     * @param  string|Zend_Locale $locale
     * @return Zend_Validate_Date provides a fluent interface
    public function setLocale($locale = null)
        if ($locale === null) {
            $this->_locale = null;
            return $this;

        require_once 'Zend/Locale.php';
        if (!Zend_Locale::isLocale($locale, true, false)) {
            if (!Zend_Locale::isLocale($locale, false, false)) {
                require_once 'Zend/Validate/Exception.php';
                throw new Zend_Validate_Exception("The locale '$locale' is no known locale");

            $locale = new Zend_Locale($locale);

        $this->_locale = (string) $locale;
        return $this;
     * Defined by Zend_Validate_Interface
     * Returns true if and only if $value is a floating-point value
     * @param  string $value
     * @return boolean
    public function isValid($value)
        $valueString = (string) $value;


//        // ORIGINAL FROM ZEND_FLOAT (ZF 1.7.0)
//        $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;
//        }

        // Locale aware.
        if(!Zend_Locale_Format::isFloat($value, array('locale' => $locale))) { 
            return false; 
        return true;

Posted by Thomas Weidner (thomas) on 2008-12-11T06:46:36.000+0000

Yes, this solution is the right direction. It can be used as workaround and shows what I said to be the solution.

There are only part details which will be changed by me.

Thanks Sven :-)

Posted by Thomas Weidner (thomas) on 2008-12-19T04:02:38.000+0000

New feature added with r13372

Have you found an issue?

See the Overview section for more details.


© 2006-2018 by Zend, a Rogue Wave Company. Made with by awesome contributors.

This website is built using zend-expressive and it runs on PHP 7.