Open in-session opened 4 weeks ago
Hi @in-session. Thank you for your report. To speed up processing of this issue, make sure that the issue is reproducible on the vanilla Magento instance following Steps to reproduce. To deploy vanilla Magento instance on our environment, Add a comment to the issue:
@magento give me 2.4-develop instance
- upcoming 2.4.x release@magento I am working on this
Join Magento Community Engineering Slack and ask your questions in #github channel. :warning: According to the Magento Contribution requirements, all issues must go through the Community Contributions Triage process. Community Contributions Triage is a public meeting. :clock10: You can find the schedule on the Magento Community Calendar page. :telephone_receiver: The triage of issues happens in the queue order. If you want to speed up the delivery of your contribution, join the Community Contributions Triage session to discuss the appropriate ticket.
The problem relates to all Symfony\Component\Intl components. if i see it correctly magento tries to use the language iso codes ISO-639-1 with ISO-3166-1. There should be a check which then falls back $isValidLanguage = Languages::exists($languageCode);
to ISO-639-1 if not available.
I think that this issue is due to the problem: https://github.com/magento/magento2/issues/37780
Hi @engcom-Hotel. Thank you for working on this issue. In order to make sure that issue has enough information and ready for development, please read and check the following instruction: :point_down:
Area: XXXXX
label to the ticket, indicating the functional areas it may be related to.2.4-develop
branch@magento give me 2.4-develop instance
to deploy test instance on Magento infrastructure. 2.4-develop
branch, please, add the label Reproduced on 2.4.x
.Issue: Confirmed
once verification is complete. Hello @in-session,
Thanks for the report and collaboration!
We have tried to reproduce the issue in the latest development branch of Magento i.e. 2.4-develop, but it seems the issue is not reproducible for us. We have followed the below steps in order to reproduce the issue:
Locale
to German(Germany)
We are not getting the error mentioned in the main description.
Locale
to German(Germany)
vendor/symfony/intl/Data/Bundle/Reader/PhpBundleReader.php
and lib/internal/Magento/Framework/Currency/Data/Currency.php
while getting the product from the frontendWe are not getting the error mentioned in the main description.
Please let us know if we missed anything for this issue.
Thanks
@engcom-Hotel When I make an error_log here, I always get the value de_DE, but the Currencies::getName and Currencies::getSymbol are 'de' expected. The problem has only arisen through the integration with NewRelic and when, for example, product sliders are stored in their own ESI block. We received 50 GB of Tracelogs within 7 days. You won't be able to replicate this so easily with a dev instance. Can you please categorise this as S1 and open Jira Issus. To reproduce you should set the locale from de_DE and the currencies to EUR.
Perhaps @ihor-sviziev @mrtuvn has an idea for this issus?
Here, however, Symfony\Component\Intl expects 'DE' so that it can load the data from htdocs/vendor/symfony/intl/Resources/data/currencies
https://symfony.com/doc/5.x/components/intl.html#currencies
$currencies = Currencies::getNames('de');
// => ['AFN' => 'Afghanischer Afghani', 'EGP' => 'Ägyptisches Pfund', ...]
$currency = Currencies::getName('EUR', 'de');
// => 'Indische Rupie'
$symbol = Currencies::getSymbol('EUR', 'de');
// => '€'
/**
* @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);
//error_log("setLocale: " . print_r($locale, true));
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;
}
}
}
This returns de_DE which is incorrect.
/**
* 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);
error_log("setLocale: " . print_r($locale, true));
} else {
$symbol = Currencies::getSymbol($params['name'], $params['locale']);
}
return !empty($symbol) ? $symbol : null;
}
As soon as we insert it hard-coded, the problem no longer exists:
/**
* 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'], 'de');
} else {
$symbol = Currencies::getSymbol($params['name'], $params['locale']);
}
return !empty($symbol) ? $symbol : null;
}
Hello @in-session,
Thanks for the reply!
We have more dig into this issue and tried to debug the following method call:
Actually here we are trying to get the Name from the method call Currencies::getName
with param de
and de_DE
. But what we have observed here is, we are getting the same and correct Euro
name in return. Please refer to the below screenshots for reference:
If we pass de
_If we pass de_DE
_
But we have also gone through the Symfony documentation here: https://symfony.com/doc/6.4/components/intl.html#currencies and it requires de
as a second parameter.
But still we are unable to reproduce the issue as mentioned in the main description.
Thanks
@engcom-Hotel
thanks for your check i have looked at everything again and i think this only affects the getSymbol.
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);
// $symbol = Currencies::getSymbol($params['currency'], 'de');
} else {
$symbol = Currencies::getSymbol($params['name'], $params['locale']);
}
return !empty($symbol) ? $symbol : null;
}
But I have found a way to reproduce this:
Firstly, you should change the following value for EUR in Symfony\Component\Intl\Resources\data\currencies\de.php::377
'EUR' => [
'€ New',
'Euro',
],
As a result, you will not yet see any changes in the frontend. If you change the value $symbol = Currencies::getSymbol($params['currency'], $locale);
to $symbol = Currencies::getSymbol($params['currency'], 'de');
Only then will the prices be displayed with '€ New'
This is because there is no de_DE.php in the intl and it uses en.php as a fallback.
This means that all locations always use the default en.php, like:
Therefore it should be checked here whether the locale exists, if not the language code should be manipulated from de_DE to de and als fallback en, as a rough example
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'];
// Check whether the locale code is valid
$isValidLocale = Locales::exists($locale);
if (!$isValidLocale) {
$croppedLocale = substr($params['locale'], (strpos($params['locale'], '_') + 1));
$symbol = Currencies::getSymbol($params['currency'], $croppedLocale);
} else {
$symbol = Currencies::getSymbol($params['currency'], $locale);
}
} else {
$symbol = Currencies::getSymbol($params['name'], $params['locale']);
}
return !empty($symbol) ? $symbol : null;
}
This is also the reason why the value in the Issus is not taken here, the MXN cannot be displayed correctly because de.php is not loaded https://github.com/magento/magento2/issues/37780
Hello @in-session,
Thanks for the reply!
We have debugged the issue and are able to reproduce it, but there is a catch, let me explain here.
Please refer to the below screenshot from method vendor/symfony/intl/Data/Bundle/Reader/BundleEntryReader:readEntry
, when the $locale
is de_DE
:
But after that on line no. 136, the below method has been called:
$currentLocale = Locale::getFallback($currentLocale);
Which then called getFallback method, the documentation of the method is as follows:
Returns the fallback locale for a given locale.
For example, the fallback of "fr_FR" is "fr". The fallback of "fr" is the default fallback locale configured with setDefaultFallback(). The default fallback locale has no fallback.
Returns:
null|string The ICU locale code of the fallback locale, or null if no fallback exists
Now this method will return de
, which is available on the vendor/symfony/intl/Resources/data/currencies/
path, hence it is returning the correct value for us:
It seems to us an expected behaviour, let me know in case we have missed anything.
Thanks
@engcom-Hotel
Thank you for your feedback
This does indeed return the correct value:
// Then determine fallback locale
$currentLocale = Locale::getFallback($currentLocale);
error_log("currentLocale: " . print_r($currentLocale, true));
But if you make this change, it will not be recognised in the frontend. You should change the following value for EUR in Symfony\Component\Intl\Resources\data\currencies\de.php::377
'EUR' => [
'€ New',
'Euro',
],
Which means for me that getFallback might be loaded but the frontend does not take over. With the value "€ New" all article prices should actually appear in the frontend if the fallback should work.
Which symfony/intl version are you using 6.4? Because version 2.4.6-p6 should actually be loaded with version 5
Hello @in-session,
Thanks for the reply!
But if you make this change, it will not be recognised in the frontend. You should change the following value for EUR in Symfony\Component\Intl\Resources\data\currencies\de.php::377
'EUR' => [ '€ New', 'Euro', ],
Which means for me that getFallback might be loaded but the frontend does not take over. With the value "€ New" all article prices should actually appear in the frontend if the fallback should work.
I made the changes you asked for and made the changes in the de.php as below:
'EUR' => [
'€ New',
'Euro',
],
Please refer to the screenshots attached to this https://github.com/magento/magento2/issues/38862#issuecomment-2196389524.
Which symfony/intl version are you using 6.4? Because version 2.4.6-p6 should actually be loaded with version 5
We are using version 6.4.
@engcom-Hotel Can you please try with 5.4.40 because version 2.4.6-p6 should actually be loaded with version 5
Hello @in-session,
Yes, we have tried it on 2.4.6-p6 with symphony/intl version 5.4.40 and it behaves the same as explained here in this https://github.com/magento/magento2/issues/38862#issuecomment-2196389524.
But I think we can confirm this issue, due to the logs you are getting in the NewRelic. We are also getting while debugging this issue.
Please refer to the below screenshot from method
vendor/symfony/intl/Data/Bundle/Reader/BundleEntryReader:readEntry
, when the$locale
isde_DE
:![]()
But after that on line no. 136, the below method has been called:
Hence confirming this issue for further processing.
Thanks
Unfortunately, not enough information was provided to create a Jira ticket. Please make sure you added the following label(s): Reproduced on 2.4.x
, ^Area:.*
Once all required labels are present, please add Issue: Confirmed
label again.
:white_check_mark: Jira issue https://jira.corp.adobe.com/browse/AC-12323 is successfully created for this GitHub issue.
:white_check_mark: Confirmed by @engcom-Hotel. Thank you for verifying the issue.
Issue Available: @engcom-Hotel, You will be automatically unassigned. Contributors/Maintainers can claim this issue to continue. To reclaim and continue work, reassign the ticket to yourself.
Preconditions and environment
Steps to reproduce
Expected result
Actual result
Additional information
If I look at the path, it should actually be htdocs/vendor/symfony/intl/Resources/data/currencies/de.php default language "de_DE" is used but symfony/intl expects "de".
https://github.com/magento/magento2/blob/71370a9ca1a0645bd4913de8f1483e5e9d400820/lib/internal/Magento/Framework/Currency/Data/Currency.php#L270-L285
Release note
No response
Triage and priority