Skip to content
This repository was archived by the owner on May 16, 2018. It is now read-only.

Zend_Locale_Format::toNumber() fails with setlocale(LC_ALL, 'de_DE') #514

Closed
chmielot opened this issue Feb 18, 2015 · 7 comments
Closed

Comments

@chmielot
Copy link
Contributor

I am not sure what causes this issue, as I am not able to reproduce it on every machine I have.
To test it I extended zf1/tests/Zend/Locale/FormatTest.php with the following code:

    public function testToNumberSetlocale()
    {
        setlocale(LC_ALL, 'de_DE'); // test setup
        $locale_de = new Zend_Locale('de_DE');
        var_dump(localeconv());
        $params_de = array('precision' => 2, 'locale' => $locale_de);
        $myFloat = 3.2;
        var_dump($myFloat);
        $test1 = Zend_Locale_Format::toNumber($myFloat, $params_de);
        $this->assertEquals("3,2", $test1);
    }

I am var_dumping the float to see if setlocale settings are active, it should output float(3,3) when everything i correct.
Unfortunately I get:

1) Zend_Locale_FormatTest::testToNumberSetlocale
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'3,20'
+'320,00'

I ran this test with phpunit 4.5.0, PHP 5.3.26 on debian wheezy Linux dev 3.2.0-4-amd64 #1 SMP Debian 3.2.60-1+deb7u3 x86_64 GNU/Linux

I read about this problem on the internet, but none of the developers was ever able to reproduce it.

The exact same test is running successfully on my Mac with phpunit 4.5.0, PHP 5.4.24, Darwin mac 13.3.0 Darwin Kernel Version 13.3.0: Tue Jun 3 21:27:35 PDT 2014; root:xnu-2422.110.17~1/RELEASE_X86_64 x86_64

There is one difference in the output of localeconv() though:
Debian

array(18) {
  ["decimal_point"]=>
  string(1) ","
  ["thousands_sep"]=>
  string(1) "."
  ["int_curr_symbol"]=>
  string(4) "EUR "
  ["currency_symbol"]=>
  string(3) "EUR"
  ["mon_decimal_point"]=>
  string(1) ","
  ["mon_thousands_sep"]=>
  string(1) "."
  ["positive_sign"]=>
  string(0) ""
  ["negative_sign"]=>
  string(1) "-"
  ["int_frac_digits"]=>
  int(2)
  ["frac_digits"]=>
  int(2)
  ["p_cs_precedes"]=>
  int(0)
  ["p_sep_by_space"]=>
  int(1)
  ["n_cs_precedes"]=>
  int(0)
  ["n_sep_by_space"]=>
  int(1)
  ["p_sign_posn"]=>
  int(1)
  ["n_sign_posn"]=>
  int(1)
  ["grouping"]=>
  array(2) {
    [0]=>
    int(3)
    [1]=>
    int(3)
  }
  ["mon_grouping"]=>
  array(2) {
    [0]=>
    int(3)
    [1]=>
    int(3)
  }
}

Mac:

array(18) {
  ["decimal_point"]=>
  string(1) ","
  ["thousands_sep"]=>
  string(0) ""
  ["int_curr_symbol"]=>
  string(4) "EUR "
  ["currency_symbol"]=>
  string(2) "Eu"
  ["mon_decimal_point"]=>
  string(1) ","
  ["mon_thousands_sep"]=>
  string(1) "."
  ["positive_sign"]=>
  string(0) ""
  ["negative_sign"]=>
  string(1) "-"
  ["int_frac_digits"]=>
  int(2)
  ["frac_digits"]=>
  int(2)
  ["p_cs_precedes"]=>
  int(1)
  ["p_sep_by_space"]=>
  int(0)
  ["n_cs_precedes"]=>
  int(1)
  ["n_sep_by_space"]=>
  int(0)
  ["p_sign_posn"]=>
  int(1)
  ["n_sign_posn"]=>
  int(1)
  ["grouping"]=>
  array(1) {
    [0]=>
    int(127)
  }
  ["mon_grouping"]=>
  array(2) {
    [0]=>
    int(3)
    [1]=>
    int(3)
  }
}

There is no thousands separator defined on the mac! If I set the locale on the debian machine to it_IT the test runs succesfully with the following output for localeconv:

