Как изменить формат валюты в Magento 2?

8

В настоящее время цена показывает как $ 2.999,00

Я хочу, чтобы цена показывалась как 2 999,00 долларов США для локали es_MX (испанский, Мексика) на страницах продукта , где-либо еще формат валюты был правильным.

Я перепробовал все решения в stackexchange, но никто не работает.

Файл app / code / Jsp / Currency / etc / di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Framework\Locale\Format" type="Jsp\Currency\Model\Format"/>
</config>

Файл приложения / код / ​​JSP / валюта / модель / Format.php

<?php
namespace Jsp\Currency\Model;

use Magento\Framework\Locale\Bundle\DataBundle;

class Format extends \Magento\Framework\Locale\Format
{
    private static $defaultNumberSet = 'latn';

    public function getPriceFormat($localeCode = null, $currencyCode = null)
    {
        $localeCode = $localeCode ?: $this->_localeResolver->getLocale();
        if ($currencyCode) {
            $currency = $this->currencyFactory->create()->load($currencyCode);
        } else {
            $currency = $this->_scopeResolver->getScope()->getCurrentCurrency();
        }

        $localeData = (new DataBundle())->get($localeCode);
        $defaultSet = $localeData['NumberElements']['default'] ?: self::$defaultNumberSet;

        $format = $localeData['NumberElements'][$defaultSet]['patterns']['currencyFormat']
            ?: ($localeData['NumberElements'][self::$defaultNumberSet]['patterns']['currencyFormat']
                ?: explode(';', $localeData['NumberPatterns'][1])[0]);

        //your main changes are gone here.....
        if($localeCode == 'es_MX'){
            $decimalSymbol = '.';
            $groupSymbol = ',';
        }else{
            $decimalSymbol = $localeData['NumberElements'][$defaultSet]['symbols']['decimal']
                ?: ($localeData['NumberElements'][self::$defaultNumberSet]['symbols']['decimal']
                    ?: $localeData['NumberElements'][0]);

            $groupSymbol = $localeData['NumberElements'][$defaultSet]['symbols']['group']
                ?: ($localeData['NumberElements'][self::$defaultNumberSet]['symbols']['group']
                    ?: $localeData['NumberElements'][1]);
        }

        $pos = strpos($format, ';');
        if ($pos !== false) {
            $format = substr($format, 0, $pos);
        }
        $format = preg_replace("/[^0\#\.,]/", "", $format);
        $totalPrecision = 0;
        $decimalPoint = strpos($format, '.');
        if ($decimalPoint !== false) {
            $totalPrecision = strlen($format) - (strrpos($format, '.') + 1);
        } else {
            $decimalPoint = strlen($format);
        }
        $requiredPrecision = $totalPrecision;
        $t = substr($format, $decimalPoint);
        $pos = strpos($t, '#');
        if ($pos !== false) {
            $requiredPrecision = strlen($t) - $pos - $totalPrecision;
        }

        if (strrpos($format, ',') !== false) {
            $group = $decimalPoint - strrpos($format, ',') - 1;
        } else {
            $group = strrpos($format, '.');
        }
        $integerRequired = strpos($format, '.') - strpos($format, '0');

        $result = [
            //TODO: change interface
            'pattern' => $currency->getOutputFormat(),
            'precision' => $totalPrecision,
            'requiredPrecision' => $requiredPrecision,
            'decimalSymbol' => $decimalSymbol,
            'groupSymbol' => $groupSymbol,
            'groupLength' => $group,
            'integerRequired' => $integerRequired,
        ];       
        return $result;
    }
}

Поставщик файла / magento / framework / Locale / Format.php

