Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 60985be

Browse files
committed
wip
1 parent e34cd7d commit 60985be

File tree

7 files changed

+212
-5
lines changed

7 files changed

+212
-5
lines changed

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
"doctrine/doctrine-bundle": "^2.0",
134134
"guzzlehttp/promises": "^1.4",
135135
"masterminds/html5": "^2.6",
136+
"moneyphp/money": "^3.0|^4.0",
136137
"monolog/monolog": "^1.25.1|^2",
137138
"nyholm/psr7": "^1.0",
138139
"paragonie/sodium_compat": "^1.8",
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Translation\Tests\Translatable;
13+
14+
use Money\Money;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\Component\Translation\Translatable\TranslatableMoney;
17+
use Symfony\Contracts\Translation\TranslatorInterface;
18+
19+
class TranslatableMoneyTest extends TestCase
20+
{
21+
/**
22+
* @dataProvider getTransValues()
23+
*/
24+
public function testTrans(string $expected, TranslatableMoney $translatable, string $locale): void
25+
{
26+
$translator = $this->createMock(TranslatorInterface::class);
27+
28+
$this->assertSame($expected, $translatable->trans($translator, $locale));
29+
}
30+
31+
public function getTransValues(): iterable
32+
{
33+
$translatableEuros = new TranslatableMoney(1000, 'EUR');
34+
$translatableDollars = new TranslatableMoney(1000, 'USD');
35+
36+
yield 'Euros in French' => ['1 000,00 €', $translatableEuros, 'fr_FR'];
37+
yield 'Euros in US English' => ['€ 1,000.00', $translatableEuros, 'en_US'];
38+
yield 'US Dollars in French' => ['1 000,00 $', $translatableDollars, 'fr_FR'];
39+
yield 'US Dollars in US English' => ['$ 1,000.00', $translatableDollars, 'en_US'];
40+
41+
$translatableEuros = TranslatableMoney::fromMoney(Money::EUR(100000));
42+
yield 'Euros in French from Money' => ['1 000,00 €', $translatableEuros, 'fr_FR'];
43+
yield 'Euros in US English from Money' => ['€ 1,000.00', $translatableEuros, 'en_US'];
44+
45+
$translatableDollars = TranslatableMoney::fromMoney(Money::USD(100000));
46+
yield 'US Dollars in French from Money' => ['1 000,00 $', $translatableDollars, 'fr_FR'];
47+
yield 'US Dollars in US English from Money' => ['$ 1,000.00', $translatableDollars, 'en_US'];
48+
}
49+
50+
public function testToString(): void
51+
{
52+
$this->assertSame('€ 100.00', new TranslatableMoney(100, 'EUR'));
53+
}
54+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Translation\Translatable;
13+
14+
use Symfony\Contracts\Translation\TranslatableInterface;
15+
use Symfony\Contracts\Translation\TranslatorInterface;
16+
17+
/**
18+
* Wrapper around PHP IntlDateFormatter for date and time
19+
* The timezone from the DateTime instance is used instead of the server's timezone
20+
*
21+
* @author Sylvain Fabre <[email protected]>
22+
*/
23+
class TranslatableDateTime implements TranslatableInterface
24+
{
25+
private $dateTime;
26+
private $dateType;
27+
private $timeType;
28+
29+
private $formatters = [];
30+
31+
public function __construct(\DateTimeInterface $dateTime, int $dateType, int $timeType)
32+
{
33+
$this->dateTime = $dateTime;
34+
$this->dateType = $dateType;
35+
$this->timeType = $timeType;
36+
}
37+
38+
public function trans(TranslatorInterface $translator, string $locale = null): string
39+
{
40+
$timezone = $this->dateTime->getTimezone();
41+
$key = implode('.', [$locale, $this->dateType, $this->timeType, $timezone->getName()]);
42+
if (!isset($this->formatters[$key])) {
43+
$this->formatters[$key] = new \IntlDateFormatter(
44+
$locale,
45+
$this->dateType,
46+
$this->timeType,
47+
$timezone
48+
);
49+
}
50+
51+
return $this->formatters[$key]->format($this->dateTime);
52+
}
53+
54+
/**
55+
* Short-hand to only format a date
56+
*/
57+
public static function date(\DateTimeInterface $dateTime, int $type = \IntlDateFormatter::SHORT): self
58+
{
59+
return new self($dateTime, $type, \IntlDateFormatter::NONE);
60+
}
61+
62+
/**
63+
* Short-hand to only format a time
64+
*/
65+
public static function time(\DateTimeInterface $dateTime, int $type = \IntlDateFormatter::SHORT): self
66+
{
67+
return new self($dateTime, \IntlDateFormatter::NONE, $type);
68+
}
69+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Translation\Translatable;
13+
14+
use Money\Money;
15+
use Symfony\Contracts\Translation\TranslatableInterface;
16+
use Symfony\Contracts\Translation\TranslatorInterface;
17+
18+
/**
19+
* Wrapper around PHP NumberFormatter for money
20+
* The provided currency is used instead of the locale's currency
21+
*
22+
* @author Sylvain Fabre <[email protected]>
23+
*/
24+
class TranslatableMoney implements TranslatableInterface
25+
{
26+
private $value;
27+
private $currency;
28+
29+
private $formatters = [];
30+
31+
public function __construct($value, string $currency)
32+
{
33+
$this->value = $value;
34+
$this->currency = $currency;
35+
}
36+
37+
public function __toString(): string
38+
{
39+
return $this->format();
40+
}
41+
42+
public function trans(TranslatorInterface $translator, string $locale = null): string
43+
{
44+
return $this->format($locale);
45+
}
46+
47+
private function format(string $locale = null): string
48+
{
49+
if (!isset($this->formatters[$locale])) {
50+
$this->formatters[$locale] = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
51+
}
52+
53+
return $this->formatters[$locale]->formatCurrency($this->value, $this->currency);
54+
}
55+
56+
/**
57+
* Short-hand to instantiate from a Money instance
58+
*/
59+
public static function fromMoney(Money $money): self
60+
{
61+
return new self($money->getAmount(), $money->getCurrency()->getCode());
62+
}
63+
}

src/Symfony/Component/Translation/TranslatableMessage.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
/**
1818
* @author Nate Wiebe <[email protected]>
19+
* TODO: Move this class to the Translatable namespace with a deprecation message?
1920
*/
2021
class TranslatableMessage implements TranslatableInterface
2122
{
@@ -52,6 +53,13 @@ public function getDomain(): ?string
5253

5354
public function trans(TranslatorInterface $translator, string $locale = null): string
5455
{
55-
return $translator->trans($this->getMessage(), $this->getParameters(), $this->getDomain(), $locale);
56+
$parameters = array_map(function($parameter) use($translator, $locale) {
57+
if ($parameter instanceof TranslatableInterface) {
58+
return $parameter->trans($translator, $locale);
59+
}
60+
return $parameter;
61+
}, $this->getParameters());
62+
63+
return $translator->trans($this->getMessage(), $parameters, $this->getDomain(), $locale);
5664
}
5765
}

src/Symfony/Component/Translation/Translator.php

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use Symfony\Component\Translation\Formatter\MessageFormatterInterface;
2323
use Symfony\Component\Translation\Loader\LoaderInterface;
2424
use Symfony\Contracts\Translation\LocaleAwareInterface;
25+
use Symfony\Contracts\Translation\TranslatableInterface;
2526
use Symfony\Contracts\Translation\TranslatorInterface;
2627

2728
// Help opcache.preload discover always-needed symbols
@@ -214,15 +215,24 @@ public function trans(?string $id, array $parameters = [], string $domain = null
214215
}
215216
}
216217

218+
$message = $catalogue->get($id, $domain);
219+
220+
$parameters = array_map(function($parameter) use ($locale) {
221+
if ($parameter instanceof TranslatableInterface) {
222+
return $parameter->trans($this, $locale);
223+
}
224+
return $parameter;
225+
}, $parameters);
226+
217227
$len = \strlen(MessageCatalogue::INTL_DOMAIN_SUFFIX);
218228
if ($this->hasIntlFormatter
219229
&& ($catalogue->defines($id, $domain.MessageCatalogue::INTL_DOMAIN_SUFFIX)
220230
|| (\strlen($domain) > $len && 0 === substr_compare($domain, MessageCatalogue::INTL_DOMAIN_SUFFIX, -$len, $len)))
221231
) {
222-
return $this->formatter->formatIntl($catalogue->get($id, $domain), $locale, $parameters);
232+
return $this->formatter->formatIntl($message, $locale, $parameters);
223233
}
224234

225-
return $this->formatter->format($catalogue->get($id, $domain), $locale, $parameters);
235+
return $this->formatter->format($message, $locale, $parameters);
226236
}
227237

228238
/**

src/Symfony/Component/Translation/composer.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@
3232
"symfony/service-contracts": "^1.1.2|^2",
3333
"symfony/yaml": "^4.4|^5.0",
3434
"symfony/finder": "^4.4|^5.0",
35-
"psr/log": "~1.0"
35+
"psr/log": "~1.0",
36+
"moneyphp/money": "^3.0|^4.0"
3637
},
3738
"conflict": {
3839
"symfony/config": "<4.4",
@@ -47,7 +48,8 @@
4748
"suggest": {
4849
"symfony/config": "",
4950
"symfony/yaml": "",
50-
"psr/log-implementation": "To use logging capability in translator"
51+
"psr/log-implementation": "To use logging capability in translator",
52+
"moneyphp/money": "To use Currency capability in translator"
5153
},
5254
"autoload": {
5355
"files": [ "Resources/functions.php" ],

0 commit comments

Comments
 (0)