From a96ce1985bfef7bdb5085748876825f639b75f74 Mon Sep 17 00:00:00 2001 From: webchick Date: Wed, 12 Mar 2014 13:05:12 -0700 Subject: [PATCH] Issue #2175821 by Xano, dawehner: Add placeholder support to the @Translation annotation. --- .../Drupal/Core/Annotation/Translation.php | 40 +++++++- .../Tests/Core/Annotation/TranslationTest.php | 97 +++++++++++++++++++ core/tests/Drupal/Tests/UnitTestCase.php | 2 +- 3 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php diff --git a/core/lib/Drupal/Core/Annotation/Translation.php b/core/lib/Drupal/Core/Annotation/Translation.php index ebb26554f3a..57268783069 100644 --- a/core/lib/Drupal/Core/Annotation/Translation.php +++ b/core/lib/Drupal/Core/Annotation/Translation.php @@ -24,6 +24,11 @@ use Drupal\Component\Annotation\AnnotationBase; * Remove spaces after @ in your actual plugin - these are put into this sample * code so that it is not recognized as annotation. * + * To provide replacement values for placeholders, use the "arguments" array: + * @code + * title = @ Translation("Bundle !title", arguments = {"!title" = "Foo"}), + * @endcode + * * It is also possible to provide a context with the text, similar to t(): * @code * title = @ Translation("Bundle", context = "Validation"), @@ -55,20 +60,35 @@ class Translation extends AnnotationBase { protected $translation; /** - * Constructs a Translation object. + * The translation manager. + * + * @var \Drupal\Core\StringTranslation\TranslationInterface + */ + protected $translationManager; + + /** + * Constructs a new class instance. * * Parses values passed into this class through the t() function in Drupal and * handles an optional context for the string. + * + * @param array $values + * Possible array keys: + * - value (required): the string that is to be translated. + * - arguments (optional): an array with placeholder replacements, keyed by + * placeholder. + * - context (optional): a string that describes the context of "value"; */ - public function __construct($values) { + public function __construct(array $values) { $string = $values['value']; + $arguments = isset($values['arguments']) ? $values['arguments'] : array(); $options = array(); if (!empty($values['context'])) { $options = array( 'context' => $values['context'], ); } - $this->translation = t($string, array(), $options); + $this->translation = $this->getTranslationManager()->translate($string, $arguments, $options); } /** @@ -78,4 +98,18 @@ class Translation extends AnnotationBase { return $this->translation; } + /** + * Returns the translation manager. + * + * @return \Drupal\Core\StringTranslation\TranslationInterface + * The translation manager. + */ + protected function getTranslationManager() { + if (!$this->translationManager) { + $this->translationManager = \Drupal::translation(); + } + + return $this->translationManager; + } + } diff --git a/core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php b/core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php new file mode 100644 index 00000000000..258279e53e6 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Annotation/TranslationTest.php @@ -0,0 +1,97 @@ + '', + 'name' => '\Drupal\Core\Annotation\Translation unit test', + 'group' => 'System', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp() { + $this->translationManager = $this->getStringTranslationStub(); + } + + /** + * @covers \Drupal\Core\Annotation\Translation::get() + * + * @dataProvider providerTestGet + */ + public function testGet(array $values, $expected) { + $container = new ContainerBuilder(); + $container->set('string_translation', $this->translationManager); + \Drupal::setContainer($container); + + $arguments = isset($values['arguments']) ? $values['arguments'] : array(); + $options = isset($values['context']) ? array( + 'context' => $values['context'], + ) : array(); + $this->translationManager->expects($this->once()) + ->method('translate') + ->with($values['value'], $arguments, $options); + + $annotation = new Translation($values); + + $this->assertSame($expected, $annotation->get()); + } + + /** + * Provides data to self::testGet(). + */ + public function providerTestGet() { + $data = array(); + $data[] = array( + array( + 'value' => 'Foo', + ), + 'Foo' + ); + $random = $this->randomName(); + $random_html_entity = '&' . $random; + $data[] = array( + array( + 'value' => 'Foo !bar @baz %qux', + 'arguments' => array( + '!bar' => $random, + '@baz' => $random_html_entity, + '%qux' => $random_html_entity, + ), + 'context' => $this->randomName(), + ), + 'Foo ' . $random . ' &' . $random . ' &' . $random . '', + ); + + return $data; + } + +} diff --git a/core/tests/Drupal/Tests/UnitTestCase.php b/core/tests/Drupal/Tests/UnitTestCase.php index b862f12a067..f64dca00b2f 100644 --- a/core/tests/Drupal/Tests/UnitTestCase.php +++ b/core/tests/Drupal/Tests/UnitTestCase.php @@ -190,7 +190,7 @@ abstract class UnitTestCase extends \PHPUnit_Framework_TestCase { $translation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface'); $translation->expects($this->any()) ->method('translate') - ->will($this->returnCallback(function ($string, array $args = array()) { return strtr($string, $args); })); + ->will($this->returnCallback('Drupal\Component\Utility\String::format')); return $translation; }