<?php
/**
 * Copyright © 2016 Magento. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Magento\Framework\Locale;

use Magento\Framework\Locale\Bundle\DataBundle;

class Format implements \Magento\Framework\Locale\FormatInterface
{
    /**
     * @var string
     */
    private static $defaultNumberSet = 'latn';

    /**
     * @var \Magento\Framework\App\ScopeResolverInterface
     */
    protected $_scopeResolver;

    /**
     * @var \Magento\Framework\Locale\ResolverInterface
     */
    protected $_localeResolver;

    /**
     * @var \Magento\Directory\Model\CurrencyFactory
     */
    protected $currencyFactory;

    /**
     * @param \Magento\Framework\App\ScopeResolverInterface $scopeResolver
     * @param ResolverInterface $localeResolver
     * @param \Magento\Directory\Model\CurrencyFactory $currencyFactory
     */
    public function __construct(
        \Magento\Framework\App\ScopeResolverInterface $scopeResolver,
        \Magento\Framework\Locale\ResolverInterface $localeResolver,
        \Magento\Directory\Model\CurrencyFactory $currencyFactory
    ) {
        $this->_scopeResolver = $scopeResolver;
        $this->_localeResolver = $localeResolver;
        $this->currencyFactory = $currencyFactory;
    }

    /**
     * Returns the first found number from an string
     * Parsing depends on given locale (grouping and decimal)
     *
     * Examples for input:
     * '  2345.4356,1234' = 23455456.1234
     * '+23,3452.123' = 233452.123
     * ' 12343 ' = 12343
     * '-9456km' = -9456
     * '0' = 0
     * '2 054,10' = 2054.1
     * '2'054.52' = 2054.52
     * '2,46 GB' = 2.46
     *
     * @param string|float|int $value
     * @return float|null
     */
    public function getNumber($value)
    {
        if ($value === null) {
            return null;
        }

        if (!is_string($value)) {
            return floatval($value);
        }

        //trim spaces and apostrophes
        $value = str_replace(['\'', ' '], '', $value);

        $separatorComa = strpos($value, ',');
        $separatorDot = strpos($value, '.');

        if ($separatorComa !== false && $separatorDot !== false) {
            if ($separatorComa > $separatorDot) {
                $value = str_replace('.', '', $value);
                $value = str_replace(',', '.', $value);
            } else {
                $value = str_replace(',', '', $value);
            }
        } elseif ($separatorComa !== false) {
            $value = str_replace(',', '.', $value);
        }

        return floatval($value);
    }

    /**
     * Functions returns array with price formatting info
     *
     * @param string $localeCode Locale code.
     * @param string $currencyCode Currency code.
     * @return array
     * @SuppressWarnings(PHPMD.NPathComplexity)
     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
     */
    public function getPriceFormat($localeCode = null, $currencyCode = null)
    {
        $localeCode = $localeCode ?: $this->_localeResolver->getLocale();
        if ($currencyCode) {
            $currency = $this->currencyFactory->create()->load($currencyCode);
        } else {
            $currency = $this->_scopeResolver->getScope()->getCurrentCurrency();
        }
        $localeData = (new DataBundle())->get($localeCode);
        $defaultSet = $localeData['NumberElements']['default'] ?: self::$defaultNumberSet;
        $format = $localeData['NumberElements'][$defaultSet]['patterns']['currencyFormat']
            ?: ($localeData['NumberElements'][self::$defaultNumberSet]['patterns']['currencyFormat']
                ?: explode(';', $localeData['NumberPatterns'][1])[0]);

        $decimalSymbol = $localeData['NumberElements'][$defaultSet]['symbols']['decimal']
            ?: ($localeData['NumberElements'][self::$defaultNumberSet]['symbols']['decimal']
                ?: $localeData['NumberElements'][0]);

        $groupSymbol = $localeData['NumberElements'][$defaultSet]['symbols']['group']
            ?: ($localeData['NumberElements'][self::$defaultNumberSet]['symbols']['group']
                ?: $localeData['NumberElements'][1]);

        $pos = strpos($format, ';');
        if ($pos !== false) {
            $format = substr($format, 0, $pos);
        }
        $format = preg_replace("/[^0\#\.,]/", "", $format);
        $totalPrecision = 0;
        $decimalPoint = strpos($format, '.');
        if ($decimalPoint !== false) {
            $totalPrecision = strlen($format) - (strrpos($format, '.') + 1);
        } else {
            $decimalPoint = strlen($format);
        }
        $requiredPrecision = $totalPrecision;
        $t = substr($format, $decimalPoint);
        $pos = strpos($t, '#');
        if ($pos !== false) {
            $requiredPrecision = strlen($t) - $pos - $totalPrecision;
        }

        if (strrpos($format, ',') !== false) {
            $group = $decimalPoint - strrpos($format, ',') - 1;
        } else {
            $group = strrpos($format, '.');
        }
        $integerRequired = strpos($format, '.') - strpos($format, '0');

        $result = [
            //TODO: change interface
            'pattern' => $currency->getOutputFormat(),
            'precision' => $totalPrecision,
            'requiredPrecision' => $requiredPrecision,
            'decimalSymbol' => $decimalSymbol,
            'groupSymbol' => $groupSymbol,
            'groupLength' => $group,
            'integerRequired' => $integerRequired,
        ];

        return $result;
    }
}
Луис Гарсия
источник
Пожалуйста, проверьте обновленный ответ, и если у вас возникли проблемы, дайте мне знать, это рабочий код для вашей проблемы. Я имею ту же самую проблему, прибывающую для испанского сайта и решенную, используя код ниже. Спасибо.
Ракеш Джесадия
Удалите условия в вашем коде и просто оставьте $ decimalSymbol = '.' И $ groupSymbol = ',' удалите var и проверьте. Для получения дополнительной информации я держу обновленный код. Пожалуйста, проверь это.
Ракеш Джесадия
Убедитесь, что функция вашего пользовательского модуля вызывается или нет, вы можете отладить вышеуказанную функцию, если ваш код входит в функцию getPriceFormat или нет. Потому что код работает для меня для того же типа проблемы, с которой сталкивались со мной.
Ракеш Джесадия
Я заметил, что предоставленный вами файл Format.php немного отличается от того, который вы указали. Может ли это быть проблемой? Что касается отладки функции, можете ли вы объяснить более подробно, как я могу ее отладить?
Луис Гарсия
Нужно ли мне добавлять файл registration.php в папку моего модуля?
Луис Гарсия

