Issue #2114069 by dawehner, Gábor Hojtsy, ursula: Fixed Routing / tabs / actions lack way to attach context to UI strings.
parent
4361e6795b
commit
b376379368
|
@ -57,8 +57,12 @@ class TitleResolver implements TitleResolverInterface {
|
|||
$route_title = call_user_func_array($callable, $arguments);
|
||||
}
|
||||
elseif ($title = $route->getDefault('_title')) {
|
||||
$options = array();
|
||||
if ($context = $route->getDefault('_title_context')) {
|
||||
$options['context'] = $context;
|
||||
}
|
||||
// Fall back to a static string from the route.
|
||||
$route_title = $this->translationManager->translate($title);
|
||||
$route_title = $this->translationManager->translate($title, array(), $options);
|
||||
}
|
||||
return $route_title;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,11 @@ use Drupal\Core\ContentNegotiation;
|
|||
*/
|
||||
class ViewSubscriber implements EventSubscriberInterface {
|
||||
|
||||
/**
|
||||
* The content negotiation.
|
||||
*
|
||||
* @var \Drupal\Core\ContentNegotiation
|
||||
*/
|
||||
protected $negotiation;
|
||||
|
||||
/**
|
||||
|
@ -91,8 +96,8 @@ class ViewSubscriber implements EventSubscriberInterface {
|
|||
}
|
||||
|
||||
// If no title was returned fall back to one defined in the route.
|
||||
if (!isset($page_result['#title']) && $request->attributes->has('_title')) {
|
||||
$page_result['#title'] = $request->attributes->get('_title');
|
||||
if (!isset($page_result['#title'])) {
|
||||
$page_result['#title'] = $this->titleResolver->getTitle($request, $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT));
|
||||
}
|
||||
|
||||
$event->setResponse(new Response(drupal_render_page($page_result)));
|
||||
|
@ -109,8 +114,8 @@ class ViewSubscriber implements EventSubscriberInterface {
|
|||
}
|
||||
|
||||
// If no title was returned fall back to one defined in the route.
|
||||
if (!isset($page_result['#title']) && $request->attributes->has('_title')) {
|
||||
$page_result['#title'] = $request->attributes->get('_title');
|
||||
if (!isset($page_result['#title'])) {
|
||||
$page_result['#title'] = $this->titleResolver->getTitle($request, $request->attributes->get(RouteObjectInterface::ROUTE_OBJECT));
|
||||
}
|
||||
|
||||
$event->setResponse(new Response(drupal_render($page_result)));
|
||||
|
|
|
@ -67,7 +67,11 @@ class LocalActionDefault extends PluginBase implements LocalActionInterface, Con
|
|||
*/
|
||||
public function getTitle() {
|
||||
// Subclasses may pull in the request or specific attributes as parameters.
|
||||
return $this->t($this->pluginDefinition['title']);
|
||||
$options = array();
|
||||
if (!empty($this->pluginDefinition['title_context'])) {
|
||||
$options['context'] = $this->pluginDefinition['title_context'];
|
||||
}
|
||||
return $this->t($this->pluginDefinition['title'], array(), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -75,7 +75,11 @@ class LocalTaskDefault extends PluginBase implements LocalTaskInterface {
|
|||
*/
|
||||
public function getTitle() {
|
||||
// Subclasses may pull in the request or specific attributes as parameters.
|
||||
return $this->t($this->pluginDefinition['title']);
|
||||
$options = array();
|
||||
if (!empty($this->pluginDefinition['title_context'])) {
|
||||
$options['context'] = $this->pluginDefinition['title_context'];
|
||||
}
|
||||
return $this->t($this->pluginDefinition['title'], array(), $options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -115,6 +115,9 @@ class CommentFormController extends ContentEntityFormController {
|
|||
'%title' => $comment->subject->value,
|
||||
));
|
||||
}
|
||||
else {
|
||||
$form['#title'] = $this->t('Preview comment');
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($this->currentUser->isAuthenticated()) {
|
||||
|
|
|
@ -239,6 +239,8 @@ system.date_format_localize_reset:
|
|||
system.modules_list:
|
||||
path: '/admin/modules'
|
||||
defaults:
|
||||
_title: 'Extend'
|
||||
_title_context: 'With components'
|
||||
_form: 'Drupal\system\Form\ModulesListForm'
|
||||
requirements:
|
||||
_permission: 'administer modules'
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Controller\TitleResolverTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Controller;
|
||||
|
||||
use Drupal\Component\Utility\String;
|
||||
use Drupal\Core\Controller\TitleResolver;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* Tests the title resolver.
|
||||
*
|
||||
* @see \Drupal\Core\Controller\TitleResolver
|
||||
*/
|
||||
class TitleResolverTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The mocked controller resolver.
|
||||
*
|
||||
* @var \Drupal\Core\Controller\ControllerResolverInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $controllerResolver;
|
||||
|
||||
/**
|
||||
* The mocked translation manager.
|
||||
*
|
||||
* @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $translationManager;
|
||||
|
||||
/**
|
||||
* The actual tested title resolver.
|
||||
*
|
||||
* @var \Drupal\Core\Controller\TitleResolver
|
||||
*/
|
||||
protected $titleResolver;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Title resolver',
|
||||
'description' => 'Tests the title resolver.',
|
||||
'group' => 'Routing',
|
||||
);
|
||||
}
|
||||
|
||||
protected function setUp() {
|
||||
$this->controllerResolver = $this->getMock('\Drupal\Core\Controller\ControllerResolverInterface');
|
||||
$this->translationManager = $this->getMock('\Drupal\Core\StringTranslation\TranslationInterface');
|
||||
|
||||
$this->titleResolver = new TitleResolver($this->controllerResolver, $this->translationManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a static title without a context.
|
||||
*
|
||||
* @see \Drupal\Core\Controller\TitleResolver::getTitle()
|
||||
*/
|
||||
public function testStaticTitle() {
|
||||
$request = new Request();
|
||||
$route = new Route('/test-route', array('_title' => 'static title'));
|
||||
|
||||
$this->translationManager->expects($this->once())
|
||||
->method('translate')
|
||||
->with('static title', array(), array())
|
||||
->will($this->returnValue('translated title'));
|
||||
|
||||
$this->assertEquals('translated title', $this->titleResolver->getTitle($request, $route));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a static title with a context.
|
||||
*
|
||||
* @see \Drupal\Core\Controller\TitleResolver::getTitle()
|
||||
*/
|
||||
public function testStaticTitleWithContext() {
|
||||
$request = new Request();
|
||||
$route = new Route('/test-route', array('_title' => 'static title', '_title_context' => 'context'));
|
||||
|
||||
$this->translationManager->expects($this->once())
|
||||
->method('translate')
|
||||
->with('static title', array(), array('context' => 'context'))
|
||||
->will($this->returnValue('translated title with context'));
|
||||
|
||||
$this->assertEquals('translated title with context', $this->titleResolver->getTitle($request, $route));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests a dynamic title.
|
||||
*
|
||||
* @see \Drupal\Core\Controller\TitleResolver::getTitle()
|
||||
*/
|
||||
public function testDynamicTitle() {
|
||||
$request = new Request();
|
||||
$route = new Route('/test-route', array('_title' => 'static title', '_title_callback' => 'Drupal\Tests\Core\Controller\TitleCallback::example'));
|
||||
|
||||
$callable = array(new TitleCallback(), 'example');
|
||||
$this->controllerResolver->expects($this->once())
|
||||
->method('getControllerFromDefinition')
|
||||
->with('Drupal\Tests\Core\Controller\TitleCallback::example')
|
||||
->will($this->returnValue($callable));
|
||||
$this->controllerResolver->expects($this->once())
|
||||
->method('getArguments')
|
||||
->with($request, $callable)
|
||||
->will($this->returnValue(array('example')));
|
||||
|
||||
$this->assertEquals('test example', $this->titleResolver->getTitle($request, $route));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides an example title callback for the testDynamicTitle method above.
|
||||
*/
|
||||
class TitleCallback {
|
||||
|
||||
/**
|
||||
* Gets the example string.
|
||||
*
|
||||
* @param string $value
|
||||
* The dynamic value.
|
||||
*
|
||||
* @return string
|
||||
* Returns the example string.
|
||||
*/
|
||||
public function example($value) {
|
||||
return String::format('test @value', array('@value' => $value));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Menu\LocalActionDefaultTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Menu;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\Menu\LocalActionDefault;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
|
||||
/**
|
||||
* Tests the local action default class.
|
||||
*
|
||||
* @see \Drupal\Core\Menu\LocalActionDefault
|
||||
*/
|
||||
class LocalActionDefaultTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The tested local action default plugin.
|
||||
*
|
||||
* @var \Drupal\Core\Menu\LocalActionDefault
|
||||
*/
|
||||
protected $localActionDefault;
|
||||
|
||||
/**
|
||||
* The used plugin configuration.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $config = array();
|
||||
|
||||
/**
|
||||
* The used plugin ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $pluginId = 'local_action_default';
|
||||
|
||||
/**
|
||||
* The used plugin definition.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $pluginDefinition = array(
|
||||
'id' => 'local_action_default',
|
||||
);
|
||||
|
||||
/**
|
||||
* The mocked translator.
|
||||
*
|
||||
* @var \Drupal\Core\StringTranslation\TranslationInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $stringTranslation;
|
||||
|
||||
/**
|
||||
* The mocked route provider.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\RouteProviderInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $routeProvider;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Local actions default plugin.',
|
||||
'description' => 'Tests the local action default class.',
|
||||
'group' => 'Menu',
|
||||
);
|
||||
}
|
||||
|
||||
protected function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$this->stringTranslation = $this->getMock('Drupal\Core\StringTranslation\TranslationInterface');
|
||||
$this->routeProvider = $this->getMock('Drupal\Core\Routing\RouteProviderInterface');
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the local action default.
|
||||
*/
|
||||
protected function setupLocalActionDefault() {
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('string_translation', $this->stringTranslation);
|
||||
\Drupal::setContainer($container);
|
||||
|
||||
$this->localActionDefault = new LocalActionDefault($this->config, $this->pluginId, $this->pluginDefinition, $this->routeProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getTitle method without a translation context.
|
||||
*
|
||||
* @see \Drupal\Core\Menu\LocalTaskDefault::getTitle()
|
||||
*/
|
||||
public function testGetTitle() {
|
||||
$this->pluginDefinition['title'] = 'Example';
|
||||
$this->stringTranslation->expects($this->once())
|
||||
->method('translate')
|
||||
->with($this->pluginDefinition['title'], array(), array())
|
||||
->will($this->returnValue('Example translated'));
|
||||
|
||||
$this->setupLocalActionDefault();
|
||||
$this->assertEquals('Example translated', $this->localActionDefault->getTitle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getTitle method with a translation context.
|
||||
*
|
||||
* @see \Drupal\Core\Menu\LocalTaskDefault::getTitle()
|
||||
*/
|
||||
public function testGetTitleWithContext() {
|
||||
$this->pluginDefinition['title'] = 'Example';
|
||||
$this->pluginDefinition['title_context'] = 'context';
|
||||
$this->stringTranslation->expects($this->once())
|
||||
->method('translate')
|
||||
->with($this->pluginDefinition['title'], array(), array('context' => 'context'))
|
||||
->will($this->returnValue('Example translated with context'));
|
||||
|
||||
$this->setupLocalActionDefault();
|
||||
$this->assertEquals('Example translated with context', $this->localActionDefault->getTitle());
|
||||
}
|
||||
|
||||
}
|
|
@ -253,20 +253,38 @@ class LocalTaskDefaultTest extends UnitTestCase {
|
|||
}
|
||||
|
||||
/**
|
||||
* Tests the getTitle method.
|
||||
* Tests the getTitle method without a translation context.
|
||||
*
|
||||
* @see \Drupal\Core\Menu\LocalTaskDefault::getTitle()
|
||||
*/
|
||||
public function testGetTitle() {
|
||||
$this->pluginDefinition['title'] = 'Example';
|
||||
$this->stringTranslation->expects($this->once())
|
||||
->method('translate', $this->pluginDefinition['title'])
|
||||
->method('translate')
|
||||
->with($this->pluginDefinition['title'], array(), array())
|
||||
->will($this->returnValue('Example translated'));
|
||||
|
||||
$this->setupLocalTaskDefault();
|
||||
$this->assertEquals('Example translated', $this->localTaskBase->getTitle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getTitle method with a translation context.
|
||||
*
|
||||
* @see \Drupal\Core\Menu\LocalTaskDefault::getTitle()
|
||||
*/
|
||||
public function testGetTitleWithContext() {
|
||||
$this->pluginDefinition['title'] = 'Example';
|
||||
$this->pluginDefinition['title_context'] = 'context';
|
||||
$this->stringTranslation->expects($this->once())
|
||||
->method('translate')
|
||||
->with($this->pluginDefinition['title'], array(), array('context' => 'context'))
|
||||
->will($this->returnValue('Example translated with context'));
|
||||
|
||||
$this->setupLocalTaskDefault();
|
||||
$this->assertEquals('Example translated with context', $this->localTaskBase->getTitle());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getOption method.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue