diff --git a/core/lib/Drupal/Core/StringTranslation/TranslationWrapper.php b/core/lib/Drupal/Core/StringTranslation/TranslationWrapper.php index e2c1ecd..8f6236b 100644 --- a/core/lib/Drupal/Core/StringTranslation/TranslationWrapper.php +++ b/core/lib/Drupal/Core/StringTranslation/TranslationWrapper.php @@ -29,6 +29,13 @@ class TranslationWrapper implements SafeStringInterface { protected $string; /** + * The translation arguments. + * + * @var array + */ + protected $arguments = []; + + /** * The translation options. * * @var array @@ -46,7 +53,7 @@ class TranslationWrapper implements SafeStringInterface { * @param array $options * (optional) An array of additional options. */ - public function __construct($string, array $options = array()) { + public function __construct($string, array $options = []) { $this->string = $string; $this->options = $options; } @@ -62,6 +69,16 @@ public function getUntranslatedString() { } /** + * Gets all arguments from this translation wrapper. + * + * @return string[] + * The array of arguments. + */ + public function getArguments() { + return $this->arguments; + } + + /** * Gets a specific option from this translation wrapper. * * @param $name @@ -75,6 +92,16 @@ public function getOption($name) { } /** + * Gets all options from this translation wrapper. + * + * @return array + * The array of options. + */ + public function getOptions() { + return $this->options; + } + + /** * Implements the magic __toString() method. */ public function __toString() { @@ -82,20 +109,37 @@ public function __toString() { } /** + * Creates a new object with updated arguments. + * + * @param string[] $arguments + * An array with placeholder replacements, keyed by placeholder. The values + * will be merged with and replace any existing arguments with the same + * keys. + * + * @return \Drupal\Core\StringTranslation\TranslationWrapper + * The new object. + */ + public function withArguments(array $arguments) { + $with = new static($this->string, $this->options); + $with->arguments = $arguments + $this->arguments; + return $with; + } + + /** * Renders the object as a string. * * @return string * The translated string. */ public function render() { - return $this->t($this->string, [], $this->options); + return $this->t($this->string, $this->arguments, $this->options); } /** * Magic __sleep() method to avoid serializing the string translator. */ public function __sleep() { - return array('string', 'options'); + return array('string', 'arguments', 'options'); } } diff --git a/core/tests/Drupal/Tests/Core/StringTranslation/TranslationWrapperTest.php b/core/tests/Drupal/Tests/Core/StringTranslation/TranslationWrapperTest.php new file mode 100644 index 0000000..4099742 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/StringTranslation/TranslationWrapperTest.php @@ -0,0 +1,91 @@ +assertArrayEquals([], $base->getArguments()); + $wrapper = $base->withArguments(['@ho' => 'ho', '@merry' => 'go']); + $this->assertArrayEquals(['@ho' => 'ho', '@merry' => 'go'], $wrapper->getArguments()); + } + + /** + * @covers ::getOption + */ + public function testGetOption() { + $wrapper = new TranslationWrapper('hey @ho @merry', ['context' => 'interface']); + $this->assertSame('interface', $wrapper->getOption('context')); + } + + /** + * @covers ::getOptions + */ + public function testGetOptions() { + $wrapper = new TranslationWrapper('hey @ho @merry', ['context' => 'interface']); + $this->assertArrayEquals(['context' => 'interface'], $wrapper->getOptions()); + } + + /** + * @covers ::getUntranslatedString + */ + public function testGetUntranslatedString() { + $wrapper = new TranslationWrapper('hey @ho @merry', ['context' => 'interface']); + $this->assertSame('hey @ho @merry', $wrapper->getUntranslatedString()); + } + + /** + * @covers ::withArguments + */ + public function testWithArguments() { + $base = new TranslationWrapper('hey @ho @merry'); + $wrapper = $base->withArguments(['@ho' => 'ho', '@merry' => 'go']); + // Replace no arguments. + $with_args = $wrapper->withArguments([]); + // The method must return a new object. + $this->assertNotEquals(spl_object_hash($wrapper), spl_object_hash($with_args)); + $last_object_hash = spl_object_hash($with_args); + $with_args->setStringTranslation($this->getStringTranslationStub()); + $this->assertSame('hey ho go', (string) $with_args); + // Replace one argument. + $with_args = $wrapper->withArguments(['@ho' => 'llama']); + // The method must return a new object. + $this->assertNotEquals($last_object_hash, spl_object_hash($with_args)); + $this->assertNotEquals(spl_object_hash($wrapper), spl_object_hash($with_args)); + $with_args->setStringTranslation($this->getStringTranslationStub()); + $this->assertSame('hey llama go', (string) $with_args); + $this->assertSame('hey @ho @merry', $with_args->getUntranslatedString()); + // Replace two arguments. + $with_args = $wrapper->withArguments(['@ho' => 'llama', '@merry' => 'new year']); + $with_args->setStringTranslation($this->getStringTranslationStub()); + $this->assertSame('hey llama new year', (string) $with_args); + // Replace an argument that is not used. + $with_args = $wrapper->withArguments(['@horse' => 'llama']); + $with_args->setStringTranslation($this->getStringTranslationStub()); + $this->assertSame('hey ho go', (string) $with_args); + $this->assertArrayEquals(['@ho' => 'ho', '@merry' => 'go', '@horse' => 'llama'], $with_args->getArguments()); + // Start with no arguments in the original. + $wrapper = new TranslationWrapper('hey @ho @merry', []); + // Add one argument. + $with_args = $wrapper->withArguments(['@ho' => 'llama']); + $with_args->setStringTranslation($this->getStringTranslationStub()); + // The missing argument is not replaced. + $this->assertSame('hey llama @merry', (string) $with_args); + } +}