Ответы:

16

создать простой модуль и переопределить файл по умолчанию * Format.php **,

Приложение / код / ​​пакет / MODULENAME / и т.д. / di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Framework\Locale\Format" type="Vendor\Currency\Model\Format" />
</config>

создать файл модели, приложение / код / ​​пакет / имя модуля / модель / формат.php

<?php
namespace Package\Modulename\Model;

use Magento\Framework\Locale\Bundle\DataBundle;

class Format extends \Magento\Framework\Locale\Format
{
    private static $defaultNumberSet = 'latn';

    public function getPriceFormat($localeCode = null, $currencyCode = null)
    {
        $localeCode = $localeCode ?: $this->_localeResolver->getLocale();
        if ($currencyCode) {
            $currency = $this->currencyFactory->create()->load($currencyCode);
        } else {
            $currency = $this->_scopeResolver->getScope()->getCurrentCurrency();
        }

        $localeData = (new DataBundle())->get($localeCode);
        $defaultSet = $localeData['NumberElements']['default'] ?: self::$defaultNumberSet;

        $format = $localeData['NumberElements'][$defaultSet]['patterns']['currencyFormat']
            ?: ($localeData['NumberElements'][self::$defaultNumberSet]['patterns']['currencyFormat']
                ?: explode(';', $localeData['NumberPatterns'][1])[0]);

        //your main changes are gone here.....
        $decimalSymbol = '.';
        $groupSymbol = ',';

        $pos = strpos($format, ';');
        if ($pos !== false) {
            $format = substr($format, 0, $pos);
        }
        $format = preg_replace("/[^0\#\.,]/", "", $format);
        $totalPrecision = 0;
        $decimalPoint = strpos($format, '.');
        if ($decimalPoint !== false) {
            $totalPrecision = strlen($format) - (strrpos($format, '.') + 1);
        } else {
            $decimalPoint = strlen($format);
        }
        $requiredPrecision = $totalPrecision;
        $t = substr($format, $decimalPoint);
        $pos = strpos($t, '#');
        if ($pos !== false) {
            $requiredPrecision = strlen($t) - $pos - $totalPrecision;
        }

        if (strrpos($format, ',') !== false) {
            $group = $decimalPoint - strrpos($format, ',') - 1;
        } else {
            $group = strrpos($format, '.');
        }
        $integerRequired = strpos($format, '.') - strpos($format, '0');

        $result = [
            //TODO: change interface
            'pattern' => $currency->getOutputFormat(),
            'precision' => $totalPrecision,
            'requiredPrecision' => $requiredPrecision,
            'decimalSymbol' => $decimalSymbol,
            'groupSymbol' => $groupSymbol,
            'groupLength' => $group,
            'integerRequired' => $integerRequired,
        ];       
        return $result;
    }
}

Спасибо.

