diff --git a/vendor/magento/module-bundle/Ui/DataProvider/Product/Modifier/SpecialPriceAttributes.php b/vendor/magento/module-bundle/Ui/DataProvider/Product/Modifier/SpecialPriceAttributes.php
index cbe4dfa7483..1a19e566a77 100644
--- a/vendor/magento/module-bundle/Ui/DataProvider/Product/Modifier/SpecialPriceAttributes.php
+++ b/vendor/magento/module-bundle/Ui/DataProvider/Product/Modifier/SpecialPriceAttributes.php
@@ -9,12 +9,10 @@ namespace Magento\Bundle\Ui\DataProvider\Product\Modifier;
 
 use Magento\Bundle\Model\Product\Type;
 use Magento\Directory\Model\Currency as DirectoryCurrency;
-use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Currency\Data\Currency as CurrencyData;
 use Magento\Framework\Locale\ResolverInterface;
 use Magento\Ui\DataProvider\Modifier\ModifierInterface;
 use NumberFormatter;
-use Zend_Currency;
-use Zend_Currency_Exception;
 
 /**
  * Modify product listing special price attributes
@@ -55,8 +53,6 @@ class SpecialPriceAttributes implements ModifierInterface
 
     /**
      * @inheritdoc
-     * @throws NoSuchEntityException
-     * @throws Zend_Currency_Exception
      */
     public function modifyData(array $data): array
     {
@@ -74,7 +70,7 @@ class SpecialPriceAttributes implements ModifierInterface
                     $item[$priceAttribute] =
                         $this->directoryCurrency->format(
                             $item[$priceAttribute],
-                            ['display' => Zend_Currency::NO_SYMBOL],
+                            ['display' => CurrencyData::NO_SYMBOL],
                             false
                         );
                     $item[$priceAttribute] = $numberFormatter->format($item[$priceAttribute] / 100);
diff --git a/vendor/magento/module-configurable-product/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php b/vendor/magento/module-configurable-product/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php
index 7815408321e..f01a8877d63 100644
--- a/vendor/magento/module-configurable-product/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php
+++ b/vendor/magento/module-configurable-product/Ui/DataProvider/Product/Form/Modifier/Data/AssociatedProducts.php
@@ -13,12 +13,13 @@ use Magento\Catalog\Model\Product;
 use Magento\CatalogInventory\Api\StockRegistryInterface;
 use Magento\ConfigurableProduct\Model\Product\Type\Configurable as ConfigurableType;
 use Magento\ConfigurableProduct\Model\Product\Type\VariationMatrix;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Currency\Exception\CurrencyException;
+use Magento\Framework\Escaper;
 use Magento\Framework\Exception\NoSuchEntityException;
 use Magento\Framework\Json\Helper\Data as JsonHelper;
 use Magento\Framework\Locale\CurrencyInterface;
 use Magento\Framework\UrlInterface;
-use Magento\Framework\App\ObjectManager;
-use Magento\Framework\Escaper;
 
 /**
  * Associated products helper
@@ -232,7 +233,7 @@ class AssociatedProducts
      * Prepare variations
      *
      * @return void
-     * @throws \Zend_Currency_Exception
+     * @throws CurrencyException
      * @SuppressWarnings(PHPMD.CyclomaticComplexity)
      * phpcs:disable Generic.Metrics.NestingLevel.TooHigh
      */
diff --git a/vendor/magento/module-quote/Model/Quote/Validator/MinimumOrderAmount/ValidationMessage.php b/vendor/magento/module-quote/Model/Quote/Validator/MinimumOrderAmount/ValidationMessage.php
index 78aa31d7d95..c7e566b5520 100644
--- a/vendor/magento/module-quote/Model/Quote/Validator/MinimumOrderAmount/ValidationMessage.php
+++ b/vendor/magento/module-quote/Model/Quote/Validator/MinimumOrderAmount/ValidationMessage.php
@@ -20,6 +20,7 @@ class ValidationMessage
     /**
      * @var \Magento\Framework\Locale\CurrencyInterface
      * @deprecated 101.0.3 since 101.0.0
+     * @see no alternatives
      */
     private $currency;
 
@@ -51,7 +52,6 @@ class ValidationMessage
      * Get validation message.
      *
      * @return \Magento\Framework\Phrase
-     * @throws \Zend_Currency_Exception
      */
     public function getMessage()
     {
diff --git a/vendor/magento/module-quote/Model/ValidationRules/MinimumAmountValidationRule.php b/vendor/magento/module-quote/Model/ValidationRules/MinimumAmountValidationRule.php
index 34e953be43c..0c50b97a5be 100644
--- a/vendor/magento/module-quote/Model/ValidationRules/MinimumAmountValidationRule.php
+++ b/vendor/magento/module-quote/Model/ValidationRules/MinimumAmountValidationRule.php
@@ -48,7 +48,6 @@ class MinimumAmountValidationRule implements QuoteValidationRuleInterface
 
     /**
      * @inheritdoc
-     * @throws \Zend_Currency_Exception
      */
     public function validate(Quote $quote): array
     {
diff --git a/vendor/magento/module-reports/Block/Adminhtml/Grid/Column/Renderer/Currency.php b/vendor/magento/module-reports/Block/Adminhtml/Grid/Column/Renderer/Currency.php
index 1ebfd64b2f3..97d0493c5d9 100644
--- a/vendor/magento/module-reports/Block/Adminhtml/Grid/Column/Renderer/Currency.php
+++ b/vendor/magento/module-reports/Block/Adminhtml/Grid/Column/Renderer/Currency.php
@@ -7,10 +7,11 @@ declare(strict_types=1);
 
 namespace Magento\Reports\Block\Adminhtml\Grid\Column\Renderer;
 
-use Magento\Backend\Block\Widget\Grid\Column\Renderer\Currency as BackendCurrency;
 use Magento\Backend\Block\Context;
+use Magento\Backend\Block\Widget\Grid\Column\Renderer\Currency as BackendCurrency;
 use Magento\Directory\Model\Currency\DefaultLocator;
 use Magento\Directory\Model\CurrencyFactory;
+use Magento\Framework\Currency\Exception\CurrencyException;
 use Magento\Framework\DataObject;
 use Magento\Framework\Exception\LocalizedException;
 use Magento\Framework\Exception\NoSuchEntityException;
@@ -18,7 +19,6 @@ use Magento\Framework\Locale\CurrencyInterface;
 use Magento\Store\Model\ScopeInterface;
 use Magento\Store\Model\Store;
 use Magento\Store\Model\StoreManagerInterface;
-use Zend_Currency_Exception;
 
 /**
  * Adminhtml grid item renderer currency
@@ -70,7 +70,7 @@ class Currency extends BackendCurrency
      * @return string
      * @throws LocalizedException
      * @throws NoSuchEntityException
-     * @throws Zend_Currency_Exception
+     * @throws CurrencyException
      */
     public function render(DataObject $row)
     {
@@ -80,13 +80,10 @@ class Currency extends BackendCurrency
         if (!$currencyCode) {
             return $data;
         }
-
         $rate = $this->getStoreCurrencyRate($currencyCode, $row);
-
-        $data = (float)$data * $rate;
-        $data = sprintf("%f", $data);
-        $data = $this->_localeCurrency->getCurrency($currencyCode)->toCurrency($data);
-        return $data;
+        $data = (float) $data * $rate;
+        $data = sprintf('%f', $data);
+        return $this->_localeCurrency->getCurrency($currencyCode)->toCurrency($data);
     }
 
     /**
diff --git a/vendor/magento/module-sales/Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php b/vendor/magento/module-sales/Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php
index 781fb3b7501..59a19014f6c 100644
--- a/vendor/magento/module-sales/Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php
+++ b/vendor/magento/module-sales/Block/Adminhtml/Order/Creditmemo/Create/Adjustments.php
@@ -5,9 +5,9 @@
  */
 namespace Magento\Sales\Block\Adminhtml\Order\Creditmemo\Create;
 
+use Magento\Framework\Currency\Data\Currency as CurrencyData;
 use Magento\Framework\Pricing\PriceCurrencyInterface;
 use Magento\Sales\Model\Order;
-use Zend_Currency;
 
 /**
  * Credit memo adjustments block
@@ -25,8 +25,6 @@ class Adjustments extends \Magento\Backend\Block\Template
     protected $_source;
 
     /**
-     * Tax config
-     *
      * @var \Magento\Tax\Model\Config
      */
     protected $_taxConfig;
@@ -86,7 +84,7 @@ class Adjustments extends \Magento\Backend\Block\Template
         return $order->getOrderCurrency()->formatPrecision(
             $value,
             2,
-            ['display' => Zend_Currency::NO_SYMBOL],
+            ['display' => CurrencyData::NO_SYMBOL],
             false,
             false
         );
diff --git a/vendor/magento/framework/Currency.php b/vendor/magento/framework/Currency.php
index 1eb74f3bb3c..fa022e7f514 100644
--- a/vendor/magento/framework/Currency.php
+++ b/vendor/magento/framework/Currency.php
@@ -6,24 +6,26 @@
 namespace Magento\Framework;
 
 use Magento\Framework\App\CacheInterface;
+use Magento\Framework\Currency\Data\Currency as CurrencyData;
+use Magento\Framework\Currency\Exception\CurrencyException;
 
-class Currency extends \Zend_Currency implements CurrencyInterface
+class Currency extends CurrencyData implements CurrencyInterface
 {
     /**
      * Creates a currency instance.
      *
      * @param CacheInterface $appCache
-     * @param string|array $options Options array or currency short name when string is given
-     * @param string $locale Locale name
+     * @param array|string|null $options Options array or currency short name when string is given
+     * @param string|null $locale Locale name
+     * @throws CurrencyException
      */
     public function __construct(
         CacheInterface $appCache,
         $options = null,
         $locale = null
     ) {
-        // set Zend cache to low level frontend app cache
         $lowLevelFrontendCache = $appCache->getFrontend()->getLowLevelFrontend();
-        \Zend_Currency::setCache($lowLevelFrontendCache);
+        self::setCache($lowLevelFrontendCache);
         parent::__construct($options, $locale);
     }
 }
diff --git a/vendor/magento/framework/Currency/Data/Currency.php b/vendor/magento/framework/Currency/Data/Currency.php
new file mode 100644
index 00000000000..ce1d5494852
--- /dev/null
+++ b/vendor/magento/framework/Currency/Data/Currency.php
@@ -0,0 +1,749 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+declare(strict_types=1);
+
+namespace Magento\Framework\Currency\Data;
+
+use Locale;
+use Magento\Framework\Currency\Exception\CurrencyException;
+use Magento\Framework\NumberFormatter;
+use Symfony\Component\Intl\Countries;
+use Symfony\Component\Intl\Currencies;
+use Zend_Cache_Core;
+use Magento\Framework\CurrencyInterface;
+
+/**
+ * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
+ */
+class Currency
+{
+    public const NO_SYMBOL = 1;
+    public const USE_SYMBOL = 2;
+    public const USE_SHORTNAME = 3;
+    public const USE_NAME = 4;
+    public const STANDARD = 8;
+    public const RIGHT = 16;
+    public const LEFT = 32;
+
+    /**
+     * @var Zend_Cache_Core
+     */
+    private static $cache = null;
+
+    /**
+     * @var array
+     */
+    protected $options = [
+        'position' => self::STANDARD,
+        'display' => self::NO_SYMBOL,
+        'precision' => 2,
+        'name' => null,
+        'currency' => null,
+        'symbol' => null,
+        'locale' => null,
+        'value' => 0
+    ];
+
+    /**
+     * @var array
+     */
+    private $displayLocale = [
+        'AED' => 'ar_AE', 'AFN' => 'fa_AF', 'ALL' => 'sq_AL', 'AMD' => 'hy_AM',
+        'AOA' => 'pt_AO', 'ARS' => 'es_AR', 'AUD' => 'en_AU', 'AWG' => 'nl_AW',
+        'AZN' => 'az_Latn_AZ', 'BAM' => 'bs_BA', 'BBD' => 'en_BB', 'BDT' => 'bn_BD',
+        'BGN' => 'bg_BG', 'BHD' => 'ar_BH', 'BIF' => 'rn_BI', 'BMD' => 'en_BM',
+        'BND' => 'ms_BN', 'BOB' => 'es_BO', 'BRL' => 'pt_BR', 'BSD' => 'en_BS',
+        'BTN' => 'dz_BT', 'BWP' => 'en_BW', 'BYN' => 'be_BY', 'BZD' => 'en_BZ',
+        'CAD' => 'en_CA', 'CDF' => 'sw_CD', 'CLP' => 'es_CL', 'COP' => 'es_CO',
+        'CRC' => 'es_CR', 'CUP' => 'es_CU', 'CVE' => 'kea_CV', 'CZK' => 'cs_CZ',
+        'DJF' => 'aa_DJ', 'DKK' => 'da_DK', 'DOP' => 'es_DO', 'DZD' => 'ar_DZ',
+        'EGP' => 'ar_EG', 'ERN' => 'ti_ER', 'ETB' => 'en_ET', 'FJD' => 'hi_FJ',
+        'FKP' => 'en_FK', 'GEL' => 'ka_GE', 'GHS' => 'ak_GH', 'GIP' => 'en_GI',
+        'GMD' => 'en_GM', 'GNF' => 'fr_GN', 'GTQ' => 'es_GT', 'GYD' => 'en_GY',
+        'HKD' => 'zh_Hant_HK', 'HNL' => 'es_HN', 'HRK' => 'hr_HR', 'HTG' => 'ht_HT',
+        'HUF' => 'hu_HU', 'IDR' => 'id_ID', 'ILS' => 'he_IL', 'INR' => 'hi_IN',
+        'IQD' => 'ar_IQ', 'IRR' => 'fa_IR', 'ISK' => 'is_IS', 'JMD' => 'en_JM',
+        'JOD' => 'ar_JO', 'JPY' => 'ja_JP', 'KES' => 'en_KE', 'KGS' => 'ky_Cyrl_KG',
+        'KHR' => 'km_KH', 'KMF' => 'ar_KM', 'KPW' => 'ko_KP', 'KRW' => 'ko_KR',
+        'KWD' => 'ar_KW', 'KYD' => 'en_KY', 'KZT' => 'ru_KZ', 'LAK' => 'lo_LA',
+        'LBP' => 'ar_LB', 'LKR' => 'si_LK', 'LRD' => 'en_LR', 'LYD' => 'ar_LY',
+        'MAD' => 'ar_EH', 'MDL' => 'ro_MD', 'MGA' => 'mg_MG', 'MKD' => 'mk_MK',
+        'MMK' => 'my_MM', 'MNT' => 'mn_Cyrl_MN', 'MOP' => 'zh_Hant_MO', 'MRU' => 'ar_MR',
+        'MUR' => 'mfe_MU', 'MVR' => 'dv_MV', 'MWK' => 'ny_MW', 'MXN' => 'es_MX',
+        'MYR' => 'ms_MY', 'MZN' => 'pt_MZ', 'NAD' => 'kj_NA', 'NGN' => 'en_NG',
+        'NIO' => 'es_NI', 'NPR' => 'ne_NP', 'OMR' => 'ar_OM', 'PAB' => 'es_PA',
+        'PEN' => 'es_PE', 'PGK' => 'tpi_PG', 'PHP' => 'fil_PH', 'PKR' => 'ur_PK',
+        'PLN' => 'pl_PL', 'PYG' => 'gn_PY', 'QAR' => 'ar_QA', 'RON' => 'ro_RO',
+        'RSD' => 'sr_Cyrl_RS', 'RUB' => 'ru_RU', 'RWF' => 'rw_RW', 'SAR' => 'ar_SA',
+        'SBD' => 'en_SB', 'SCR' => 'crs_SC', 'SDG' => 'ar_SD', 'SEK' => 'sv_SE',
+        'SGD' => 'en_SG', 'SHP' => 'en_SH', 'SLL' => 'kri_SL', 'SOS' => 'sw_SO',
+        'SRD' => 'srn_SR', 'STN' => 'pt_ST', 'SYP' => 'ar_SY', 'SZL' => 'en_SZ',
+        'THB' => 'th_TH', 'TJS' => 'tg_Cyrl_TJ', 'TMT' => 'tk_TM', 'TND' => 'ar_TN',
+        'TOP' => 'to_TO', 'TRY' => 'tr_TR', 'TTD' => 'en_TT', 'TWD' => 'zh_Hant_TW',
+        'TZS' => 'sw_TZ', 'UAH' => 'uk_UA', 'UGX' => 'sw_UG', 'USD' => 'en_GU',
+        'UYU' => 'es_UY', 'UZS' => 'uz_Cyrl_UZ', 'VES' => 'es_VE', 'VND' => 'vi_VN',
+        'VUV' => 'bi_VU', 'WST' => 'sm_WS', 'XCD' => 'en_AI', 'YER' => 'ar_YE',
+        'ZAR' => 'en_ZA', 'ZMW' => 'en_ZM'
+    ];
+
+    /**
+     * @param array|string|null $options
+     * @param string|null $locale
+     * @throws CurrencyException
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     */
+    public function __construct($options = null, $locale = null)
+    {
+        $callOptions = $options;
+
+        if (is_array($options) && isset($options['display'])) {
+            $this->options['display'] = $options['display'];
+        }
+        $this->setLocale($locale);
+
+        if (!isset($this->options['currency']) || !is_array($options)) {
+            $this->options['currency'] = $this->getShortName($options, $this->options['locale']);
+        }
+        if (!isset($this->options['name']) || !is_array($options)) {
+            $this->options['name'] = $this->getName($options, $this->options['locale']);
+        }
+        if (!isset($this->options['symbol']) || !is_array($options)) {
+            $this->options['symbol'] = $this->getSymbol($options, $this->options['locale']);
+        }
+        if ($this->options['currency'] === null && $this->options['name'] === null) {
+            throw new CurrencyException(__(
+                'Currency "%1" not found',
+                $options
+            ));
+        }
+        if ((is_array($callOptions) && !isset($callOptions['display']))
+            || (!is_array($callOptions) && $this->options['display'] == self::NO_SYMBOL)) {
+            if (!empty($this->options['symbol'])) {
+                $this->options['display'] = self::USE_SYMBOL;
+            } elseif (!empty($this->options['currency'])) {
+                $this->options['display'] = self::USE_SHORTNAME;
+            }
+        }
+    }
+
+    /**
+     * Returns a localized currency string.
+     *
+     * @param float|int|null $value
+     * @param array $options
+     * @return string
+     * @throws CurrencyException
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     * @SuppressWarnings(PHPMD.NPathComplexity)
+     */
+    public function toCurrency($value = null, array $options = []): string
+    {
+        if ($value === null) {
+            $value = $options['value'] ?? $this->options['value'];
+        }
+        if (is_array($value)) {
+            $options += $value;
+            if (isset($options['value'])) {
+                $value = $options['value'];
+            }
+        }
+        if (!isset($value) || !is_numeric($value)) {
+            throw new CurrencyException(__(
+                'Value "%1" has to be numeric',
+                $value
+            ));
+        }
+        if (isset($options['currency'])) {
+            if (!isset($options['locale'])) {
+                $options['locale'] = $this->options['locale'];
+            }
+            $options['currency'] = $this->getShortName($options['currency'], $options['locale']);
+            $options['name'] = $this->getName($options['currency'], $options['locale']);
+            $options['symbol'] = $this->getSymbol($options['currency'], $options['locale']);
+        }
+        $options = array_merge($this->options, $this->checkOptions($options));
+        $numberFormatter = new NumberFormatter($options['locale'], NumberFormatter::CURRENCY);
+        $value = $numberFormatter->format((float) $value);
+
+        if (is_numeric($options['display']) === false) {
+            $sign = $options['display'];
+        } else {
+            switch ($options['display']) {
+                case self::USE_SYMBOL:
+                    $sign = $options['symbol'];
+                    break;
+                case self::USE_SHORTNAME:
+                    $sign = $options['currency'];
+                    break;
+                case self::USE_NAME:
+                    $sign = $options['name'];
+                    break;
+                default:
+                    $sign = '';
+                    $value = str_replace(' ', '', $value);
+            }
+        }
+
+        return str_replace($this->getSymbol(null, $options['locale']), (string) $sign, $value);
+    }
+
+    /**
+     * Sets the formatting options of the localized currency string.
+     *
+     * @param array $options
+     * @return Currency
+     * @throws CurrencyException
+     */
+    public function setFormat(array $options = []): Currency
+    {
+        $this->options = array_merge($this->options, $this->checkOptions($options));
+        return $this;
+    }
+
+    /**
+     * Internal function for checking static given locale parameter
+     *
+     * @param string|null $currency
+     * @param string|null $locale
+     * @return array
+     * @throws CurrencyException
+     */
+    private function checkParams(?string $currency = null, ?string $locale = null): array
+    {
+        if (empty($locale) && !empty($currency)) {
+            $locale = $currency;
+            $currency = null;
+        }
+        if (strlen($locale) > 4) {
+            $country = substr($locale, (strpos($locale, '_') + 1));
+        } else {
+            throw new CurrencyException(__(
+                'No region found within the locale "%1"',
+                $locale
+            ));
+        }
+
+        $data = NumberFormatter::create($locale, NumberFormatter::CURRENCY)
+            ->getTextAttribute(NumberFormatter::CURRENCY_CODE);
+
+        if (!empty($currency) && !empty($data)) {
+            $abbreviation = $currency;
+        } else {
+            $abbreviation = $data;
+        }
+
+        return ['locale' => $locale, 'currency' => $currency, 'name' => $abbreviation, 'country' => $country];
+    }
+
+    /**
+     * Returns the actual or details of other currency symbols.
+     *
+     * @param string|null $currency
+     * @param string|null $locale
+     * @return string|null
+     * @throws CurrencyException
+     */
+    public function getSymbol($currency = null, $locale = null): ?string
+    {
+        if ($currency === null && $locale === null) {
+            return $this->options['symbol'];
+        }
+        $params = $this->checkParams($currency, $locale);
+
+        if (!empty($params['currency'])) {
+            $locale = $this->displayLocale[$params['currency']] ?? $params['locale'];
+            $symbol = Currencies::getSymbol($params['currency'], $locale);
+        } else {
+            $symbol = Currencies::getSymbol($params['name'], $params['locale']);
+        }
+
+        return !empty($symbol) ? $symbol : null;
+    }
+
+    /**
+     * Returns the actual or details of other currency shortnames.
+     *
+     * @param string|null $currency
+     * @param string|null $locale
+     * @return string|null
+     * @throws CurrencyException
+     */
+    public function getShortName($currency = null, $locale = null): ?string
+    {
+        if ($currency === null && $locale === null) {
+            return $this->options['currency'];
+        }
+        $params = $this->checkParams($currency, $locale);
+
+        return $params['name'];
+    }
+
+    /**
+     * Returns the actual or details of other currency names.
+     *
+     * @param string|null $currency
+     * @param string|null $locale
+     * @return string|null
+     * @throws CurrencyException
+     */
+    public function getName($currency = null, $locale = null): ?string
+    {
+        if ($currency === null && $locale === null) {
+            return $this->options['name'];
+        }
+        $params = $this->checkParams($currency, $locale);
+
+        if (!empty($params['currency'])) {
+            $name = Currencies::getName($params['currency'], $params['locale']);
+        } else {
+            $name = Currencies::getName($params['name'], $params['locale']);
+        }
+
+        if (empty($name)) {
+            return null;
+        }
+
+        return $name;
+    }
+
+    /**
+     * Returns a list of regions where this currency is or was known.
+     *
+     * @param string|null $currency
+     * @return array
+     * @throws CurrencyException
+     */
+    public function getRegionList($currency = null): array
+    {
+        if ($currency === null) {
+            $currency = $this->options['currency'];
+        }
+        if (empty($currency)) {
+            throw new CurrencyException(__('No currency defined'));
+        }
+        $countryCodes = Countries::getCountryCodes();
+        $data = [];
+
+        foreach ($countryCodes as $countryCode) {
+            $locale = strtolower($countryCode) . '_' . $countryCode;
+            $regionCurrency = NumberFormatter::create($locale, NumberFormatter::CURRENCY)
+                ->getTextAttribute(NumberFormatter::CURRENCY_CODE);
+
+            if ($regionCurrency === $currency) {
+                $data[] = $countryCode;
+            }
+        }
+
+        return $data;
+    }
+
+    /**
+     * Returns a list of currencies which are used in this region.
+     *
+     * @param string|null $region
+     * @return array
+     */
+    public function getCurrencyList($region = null): array
+    {
+        if (empty($region)) {
+            if (strlen($this->options['locale']) > 4) {
+                $region = substr($this->options['locale'], (strpos($this->options['locale'], '_') + 1));
+            }
+        }
+        $locale = strtolower($region) . '_' . $region;
+        $data = NumberFormatter::create($locale, NumberFormatter::CURRENCY)
+            ->getTextAttribute(NumberFormatter::CURRENCY_CODE);
+
+        return explode(' ', $data);
+    }
+
+    /**
+     * Returns the actual currency name.
+     *
+     * @return string
+     * @throws CurrencyException
+     */
+    public function toString(): string
+    {
+        return $this->toCurrency();
+    }
+
+    /**
+     * Returns the currency name.
+     *
+     * @return string
+     * @throws CurrencyException
+     */
+    public function __toString()
+    {
+        return $this->toString();
+    }
+
+    /**
+     * Returns the set cache.
+     *
+     * @return Zend_Cache_Core
+     */
+    public static function getCache()
+    {
+        return self::$cache;
+    }
+
+    /**
+     * Sets a cache for Currency
+     *
+     * @param Zend_Cache_Core $cache
+     * @return void
+     */
+    public static function setCache(Zend_Cache_Core $cache)
+    {
+        self::$cache = $cache;
+    }
+
+    /**
+     * Returns true when a cache is set.
+     *
+     * @return bool
+     */
+    public static function hasCache()
+    {
+        return self::$cache !== null;
+    }
+
+    /**
+     * Removes any set cache.
+     *
+     * @return void
+     */
+    public static function removeCache()
+    {
+        self::$cache = null;
+    }
+
+    /**
+     * Clears all set cache data.
+     *
+     * @param string|null $tag
+     * @return void
+     * @throws \Zend_Cache_Exception
+     */
+    public static function clearCache($tag = null): void
+    {
+        if ($tag) {
+            self::$cache->clean(\Zend_Cache::CLEANING_MODE_MATCHING_TAG, $tag);
+        } else {
+            self::$cache->clean(\Zend_Cache::CLEANING_MODE_ALL);
+        }
+    }
+
+    /**
+     * Sets a new locale for data retirement.
+     *
+     * @param string|null $locale
+     * @return Currency
+     * @throws CurrencyException
+     */
+    public function setLocale($locale = null): Currency
+    {
+        $locale = $locale ?? Locale::getDefault();
+
+        if (strlen($locale) > 4) {
+            $this->options['locale'] = $locale;
+        } else {
+            throw new CurrencyException(__(
+                'No region found within the locale "%1"',
+                $locale
+            ));
+        }
+
+        $this->options['currency'] = $this->getShortName(null, $this->options['locale']);
+        $this->options['name'] = $this->getName(null, $this->options['locale']);
+        $this->options['symbol'] = $this->getSymbol(null, $this->options['locale']);
+
+        return $this;
+    }
+
+    /**
+     * Returns the actual set locale.
+     *
+     * @return string
+     */
+    public function getLocale(): string
+    {
+        return $this->options['locale'];
+    }
+
+    /**
+     * Returns the value.
+     *
+     * @return float
+     */
+    public function getValue(): float
+    {
+        return $this->options['value'];
+    }
+
+    /**
+     * Adds a currency.
+     *
+     * @param float|int|Currency $value
+     * @param string|Currency $currency
+     * @return Currency
+     * @throws CurrencyException
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
+     */
+    public function setValue($value, $currency = null): Currency
+    {
+        $this->options['value'] = $this->exchangeCurrency($value, $currency);
+        return $this;
+    }
+
+    /**
+     * Adds a currency.
+     *
+     * @param float|int|Currency $value
+     * @param string|Currency $currency
+     * @return Currency
+     * @throws CurrencyException
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
+     */
+    public function add($value, $currency = null): Currency
+    {
+        $value = $this->exchangeCurrency($value, $currency);
+        $this->options['value'] += (float) $value;
+
+        return $this;
+    }
+
+    /**
+     * Sub a currency.
+     *
+     * @param float|int|Currency $value
+     * @param string|Currency $currency
+     * @return Currency
+     * @throws CurrencyException
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
+     */
+    public function sub($value, $currency = null): Currency
+    {
+        $value = $this->exchangeCurrency($value, $currency);
+        $this->options['value'] -= (float) $value;
+
+        return $this;
+    }
+
+    /**
+     * Divides a currency.
+     *
+     * @param float|int|Currency $value
+     * @param string|Currency $currency
+     * @return Currency
+     * @throws CurrencyException
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
+     */
+    public function div($value, $currency = null): Currency
+    {
+        $value = $this->exchangeCurrency($value, $currency);
+        $this->options['value'] /= (float) $value;
+
+        return $this;
+    }
+
+    /**
+     * Multiplies a currency.
+     *
+     * @param float|int|Currency $value
+     * @param string|Currency $currency
+     * @return Currency
+     * @throws CurrencyException
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
+     */
+    public function mul($value, $currency = null): Currency
+    {
+        $value = $this->exchangeCurrency($value, $currency);
+        $this->options['value'] *= (float) $value;
+
+        return $this;
+    }
+
+    /**
+     * Calculates the modulo from a currency.
+     *
+     * @param float|int|Currency $value
+     * @param string|Currency $currency
+     * @return Currency
+     * @throws CurrencyException
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
+     */
+    public function mod($value, $currency = null): Currency
+    {
+        $value = $this->exchangeCurrency($value, $currency);
+        $this->options['value'] %= (float) $value;
+
+        return $this;
+    }
+
+    /**
+     * Compares two currencies.
+     *
+     * @param float|int|Currency $value
+     * @param string|Currency $currency
+     * @return int
+     * @throws CurrencyException
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
+     */
+    public function compare($value, $currency = null): int
+    {
+        $value = $this->exchangeCurrency($value, $currency);
+        $value = $this->options['value'] - $value;
+        return $value <=> 0;
+    }
+
+    /**
+     * Returns true when the two currencies are equal.
+     *
+     * @param float|int|Currency $value
+     * @param string|Currency $currency
+     * @return bool
+     * @throws CurrencyException
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
+     */
+    public function equals($value, $currency = null): bool
+    {
+        $value = $this->exchangeCurrency($value, $currency);
+        return $this->options['value'] == $value;
+    }
+
+    /**
+     * Returns true when the currency is more than the given value.
+     *
+     * @param float|int|Currency $value
+     * @param string|Currency $currency
+     * @return bool
+     * @throws CurrencyException
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
+     */
+    public function isMore($value, $currency = null): bool
+    {
+        $value = $this->exchangeCurrency($value, $currency);
+        return $this->options['value'] > $value;
+    }
+
+    /**
+     * Returns true when the currency is less than the given value.
+     *
+     * @param float|int|CurrencyInterface $value
+     * @param string|CurrencyInterface $currency
+     * @return bool
+     * @throws CurrencyException
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
+     */
+    public function isLess($value, $currency = null): bool
+    {
+        $value = $this->exchangeCurrency($value, $currency);
+        return $this->options['value'] < $value;
+    }
+
+    /**
+     * Internal method which calculates the exchange currency.
+     *
+     * @param float|int|CurrencyInterface $value
+     * @param string|CurrencyInterface $currency
+     * @return int
+     * @throws CurrencyException
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
+     */
+    protected function exchangeCurrency($value, $currency)
+    {
+        if ($value instanceof CurrencyInterface) {
+            $currency = $value->getShortName();
+            $value = $value->getValue();
+        } else {
+            $currency = $this->getShortName($currency, $this->getLocale());
+        }
+        $rate = 1;
+
+        if ($currency !== $this->getShortName()) {
+            // This exception throw because Zend_Service no longer exists.
+            throw new CurrencyException(__('No exchange service not work'));
+        }
+
+        return $value * $rate;
+    }
+
+    /**
+     * Internal method for checking the options array.
+     *
+     * @param array $options Options to check
+     * @return array
+     * @throws CurrencyException
+     * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+     */
+    protected function checkOptions($options = []): array
+    {
+        if (count($options) === 0) {
+            return $this->options;
+        }
+
+        foreach ($options as $name => $value) {
+            $name = strtolower($name);
+
+            if ($name !== 'format') {
+                if (gettype($value) === 'string') {
+                    $value = strtolower($value);
+                }
+            }
+
+            switch ($name) {
+                case 'position':
+                    if (!in_array($value, [self::STANDARD, self::RIGHT, self::LEFT], true)) {
+                        throw new CurrencyException(
+                            __('Unknown position "%1"', $value)
+                        );
+                    }
+                    break;
+                case 'display':
+                    if (is_numeric($value)
+                        && !in_array(
+                            $value,
+                            [self::NO_SYMBOL, self::USE_SYMBOL, self::USE_SHORTNAME, self::USE_NAME],
+                            true
+                        )
+                    ) {
+                        throw new CurrencyException(
+                            __('Unknown display "%1"', $value)
+                        );
+                    }
+                    break;
+                case 'precision':
+                    if ($value === null) {
+                        $value = -1;
+                    }
+                    if ($value < -1 || $value > 30) {
+                        throw new CurrencyException(__(
+                            '"%1" precision has to be between -1 and 30.',
+                            $value
+                        ));
+                    }
+                    break;
+            }
+        }
+
+        return $options;
+    }
+}
diff --git a/vendor/magento/framework/Currency/Exception/CurrencyException.php b/vendor/magento/framework/Currency/Exception/CurrencyException.php
new file mode 100644
index 00000000000..9091f44d186
--- /dev/null
+++ b/vendor/magento/framework/Currency/Exception/CurrencyException.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+declare(strict_types=1);
+
+namespace Magento\Framework\Currency\Exception;
+
+use Magento\Framework\Exception\LocalizedException;
+
+class CurrencyException extends LocalizedException
+{
+}
diff --git a/vendor/magento/framework/Currency/README.md b/vendor/magento/framework/Currency/README.md
new file mode 100644
index 00000000000..bd0a9cbf70f
--- /dev/null
+++ b/vendor/magento/framework/Currency/README.md
@@ -0,0 +1,3 @@
+# Currency
+
+**Currency** library provides needed data and features to work with currencies.
diff --git a/vendor/magento/framework/CurrencyInterface.php b/vendor/magento/framework/CurrencyInterface.php
index 8ddaae5459c..444438a2ba9 100644
--- a/vendor/magento/framework/CurrencyInterface.php
+++ b/vendor/magento/framework/CurrencyInterface.php
@@ -5,6 +5,9 @@
  */
 namespace Magento\Framework;
 
+use Magento\Framework\Currency\Exception\CurrencyException;
+use Zend_Cache_Core;
+
 /**
  * @api
  * @since 100.0.2
@@ -14,29 +17,30 @@ interface CurrencyInterface
     /**
      * Returns a localized currency string
      *
-     * @param  integer|float $value   OPTIONAL Currency value
-     * @param  array         $options OPTIONAL options to set temporary
-     * @throws \Zend_Currency_Exception When the value is not a number
+     * @param  int|float $value OPTIONAL Currency value
+     * @param  array $options OPTIONAL options to set temporary
+     * @throws CurrencyException When the value is not a number
      * @return string
      */
     public function toCurrency($value = null, array $options = []);
 
     /**
-     * Sets the formating options of the localized currency string
+     * Set the formatting options.
+     *
+     * Sets the formatting options of the localized currency string
      * If no parameter is passed, the standard setting of the
      * actual set locale will be used
      *
      * @param  array $options (Optional) Options to set
-     * @return \Magento\Framework\CurrencyInterface
+     * @return CurrencyInterface
      */
     public function setFormat(array $options = []);
 
     /**
-     * Returns the actual or details of other currency symbols,
-     * when no symbol is available it returns the currency shortname (f.e. FIM for Finnian Mark)
+     * Returns the actual or details of other currency symbols, when no symbol is available it returns the shortname.
      *
-     * @param  string             $currency (Optional) Currency name
-     * @param  string $locale   (Optional) Locale to display informations
+     * @param  string $currency OPTIONAL Currency name
+     * @param  string $locale OPTIONAL Locale to display informations
      * @return string
      */
     public function getSymbol($currency = null, $locale = null);
@@ -44,8 +48,8 @@ interface CurrencyInterface
     /**
      * Returns the actual or details of other currency shortnames
      *
-     * @param  string             $currency OPTIONAL Currency's name
-     * @param  string $locale   OPTIONAL The locale
+     * @param  string $currency OPTIONAL Currency's name
+     * @param  string $locale OPTIONAL The locale
      * @return string
      */
     public function getShortName($currency = null, $locale = null);
@@ -53,8 +57,8 @@ interface CurrencyInterface
     /**
      * Returns the actual or details of other currency names
      *
-     * @param  string             $currency (Optional) Currency's short name
-     * @param  string $locale   (Optional) The locale
+     * @param  string $currency OPTIONAL Currency's short name
+     * @param  string $locale OPTIONAL The locale
      * @return string
      */
     public function getName($currency = null, $locale = null);
@@ -63,12 +67,14 @@ interface CurrencyInterface
      * Returns a list of regions where this currency is or was known
      *
      * @param  string $currency OPTIONAL Currency's short name
-     * @throws \Zend_Currency_Exception When no currency was defined
+     * @throws CurrencyException When no currency was defined
      * @return array List of regions
      */
     public function getRegionList($currency = null);
 
     /**
+     * Return currency list.
+     *
      * Returns a list of currencies which are used in this region
      * a region name should be 2 charachters only (f.e. EG, DE, US)
      * If no region is given, the actual region is used
@@ -88,17 +94,17 @@ interface CurrencyInterface
     /**
      * Returns the set cache
      *
-     * @return \Zend_Cache_Core The set cache
+     * @return Zend_Cache_Core The set cache
      */
     public static function getCache();
 
     /**
      * Sets a cache for \Magento\Framework\Currency
      *
-     * @param  \Zend_Cache_Core $cache Cache to set
+     * @param  Zend_Cache_Core $cache Cache to set
      * @return void
      */
-    public static function setCache(\Zend_Cache_Core $cache);
+    public static function setCache(Zend_Cache_Core $cache);
 
     /**
      * Returns true when a cache is set
@@ -127,8 +133,8 @@ interface CurrencyInterface
      * Example: 'de_XX' will be set to 'de' because 'de_XX' does not exist
      * 'xx_YY' will be set to 'root' because 'xx' does not exist
      *
-     * @param  string $locale (Optional) Locale for parsing input
-     * @throws \Zend_Currency_Exception When the given locale does not exist
+     * @param  string $locale OPTIONAL Locale for parsing input
+     * @throws CurrencyException When the given locale does not exist
      * @return $this
      */
     public function setLocale($locale = null);
@@ -150,90 +156,110 @@ interface CurrencyInterface
     /**
      * Adds a currency
      *
-     * @param float|integer|\Magento\Framework\CurrencyInterface $value    Add this value to currency
-     * @param string|\Magento\Framework\CurrencyInterface        $currency The currency to add
-     * @return \Magento\Framework\CurrencyInterface
+     * @param float|int|CurrencyInterface $value Add this value to currency
+     * @param string|CurrencyInterface $currency The currency to add
+     * @return CurrencyInterface
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
      */
     public function setValue($value, $currency = null);
 
     /**
      * Adds a currency
      *
-     * @param float|integer|\Magento\Framework\CurrencyInterface $value    Add this value to currency
-     * @param string|\Magento\Framework\CurrencyInterface        $currency The currency to add
-     * @return \Magento\Framework\CurrencyInterface
+     * @param float|int|CurrencyInterface $value Add this value to currency
+     * @param string|CurrencyInterface $currency The currency to add
+     * @return CurrencyInterface
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
      */
     public function add($value, $currency = null);
 
     /**
      * Substracts a currency
      *
-     * @param float|integer|\Magento\Framework\CurrencyInterface $value    Substracts this value from currency
-     * @param string|\Magento\Framework\CurrencyInterface        $currency The currency to substract
-     * @return \Magento\Framework\CurrencyInterface
+     * @param float|int|CurrencyInterface $value Substracts this value from currency
+     * @param string|CurrencyInterface $currency The currency to substract
+     * @return CurrencyInterface
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
      */
     public function sub($value, $currency = null);
 
     /**
      * Divides a currency
      *
-     * @param float|integer|\Magento\Framework\CurrencyInterface $value    Divides this value from currency
-     * @param string|\Magento\Framework\CurrencyInterface        $currency The currency to divide
-     * @return \Magento\Framework\CurrencyInterface
+     * @param float|int|CurrencyInterface $value Divides this value from currency
+     * @param string|CurrencyInterface $currency The currency to divide
+     * @return CurrencyInterface
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
      */
     public function div($value, $currency = null);
 
     /**
      * Multiplies a currency
      *
-     * @param float|integer|\Magento\Framework\CurrencyInterface $value    Multiplies this value from currency
-     * @param string|\Magento\Framework\CurrencyInterface        $currency The currency to multiply
-     * @return \Magento\Framework\CurrencyInterface
+     * @param float|int|CurrencyInterface $value Multiplies this value from currency
+     * @param string|CurrencyInterface $currency The currency to multiply
+     * @return CurrencyInterface
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
      */
     public function mul($value, $currency = null);
 
     /**
      * Calculates the modulo from a currency
      *
-     * @param float|integer|\Magento\Framework\CurrencyInterface $value    Calculate modulo from this value
-     * @param string|\Magento\Framework\CurrencyInterface        $currency The currency to calculate the modulo
-     * @return \Magento\Framework\CurrencyInterface
+     * @param float|int|CurrencyInterface $value Calculate modulo from this value
+     * @param string|CurrencyInterface $currency The currency to calculate the modulo
+     * @return CurrencyInterface
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
      */
     public function mod($value, $currency = null);
 
     /**
      * Compares two currencies
      *
-     * @param float|integer|\Magento\Framework\CurrencyInterface $value    Compares the currency with this value
-     * @param string|\Magento\Framework\CurrencyInterface        $currency The currency to compare this value from
-     * @return \Magento\Framework\CurrencyInterface
+     * @param float|int|CurrencyInterface $value Compares the currency with this value
+     * @param string|CurrencyInterface $currency The currency to compare this value from
+     * @return CurrencyInterface
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
      */
     public function compare($value, $currency = null);
 
     /**
      * Returns true when the two currencies are equal
      *
-     * @param float|integer|\Magento\Framework\CurrencyInterface $value    Compares the currency with this value
-     * @param string|\Magento\Framework\CurrencyInterface        $currency The currency to compare this value from
+     * @param float|int|CurrencyInterface $value Compares the currency with this value
+     * @param string|CurrencyInterface $currency The currency to compare this value from
      * @return boolean
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
      */
     public function equals($value, $currency = null);
 
     /**
      * Returns true when the currency is more than the given value
      *
-     * @param float|integer|\Magento\Framework\CurrencyInterface $value    Compares the currency with this value
-     * @param string|\Magento\Framework\CurrencyInterface        $currency The currency to compare this value from
+     * @param float|int|CurrencyInterface $value Compares the currency with this value
+     * @param string|CurrencyInterface $currency The currency to compare this value from
      * @return boolean
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
      */
     public function isMore($value, $currency = null);
 
     /**
      * Returns true when the currency is less than the given value
      *
-     * @param float|integer|\Magento\Framework\CurrencyInterface $value    Compares the currency with this value
-     * @param string|\Magento\Framework\CurrencyInterface        $currency The currency to compare this value from
+     * @param float|int|CurrencyInterface $value Compares the currency with this value
+     * @param string|CurrencyInterface $currency The currency to compare this value from
      * @return boolean
+     * @deprecated This approach works incorrect, because Zend_Service no longer exists.
+     * @see no alternatives
      */
     public function isLess($value, $currency = null);
 }
