猿问

NumberFormatter:在不同区域设置中带有减号的奇怪行为

我遇到了Symfony/Form的问题,它在幕后用于NumberFormatter格式化NumberType字段。我们的项目是多语言的,对于每个国家,我们使用不同的区域设置。


$formatter->format()返回负数的不同减号。例如:


$formatter = new \NumberFormatter('en', \NumberFormatter::DECIMAL);

$value = $formatter->format('-150');

var_dump($value); // string(4) "-150"


$formatter = new \NumberFormatter('lt', \NumberFormatter::DECIMAL);

$value = $formatter->format('-150');

var_dump($value); // string(6) "−150" <-- here is the problem

正如您所看到的,NumberFormatter减号更改为其他内容。


为什么它对我很重要?因为页面上有些元素是用javascript生成的,而js无法解析−150number 并返回NaN。


有人可以解释这种行为的原因以及如何从 lt 语言环境中获得正确的减号吗?NumberFormatter


繁星点点滴滴
浏览 104回答 3
3回答

不负相思意

我找到了解决方案。Symfony/Form有一个很棒的功能,可以添加视图转换器,它在渲染表单元素之前渲染。这是我的FormType:public function buildForm(FormBuilderInterface $builder, array $options){    $builder->add('amount', NumberType::class, array(        'required' => true,        'scale' => 4,    ));    $builder->get('amount')->addViewTransformer(new CallbackTransformer(        function ($forward) {            // Transform the lithuanian minus sign to the normal minus sign.            return preg_replace('/\x{2212}/u', '-', $forward);        },        function ($reverse) {            return $reverse;        }    ));    // others form elements...}这种方法允许覆盖默认的视图转换器,为其\Symfony\Component\Form\Extension\Core\Type\NumberType添加特定的减号。$builder->addViewTransformer(new NumberToLocalizedStringTransformer(    $options['scale'],    $options['grouping'],    $options['rounding_mode'],    $options['html5'] ? 'en' : null));需要明确的是,以自定义表单添加的视图转换器比任何其他合并的转换器具有更高的优先级。它一般不能解决 的问题NumberFormatter,但可以帮助我解决我的问题。

长风秋雁

转换成ascii怎么样?$formatter = new \NumberFormatter('lt', \NumberFormatter::DECIMAL);$value = $formatter->format('-150');$valueAsAscii = iconv('utf8', 'ascii//translit', $value);var_dump($value);var_dump($valueAsAscii);工作示例。输出string(6) "−150" string(4) "-150"

白衣染霜花

这里真正的问题是,根据给定的语言环境,输出NumberFormatter应该是人类可读的,而不一定可以解析为数字。您可以通过覆盖该符号来解决此特定问题:$formatter = new \NumberFormatter('lt', \NumberFormatter::DECIMAL);$formatter->setSymbol(\NumberFormatter::MINUS_SIGN_SYMBOL, '-');$value = $formatter->format('-150');var_dump($value); // string(4) "-150"但是,请考虑千位分隔符或小数分隔符,它们也不一定在 JavaScript 中进行解析:$formatter = new \NumberFormatter('lt', \NumberFormatter::DECIMAL);$formatter->setSymbol(\NumberFormatter::MINUS_SIGN_SYMBOL, '-');$value = $formatter->format('-150000.5');var_dump($value); // string(11) "-150 000,5"您也可以覆盖这些符号,但这里的要点是,您可能应该根据用户的区域设置有一个人类可读的版本,以及一个由 JavaScript 解析的单独的机器可读版本。如果您仍然想用来NumberFormatter输出机器可读的版本,您可以使用'en'区域设置,但您仍然需要覆盖分组分隔符:$machineFormatter = new \NumberFormatter('en', \NumberFormatter::DECIMAL);$machineFormatter->setSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL, '');
随时随地看视频慕课网APP
我要回答