-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Translator] Why does the currency depend on the locale? #32652
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
The message depends on the locale, in this case the currency format is inherited as such. AFAIK we don't support custom formats (yet). For now you could format the currency first using |
This behavior comes from the ICU behavior. Symfony is not the one implementing that formatting. Pre-formatting the value (and then treating it as a text placeholder in the message) is indeed an option. |
@ro0NL @stof thank you for the explanation. Would you accept a PR on Symfony docs for https://github.com/formatjs/formatjs/tree/master/packages/intl-messageformat#user-defined-formats to explain this and how to handle my use case? |
i think ulitmately we're blocked by PHP which is parsing the messages (https://php.net/messageformatter), and doenst accept custom formats. Not sure it's easy to implement such a feature on top. |
Thank you for this issue. |
Could I get an answer? If I do not hear anything I will assume this issue is resolved or abandoned. Please get back to me <3 |
@ro0NL @stof I'm working again with intl and came across this issue again. I'm thinking about decorating/modifying The tight timezone and currency would come from new methods Placeholders seem to be easily identified with regex. I'm also thinking about supporting https://moneyphp.org/en/stable/ as values for placeholders.
Thank you for your help, have a nice weekend |
actually the spec recommends to format params separately: https://unicode-org.github.io/icu/userguide/format_parse/messages/#format-the-parameters-separately-recommended im not sure we shoud start exending it :) From a i18n POV having different category locales globally feels odd, if not invalid sort of. Note there should be many general purpose formats available upstream: https://unicode-org.github.io/icu/userguide/format_parse/numbers/skeletons.html#examples |
I think why ICU reccomends separate formatting at the user level, is so we dont have to couple an implementation to a global currency locale nor specific parameter types. You can provide these values from the outside to any MessageFormat implementation (let this one be in PHP core). Im generally curious about the use case for having a different currency locale globally, i tend to believe it breaks i18n given this context derives from a single current interface locale. If anything, what we're trying to solve here should be solved upstream IMHO. |
@ro0NL First of all, thank you for your time on this matter 👍 I believe the Translation component within the Symfony framework does an amazing job at:
This PHP class is a basic way to translate messages and use default settings for currency, timezone, ... which works fine for a lot of simple use-cases. If one has advanced needs, then the spec recommends to:
As the Translation component is basically an easy-to-use wrapper around https://www.php.net/manual/en/class.messageformatter.php, then this component only works for the same simple use-cases. This is also amazing as it makes it very easy to translate messages. Skeleton like I think we both agree on this ☝️ These simple use-cases work with simple scalars as parameters. These scalars don't store any localization data. So PHP uses default settings:
However, advanced objects exist that store localized data like:
My goal is to make the Translation component even more powerful with support for these objects as parameters and leveraging the localization data they store. ( # Translation file app+intl-icu.en_US.yml
payment: "{date, date, short} at {date, time, short} - {value, number, currency}"
payment2: "{date} at {time} - {value}"
# Translation file app+intl-icu.fr_FR.yml
payment: "{date, date, short} at {date, time, short} - {value, number, currency}"
payment2: "{date} at {time} - {value}" Usage as per today // In order not to give the locale at every call of the translator
$this->translator->setLocale($userLocale);
// BASIC USAGE
// en_US: 1/25/19 at 7:30 PM - $100.00
// fr_FR: 25/01/2019 à 19:30 - 100,00 €
$this->translator->trans('payment', [
'date' => new \DateTime('2019-01-25 11:30:00', 'America/Los_Angeles'),
'value' => 100
]);
// en_US: 1/25/19 at 10:30 AM - $100.00
// fr_FR: 25/01/2019 à 10:30 - 100,00 €
$this->translator->trans('payment', [
'date' => new \DateTime('2019-01-25 11:30:00', 'Europe/Paris'),
'value' => 100
]);
// ADVANCED USAGE
// en_US: 1/25/19 at 11:30 AM - $100.00
// fr_FR: 25/01/2019 à 11:30 - 100,00 $
$userCurrency = 'USD';
$datetime = new \DateTime('2019-01-25 11:30:00', 'Europe/Paris');
$dateFormatter = new IntlDateFormatter($this->translator->getLocale(), IntlDateFormatter::SHORT, IntlDateFormatter::NONE, $datetime->getTimezone());
$timeFormatter = new IntlDateFormatter($this->translator->getLocale(), IntlDateFormatter::NONE, IntlDateFormatter::SHORT, $datetime->getTimezone());
$numberFormatter = new NumberFormatter($this->translator->getLocale(), NumberFormatter::CURRENCY);
$this->translator->trans('payment2', [
'date' => $dateFormatter->format($datetime),
'time' => $timeFormatter->format($datetime),
'value' => $numberFormatter->formatCurrency(100, $userCurrency)
]); What I find wrong with ☝️
=> I believe the Translation component should handle these advanced use-cases to make dev life even easier! MUST HAVE
NICE TO HAVE Why these 4 changes?
Proposed usages $this->translator->setLocale($userLocale);
// en_US: 1/25/19 at 11:30 AM - $100.00
// fr_FR: 25/01/2019 à 11:30 - 100,00 €
$this->translator->trans('payment', [
'date' => new \DateTime('2019-01-25 11:30:00'),
'value' => 100
]);
// en_US: 1/25/19 at 11:30 AM - $100.00
// fr_FR: 25/01/2019 à 11:30 - 100,00 €
$this->translator->trans('payment', [
'date' => new \DateTime('2019-01-25 11:30:00', 'Europe/Paris'),
'value' => 100
]);
// en_US: 1/25/19 at 11:30 AM - €100.00
// fr_FR: 25/01/2019 à 11:30 - 100,00 €
$this->translator->trans('payment', [
'date' => new \DateTime('2019-01-25 11:30:00', 'Europe/Paris'),
'value' => Money::EUR(100)
]);
$this->translator->setTimezone('America/Los_Angeles');
$this->translator->setCurrency('USD');
// en_US: 1/25/19 at 3:30 AM - $100.00
// fr_FR: 25/01/2019 à 03:30 - 100,00 $
$this->translator->trans('payment', [
'date' => new \DateTime('2019-01-25 11:30:00'),
'value' => 100
]);
// en_US: 1/25/19 at 11:30 AM - €100.00
// fr_FR: 25/01/2019 à 11:30 - 100,00 €
$this->translator->trans('payment', [
'date' => new \DateTime('2019-01-25 11:30:00', 'Europe/Paris'),
'value' => Money::EUR(100)
]); |
we are still coupling an implementation to specific parameter types. It breaks compatibility. If we reuse the same message eg. client-side we may need a translator supporting the same feature set, which is far from ideal IMHO. Other translators cannot opt-in, and our translator also cannot opt-out from handling such parameter types. To me it sounds like a dead-end, if not a rabbit hole. I think we should focus on providing the parameter values from outside more easy, eg. twig-like
In PHP perhaps:
i really dont think this makes sense from i18n POV. We cannot know all messages need this context. |
i tend to agree PHP translators can support eg.
|
@ro0NL Thank you for all your inputs. I'll work on it with my team and come back with a PR or something! |
Hello @ro0NL I have several questions about it:
Have a nice evening |
Thank you for this issue. |
#41136 should fix it |
Thank you for this issue. |
Could I get a reply or should I close this? |
Hey, I didn't hear anything so I'm going to close it. Feel free to comment if this is still relevant, I can always reopen! |
Uh oh!
There was an error while loading. Please reload this page.
Symfony version(s) affected: 4.3
Description
According to https://symfony.com/doc/current/translation/message_format.html#numbers the translator uses the locale to select the currency:
IMO, the currency does not depend on the locale: I may want to display euros in English and US dollars in French.
What is the expected way to display this sentence using the translator?
A possible workaround would be to define custom formats like with this JS lib:
https://github.com/formatjs/formatjs/tree/master/packages/intl-messageformat#user-defined-formats
The text was updated successfully, but these errors were encountered: