Skip to content

Add a MessageFormatter Phrase renderer #22996

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/code/Magento/Translation/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
<arguments>
<argument name="renderers" xsi:type="array">
<item name="translation" xsi:type="object">Magento\Framework\Phrase\Renderer\Translate</item>
<item name="messageFormatter" xsi:type="object">Magento\Framework\Phrase\Renderer\MessageFormatter</item>
<item name="placeholder" xsi:type="object">Magento\Framework\Phrase\Renderer\Placeholder</item>
<item name="inline" xsi:type="object">Magento\Framework\Phrase\Renderer\Inline</item>
</argument>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

declare(strict_types=1);

namespace Magento\Framework\Phrase\Renderer;

use Magento\Framework\Phrase\RendererInterface;
use Magento\Framework\TranslateInterface;

/**
* Process texts to resolve ICU MessageFormat
*/
class MessageFormatter implements RendererInterface
{
/** @var TranslateInterface */
private $translate;

/**
* @param TranslateInterface $translate
*/
public function __construct(TranslateInterface $translate)
{
$this->translate = $translate;
}

/**
* @inheritdoc
*/
public function render(array $source, array $arguments)
{
$text = end($source);

if (strpos($text, '{') === false) {
// About 5x faster for non-MessageFormatted strings
// Only slightly slower for MessageFormatted strings (~0.3x)
return $text;
}

$result = \MessageFormatter::formatMessage($this->translate->getLocale(), $text, $arguments);
return $result !== false ? $result : $text;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

declare(strict_types=1);

namespace Magento\Framework\Phrase\Test\Unit\Renderer;

use Magento\Framework\Phrase\Renderer\MessageFormatter;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use Magento\Framework\Translate;
use PHPUnit\Framework\TestCase;

/**
* Tests that messages sent through the MessageFormatter phrase renderer result in what would be expected when sent
* through PHP's native MessageFormatter, and that the locale is pulled from the Translate dependency
*/
class MessageFormatterTest extends TestCase
{
/** @var ObjectManager */
private $objectManager;

/**
* @inheritdoc
*/
protected function setUp()
{
$this->objectManager = new ObjectManager($this);
}

/**
* Retrieve test cases
*
* @return array [Raw Phrase, Locale, Arguments, Expected Result]
* @throws \Exception
*/
public function renderMessageFormatterDataProvider(): array
{
$twentynineteenJuneTwentyseven = new \DateTime('2019-06-27');

return [
[
'A table has {legs, plural, =0 {no legs} =1 {one leg} other {# legs}}.',
'en_US',
['legs' => 4],
'A table has 4 legs.'
],
[
'A table has {legs, plural, =0 {no legs} =1 {one leg} other {# legs}}.',
'en_US',
['legs' => 0],
'A table has no legs.'
],
[
'A table has {legs, plural, =0 {no legs} =1 {one leg} other {# legs}}.',
'en_US',
['legs' => 1],
'A table has one leg.'
],
['The table costs {price, number, currency}.', 'en_US', ['price' => 23.4], 'The table costs $23.40.'],
[
'Today is {date, date, long}.',
'en_US',
['date' => $twentynineteenJuneTwentyseven],
'Today is June 27, 2019.'
],
[
'Today is {date, date, long}.',
'ja_JP',
['date' => $twentynineteenJuneTwentyseven],
'Today is 2019年6月27日.'
],
];
}

/**
* Test MessageFormatter
*
* @param string $text The text with MessageFormat markers
* @param string $locale
* @param array $arguments The arguments supplying values for the variables
* @param string $result The expected result of Phrase rendering
*
* @dataProvider renderMessageFormatterDataProvider
*/
public function testRenderMessageFormatter(string $text, string $locale, array $arguments, string $result): void
{
$renderer = $this->getMessageFormatter($locale);

$this->assertEquals($result, $renderer->render([$text], $arguments));
}

/**
* Create a MessageFormatter object provided a locale
*
* Automatically sets up the Translate dependency to return the provided locale and returns a MessageFormatter
* that has been provided that dependency
*
* @param string $locale
* @return MessageFormatter
*/
private function getMessageFormatter(string $locale): MessageFormatter
{
$translateMock = $this->getMockBuilder(Translate::class)
->disableOriginalConstructor()
->setMethods(['getLocale'])
->getMock();
$translateMock->method('getLocale')
->willReturn($locale);

return $this->objectManager->getObject(MessageFormatter::class, ['translate' => $translateMock]);
}
}
1 change: 1 addition & 0 deletions lib/internal/Magento/Framework/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"ext-gd": "*",
"ext-hash": "*",
"ext-iconv": "*",
"ext-intl": "*",
"ext-openssl": "*",
"ext-simplexml": "*",
"ext-spl": "*",
Expand Down