Ракеш Джесадия
источник
Я попробовал ваше решение, но не сработало. Я обновил свой ответ с помощью кода di.xml, который я создал. Я также создал файл модели, изменив имя пакета и модуля в соответствии с именами моих папок
Луис Гарсия
Я обновил свой вопрос с помощью кода Format.php. Спасибо
Луис Гарсия
Я пробовал выше, это работает для страницы продукта, но не для страницы категории, интересно !!!
Зинат
это работает для всего сайта. пожалуйста, проверьте, может быть, у вас есть проблемы;
Ракеш Джесадия
@RakeshJesadiya, работает только на странице сведений о продукте и других ценах, таких как итоги, корзина и т. Д., Но не работает на странице листинга, мини-корзине, цене
корзины
3

Используйте код ниже:

$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$objectManager->create('\Magento\Framework\Pricing\PriceCurrencyInterface')->format('999,00',true,0);

Функция форматирования, как показано ниже:

public function format(
        $amount,
        $includeContainer = true,
        $precision = self::DEFAULT_PRECISION,
        $scope = null,
        $currency = null
    );

Если $ includeContainer = true, тогда цена будет показана с контейнером span

<span class="price">$999</span>

$precision = self::DEFAULT_PRECISIONОн будет отображать две десятичные точки. Использование 0 не будет отображать десятичную точку.

Прашант Валанда
источник
В каком файле я должен добавить этот код? Я новичок в Magento
Луис Гарсия
В каком файле я должен добавить этот код?
Луис Гарсия
3

По умолчанию Magento 2, формат цены немного странный для некоторых валют, поэтому мы должны изменить его. Вот способ изменить формат цены.

Вот пример для вьетнамского донга. По умолчанию отображаемый формат был 100.000,00. Затем я изменил его на 100 000 (разделенных запятой без десятичной точки).

# vendor/magento/zendframework1/library/Zend/Locale/Data/vi.xml
<symbols numbersystem="latn">
 <decimal>.</decimal>
 <group>,</group>
</symbols>

# vendor/magento/framework/Pricing/PriceCurrencyInterface.php
const DEFAULT_PRECISION = 0

# vendor/magento/module-directory/Model/Currency.php
return $this->formatPrecision($price, 0, $options, $includeContainer, $addBrackets);

# vendor/magento/module-sales/Model/Order.php
public function formatPrice($price, $addBrackets = false)
{
    return $this->formatPricePrecision($price, 0, $addBrackets);
}

Спасибо, наслаждайтесь :)

Аасим Гория
источник
попробовал, но не работает для es_MX
Луис Гарсия
1
  1. Перейдите из корневой папки в vendor / magento / zendframework1 / library / Zend / Locale / Data / es_MX.xml
  2. Искать <currencyFormat

Вы можете установить формат следующим образом:

<currencyFormat type="standard">
    <pattern draft="contributed">¤#,##0.00</pattern>
</currencyFormat>
Ашиш Джагнани
источник
Этот формат уже был установлен таким образом
Луис Гарсия
0

Чтобы изменить или удалить десятичные дроби для разных валют, вам просто нужно установить бесплатный модуль Currency Formatter Extension от Mageplaza по ссылке:  https://www.mageplaza.com/magento-2-currency-formatter/   .

Затем вы можете настроить десятичное число для ваших требований из админ-панели magento -> stores-> configuration-> Mageplaza Extensions. 

Это сработало для меня в установке magento 2.3.3. 

С наилучшими пожеланиями

Сотмир Лачи
источник
-1

Плохой способ сделать это (но быстрее) - это жестко кодировать вендор / magento / framework / Locale / Format.php

    $result = [
        //TODO: change interface
        'pattern' => $currency->getOutputFormat(),
        'precision' => $totalPrecision,
        'requiredPrecision' => $requiredPrecision,
        //'decimalSymbol' => $decimalSymbol,
        'decimalSymbol' =>'.',
        //'groupSymbol' => $groupSymbol,
        'groupSymbol' => ',',
        'groupLength' => $group,
        'integerRequired' => $integerRequired,
    ];
Алекс Давила
источник
Если это плохой путь, то зачем предлагать это? Мы никогда не должны изменять ядро ​​или поставщика.
Дэнни Ниммо
Спасибо. Я искал быстрое грязное решение, так как хочу исправить умирающий веб-сайт, пока я работаю над его новой версией.
Хасан аль-Йеши