array(18) {
  ["decimal_point"]=>
  string(1) ","
  ["thousands_sep"]=>
  string(0) ""
  ["int_curr_symbol"]=>
  string(4) "EUR "
  ["currency_symbol"]=>
  string(3) "EUR"
  ["mon_decimal_point"]=>
  string(1) ","
  ["mon_thousands_sep"]=>
  string(1) "."
  ["positive_sign"]=>
  string(0) ""
  ["negative_sign"]=>
  string(1) "-"
  ["int_frac_digits"]=>
  int(2)
  ["frac_digits"]=>
  int(2)
  ["p_cs_precedes"]=>
  int(1)
  ["p_sep_by_space"]=>
  int(1)
  ["n_cs_precedes"]=>
  int(1)
  ["n_sep_by_space"]=>
  int(1)
  ["p_sign_posn"]=>
  int(1)
  ["n_sign_posn"]=>
  int(1)
  ["grouping"]=>
  array(0) {
  }
  ["mon_grouping"]=>
  array(2) {
    [0]=>
    int(3)
    [1]=>
    int(3)
  }
}

On the mac it_IT results in the following for localeconv:

array(18) {
  ["decimal_point"]=>
  string(1) ","
  ["thousands_sep"]=>
  string(2) ". "
  ["int_curr_symbol"]=>
  string(4) "EUR "
  ["currency_symbol"]=>
  string(2) "Eu"
  ["mon_decimal_point"]=>
  string(1) ","
  ["mon_thousands_sep"]=>
  string(1) "."
  ["positive_sign"]=>
  string(0) ""
  ["negative_sign"]=>
  string(1) "-"
  ["int_frac_digits"]=>
  int(2)
  ["frac_digits"]=>
  int(2)
  ["p_cs_precedes"]=>
  int(1)
  ["p_sep_by_space"]=>
  int(1)
  ["n_cs_precedes"]=>
  int(1)
  ["n_sep_by_space"]=>
  int(1)
  ["p_sign_posn"]=>
  int(1)
  ["n_sign_posn"]=>
  int(1)
  ["grouping"]=>
  array(0) {
  }
  ["mon_grouping"]=>
  array(2) {
    [0]=>
    int(3)
    [1]=>
    int(3)
  }
}

and runs successfully too, even though there is a thousands separator set.

Any help is appreciated, tell me if you need more information. Using Zend Framework 1.12.11, it also fails on 1.12.3

@froschdesign
Copy link
Member

Please recheck with PHPs NumberFormatter class:

$fmt = new NumberFormatter('de_DE', NumberFormatter::DECIMAL);
$this->assertEquals('3,2', $fmt->format(3.2));

@chmielot
Copy link
Contributor Author

The test is successfull with the NumberFormatter assertion.

@froschdesign
Copy link
Member

The test is successfull with the NumberFormatter assertion.

This is a good reason to refactor your application.

@chmielot
Copy link
Contributor Author

Excuse me, how is this related to my application? I'm just extending the original ZF1 unit tests with the provided test case completely independant of my application.
Moreover I don't see how a successfull test with the NumberFormatter class is an answer to the problem. The NumberFormatter class is not used in the Zend_Locale_* classes.

@froschdesign
Copy link
Member

Moreover I don't see how a successfull test with the NumberFormatter class is an answer to the problem. The NumberFormatter class is not used in the Zend_Locale_* classes.

You should use the NumberFormatter class instead of Zend_Locale. It could be the first step of the migration to the a newer ZF version.
Yes, my suggestions is a little bit radical, but Zend_Locale is buggy and slow. (It is also hard to maintain and a big fat code monster.)

@chmielot
Copy link
Contributor Author

OK, then there was a misunderstanding obviously ;).
Thank you for that suggestion. It is definitely a solution in this case. Please decide yourself what to do with this issue. If anybody is interested in investagating further and I can help with that, please let me know.

@froschdesign
Copy link
Member

Please decide yourself what to do with this issue.

The current consideration is to mark Zend_Locale and Zend_Date as deprecated, but we need a migration path for both components.

Btw. Thanks for reporting!

@chmielot chmielot closed this as completed Nov 2, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

2 participants