diff --git a/core/lib/Drupal/Core/Entity/EntityType.php b/core/lib/Drupal/Core/Entity/EntityType.php index 8728fb949d9e8d86d0b24e2ba2b61f09599db7b1..9f2587e69db7fdab6c335ef2c554c1bbc5bc9027 100644 --- a/core/lib/Drupal/Core/Entity/EntityType.php +++ b/core/lib/Drupal/Core/Entity/EntityType.php @@ -175,6 +175,13 @@ class EntityType extends PluginDefinition implements EntityTypeInterface { */ protected $label = ''; + /** + * The human-readable label for a collection of entities of the type. + * + * @var string + */ + protected $label_collection = ''; + /** * The indefinite singular name of the type. * @@ -726,6 +733,17 @@ public function getLowercaseLabel() { return Unicode::strtolower($this->getLabel()); } + /** + * {@inheritdoc} + */ + public function getCollectionLabel() { + if (empty($this->label_collection)) { + $label = $this->getLabel(); + $this->label_collection = new TranslatableMarkup('@label entities', ['@label' => $label], [], $this->getStringTranslation()); + } + return $this->label_collection; + } + /** * {@inheritdoc} */ diff --git a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php index e27aeec49354daf40557a453ae128c6315b2cea5..eb5295fee0b7c1e88715dd870ce34a60255af828 100644 --- a/core/lib/Drupal/Core/Entity/EntityTypeInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityTypeInterface.php @@ -634,6 +634,14 @@ public function getLabel(); */ public function getLowercaseLabel(); + /** + * Gets the collection label of the entity type. + * + * @return string + * The collection label. + */ + public function getCollectionLabel(); + /** * Gets the singular label of the entity type. * diff --git a/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php index fd23018be0c3159d9e908ecfebfa837115ec1fcc..695dd7d1da6d555ccb36ebab117910091fc01167 100644 --- a/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php @@ -316,13 +316,16 @@ protected function getCollectionRoute(EntityTypeInterface $entity_type) { // If the entity type does not provide an admin permission, there is no way // to control access, so we cannot provide a route in a sensible way. if ($entity_type->hasLinkTemplate('collection') && $entity_type->hasListBuilderClass() && ($admin_permission = $entity_type->getAdminPermission())) { + /** @var \Drupal\Core\StringTranslation\TranslatableMarkup $label */ + $label = $entity_type->getCollectionLabel(); + $route = new Route($entity_type->getLinkTemplate('collection')); $route ->addDefaults([ '_entity_list' => $entity_type->id(), - // @todo Improve this in https://www.drupal.org/node/2767025 - '_title' => '@label entities', - '_title_arguments' => ['@label' => $entity_type->getLabel()], + '_title' => $label->getUntranslatedString(), + '_title_arguments' => $label->getArguments(), + '_title_context' => $label->getOption('context'), ]) ->setRequirement('_permission', $admin_permission); diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php index 68afc8360bcdf30f466de8657b712481e779397e..bb0e36a664e3a2e90125d66ae688e4c968291f3d 100644 --- a/core/modules/node/src/Entity/Node.php +++ b/core/modules/node/src/Entity/Node.php @@ -18,6 +18,7 @@ * @ContentEntityType( * id = "node", * label = @Translation("Content"), + * label_collection = @Translation("Content"), * label_singular = @Translation("content item"), * label_plural = @Translation("content items"), * label_count = @PluralTranslation( diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php index d633afc95fb9367bf338995e9226c41b43283ada..06cf5e11dc14ae63c281c2b726cda14ae732f001 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityTypeTest.php @@ -318,6 +318,16 @@ public function testGetGroupLabel() { $this->assertSame($default_label, $entity_type->getGroupLabel()); } + /** + * @covers ::getCollectionLabel + */ + public function testGetCollectionLabel() { + $translatable_label = new TranslatableMarkup('Entity test collection', [], [], $this->getStringTranslationStub()); + $entity_type = $this->setUpEntityType(['label_collection' => $translatable_label]); + $entity_type->setStringTranslation($this->getStringTranslationStub()); + $this->assertEquals('Entity test collection', $entity_type->getCollectionLabel()); + } + /** * @covers ::getSingularLabel */ diff --git a/core/tests/Drupal/Tests/Core/Entity/Routing/DefaultHtmlRouteProviderTest.php b/core/tests/Drupal/Tests/Core/Entity/Routing/DefaultHtmlRouteProviderTest.php index 170d0c1a65f0585eab07597d04e0aaf321bc1924..7e853bca2bd9af65b87d734c4f0b0df06e7291fb 100644 --- a/core/tests/Drupal/Tests/Core/Entity/Routing/DefaultHtmlRouteProviderTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/Routing/DefaultHtmlRouteProviderTest.php @@ -14,6 +14,7 @@ use Drupal\Core\Entity\FieldableEntityInterface; use Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider; use Drupal\Core\Field\FieldStorageDefinitionInterface; +use Drupal\Core\StringTranslation\TranslatableMarkup; use Drupal\Tests\UnitTestCase; use Prophecy\Argument; use Prophecy\Prophecy\ObjectProphecy; @@ -282,13 +283,15 @@ public function providerTestGetCollectionRoute() { $entity_type4->getAdminPermission()->willReturn('administer the entity type'); $entity_type4->id()->willReturn('the_entity_type_id'); $entity_type4->getLabel()->willReturn('The entity type'); + $entity_type4->getCollectionLabel()->willReturn(new TranslatableMarkup('Test entities')); $entity_type4->getLinkTemplate('collection')->willReturn('/the/collection/link/template'); $entity_type4->entityClassImplements(FieldableEntityInterface::class)->willReturn(FALSE); $route = (new Route('/the/collection/link/template')) ->setDefaults([ '_entity_list' => 'the_entity_type_id', - '_title' => '@label entities', - '_title_arguments' => ['@label' => 'The entity type'], + '_title' => 'Test entities', + '_title_arguments' => [], + '_title_context' => '', ]) ->setRequirements([ '_permission' => 'administer the entity type',