diff --git a/core/config/schema/core.entity.schema.yml b/core/config/schema/core.entity.schema.yml index 15f92bc85f..85460f9eab 100644 --- a/core/config/schema/core.entity.schema.yml +++ b/core/config/schema/core.entity.schema.yml @@ -373,5 +373,9 @@ bundle_entity_with_plural_labels: type: label label: 'Indefinite plural name' label_count: - type: plural_label - label: 'Count label' + type: sequence + nullable: true + label: 'Count labels' + sequence: + type: plural_label + label: 'Count label' diff --git a/core/lib/Drupal/Core/Config/Entity/EntityBundleWithPluralLabelsInterface.php b/core/lib/Drupal/Core/Config/Entity/EntityBundleWithPluralLabelsInterface.php index a7362d24ac..8eb3bce418 100644 --- a/core/lib/Drupal/Core/Config/Entity/EntityBundleWithPluralLabelsInterface.php +++ b/core/lib/Drupal/Core/Config/Entity/EntityBundleWithPluralLabelsInterface.php @@ -28,10 +28,17 @@ public function getPluralLabel(); * * @param int $count * The item count to display if the plural form was requested. + * @param string $context + * (optional) The optional context of the count label. A bundle entity can + * define unlimited definite singular/plural count labels in order to cover + * various contexts where they are used. Pass the context, as a string + * identifier, to get appropriate version of the count label. Omit the + * context if there's only one version of the definite singular/plural count + * label. Defaults to NULL. * * @return string * The count label. */ - public function getCountLabel($count); + public function getCountLabel($count, $context = NULL); } diff --git a/core/lib/Drupal/Core/Config/Entity/EntityBundleWithPluralLabelsTrait.php b/core/lib/Drupal/Core/Config/Entity/EntityBundleWithPluralLabelsTrait.php index 40d90c1120..aff03d6365 100644 --- a/core/lib/Drupal/Core/Config/Entity/EntityBundleWithPluralLabelsTrait.php +++ b/core/lib/Drupal/Core/Config/Entity/EntityBundleWithPluralLabelsTrait.php @@ -27,11 +27,29 @@ protected $label_plural; /** - * A definite singular/plural count label. + * A list definite singular/plural count label versions. * - * Plural variants are separated by ETX (PluralTranslatableMarkup::DELIMITER). + * Unlimited definite singular/plural count labels can be defined in order to + * cover various contexts where they are used. The array keys are strings, + * identifying the context. For example, a site may need two versions of count + * labels "@count items" and "Items (@count)". In this case the value of this + * property is: + * @code + * [ + * 'default' => '1 item\x03@count items', + * 'with_count_in_parenthesis' => 'Item (1)\x03Items (@count)', + * ] + * @endcode + * If there's only one context, then the key can be omitted: + * @code + * [ + * '1 item\x03@count items', + * ] + * @endcode * in the same way they + * Each value is definite singular/plural count label with the plural variants + * separated by ETX (PluralTranslatableMarkup::DELIMITER). * - * @var string + * @var string[]|null */ protected $label_count; @@ -66,13 +84,19 @@ public function getPluralLabel() { /** * {@inheritdoc} */ - public function getCountLabel($count) { - if (($index = static::getPluralIndex($count)) === -1) { + public function getCountLabel($count, $context = NULL) { + $label_count_versions = (array) $this->label_count; + + // If the context was not passed, pickup the first version of count label. + $context = $context ?: key($label_count_versions); + + $index = static::getPluralIndex($count); + if ($index === -1) { // If the index cannot be computed, fallback to a single plural variant. $index = $count > 1 ? 1 : 0; } - $label_count = empty($this->label_count) ? [] : explode(PluralTranslatableMarkup::DELIMITER, $this->label_count); + $label_count = empty($label_count_versions[$context]) ? [] : explode(PluralTranslatableMarkup::DELIMITER, $label_count_versions[$context]); if (!empty($label_count[$index])) { return new FormattableMarkup($label_count[$index], ['@count' => $count]); } diff --git a/core/modules/book/config/optional/node.type.book.yml b/core/modules/book/config/optional/node.type.book.yml index 4deaa971bd..ada815bb6d 100644 --- a/core/modules/book/config/optional/node.type.book.yml +++ b/core/modules/book/config/optional/node.type.book.yml @@ -13,4 +13,5 @@ preview_mode: 1 display_submitted: true label_singular: 'book page' label_plural: 'book pages' -label_count: "1 book page\x03@count book pages" +label_count: + - "1 book page\x03@count book pages" diff --git a/core/modules/forum/config/optional/node.type.forum.yml b/core/modules/forum/config/optional/node.type.forum.yml index a6f19e8f3a..5e0db03df4 100644 --- a/core/modules/forum/config/optional/node.type.forum.yml +++ b/core/modules/forum/config/optional/node.type.forum.yml @@ -13,4 +13,5 @@ preview_mode: 1 display_submitted: true label_singular: 'forum topic' label_plural: 'forum topics' -label_count: "1 forum topic\x03@count forum topics" +label_count: + - "1 forum topic\x03@count forum topics" diff --git a/core/modules/node/src/Entity/NodeType.php b/core/modules/node/src/Entity/NodeType.php index f48dcc4ab7..d7ba42cef0 100644 --- a/core/modules/node/src/Entity/NodeType.php +++ b/core/modules/node/src/Entity/NodeType.php @@ -3,7 +3,6 @@ namespace Drupal\node\Entity; use Drupal\Core\Config\Entity\ConfigEntityBundleBase; -use Drupal\Core\Config\Entity\EntityBundleWithPluralLabelsInterface; use Drupal\Core\Config\Entity\EntityBundleWithPluralLabelsTrait; use Drupal\Core\Entity\EntityStorageInterface; use Drupal\node\NodeTypeInterface; @@ -49,7 +48,7 @@ * } * ) */ -class NodeType extends ConfigEntityBundleBase implements NodeTypeInterface, EntityBundleWithPluralLabelsInterface { +class NodeType extends ConfigEntityBundleBase implements NodeTypeInterface { use EntityBundleWithPluralLabelsTrait; diff --git a/core/modules/node/src/NodeTypeForm.php b/core/modules/node/src/NodeTypeForm.php index adf7b58023..3544cd9026 100644 --- a/core/modules/node/src/NodeTypeForm.php +++ b/core/modules/node/src/NodeTypeForm.php @@ -211,7 +211,7 @@ public function form(array $form, FormStateInterface $form_state) { ]; $plurals = $this->getNumberOfPlurals($type->language()->getId()); for ($i = 0; $i < $plurals; $i++) { - $form['display']['label_count'][$i] = [ + $form['display']['label_count'][0][$i] = [ '#type' => 'textfield', '#title' => $this->getPluralVariantLabel($plurals, $i), '#description' => $this->t('Text to use for this variant, @count will be replaced with the number of @plural.', $arguments), @@ -245,7 +245,11 @@ public function validateForm(array &$form, FormStateInterface $form_state) { } // Pack the label_count values as a plural_label. - $form_state->setValue('label_count', implode(PluralTranslatableMarkup::DELIMITER, $form_state->getValue('label_count'))); + $label_count = []; + foreach ($form_state->getValue('label_count') as $plural_variants) { + $label_count[] = implode(PluralTranslatableMarkup::DELIMITER, $plural_variants); + } + $form_state->setValue('label_count', $label_count); } /** @@ -330,8 +334,7 @@ protected function getPluralVariantDefaultValue($delta) { $type = $this->getEntity(); if (!isset($label_count)) { - $label_count = $type->get('label_count'); - $label_count = $label_count ? explode(PluralTranslatableMarkup::DELIMITER, $label_count) : []; + $label_count = isset($type->get('label_count')[0]) ? explode(PluralTranslatableMarkup::DELIMITER, $type->get('label_count')[0]) : []; } if (isset($label_count[$delta])) { diff --git a/core/modules/node/src/NodeTypeInterface.php b/core/modules/node/src/NodeTypeInterface.php index df4831e566..80485335a6 100644 --- a/core/modules/node/src/NodeTypeInterface.php +++ b/core/modules/node/src/NodeTypeInterface.php @@ -3,12 +3,13 @@ namespace Drupal\node; use Drupal\Core\Config\Entity\ConfigEntityInterface; +use Drupal\Core\Config\Entity\EntityBundleWithPluralLabelsInterface; use Drupal\Core\Entity\RevisionableEntityBundleInterface; /** * Provides an interface defining a node type entity. */ -interface NodeTypeInterface extends ConfigEntityInterface, RevisionableEntityBundleInterface { +interface NodeTypeInterface extends ConfigEntityInterface, RevisionableEntityBundleInterface, EntityBundleWithPluralLabelsInterface { /** * Determines whether the node type is locked. diff --git a/core/modules/node/src/Tests/NodeTypeTest.php b/core/modules/node/src/Tests/NodeTypeTest.php index fec15562b7..e501eabd8c 100644 --- a/core/modules/node/src/Tests/NodeTypeTest.php +++ b/core/modules/node/src/Tests/NodeTypeTest.php @@ -280,8 +280,8 @@ public function testPluralLabels() { $edit = [ 'label_singular' => 'mouse', 'label_plural' => 'mice', - 'label_count[0]' => '1 mouse', - 'label_count[1]' => '@count mice', + 'label_count[0][0]' => '1 mouse', + 'label_count[0][1]' => '@count mice', ]; $this->drupalPostForm('admin/structure/types/manage/mouse', $edit, 'Save content type'); diff --git a/core/modules/node/tests/src/Functional/NodeTypePluralLabelsTranslationTest.php b/core/modules/node/tests/src/Functional/NodeTypePluralLabelsTranslationTest.php index 1898e1ae7b..56258e44ac 100644 --- a/core/modules/node/tests/src/Functional/NodeTypePluralLabelsTranslationTest.php +++ b/core/modules/node/tests/src/Functional/NodeTypePluralLabelsTranslationTest.php @@ -69,19 +69,19 @@ public function testNodeTypeTranslation() { $this->drupalGet('admin/structure/types/add'); // Check that 3 plural variants are exposed for the Romanian language. - $this->assertSession()->fieldExists('label_count[0]'); - $this->assertSession()->fieldExists('label_count[1]'); - $this->assertSession()->fieldExists('label_count[2]'); - $this->assertSession()->fieldNotExists('label_count[3]'); + $this->assertSession()->fieldExists('label_count[0][0]'); + $this->assertSession()->fieldExists('label_count[0][1]'); + $this->assertSession()->fieldExists('label_count[0][2]'); + $this->assertSession()->fieldNotExists('label_count[0][3]'); $edit = [ 'name' => 'Copil', 'type' => 'child', 'label_singular' => 'copil', 'label_plural' => 'copii', - 'label_count[0]' => '1 copil', - 'label_count[1]' => '@count copii', - 'label_count[2]' => '@count de copii', + 'label_count[0][0]' => '1 copil', + 'label_count[0][1]' => '@count copii', + 'label_count[0][2]' => '@count de copii', ]; $this->drupalPostForm(NULL, $edit, 'Save and manage fields'); @@ -89,8 +89,8 @@ public function testNodeTypeTranslation() { 'translation[config_names][node.type.child][name]' => 'Child', 'translation[config_names][node.type.child][label_singular]' => 'child', 'translation[config_names][node.type.child][label_plural]' => 'children', - 'translation[config_names][node.type.child][label_count][0]' => '1 child', - 'translation[config_names][node.type.child][label_count][1]' => '@count children', + 'translation[config_names][node.type.child][label_count][0][0]' => '1 child', + 'translation[config_names][node.type.child][label_count][0][1]' => '@count children', ]; $this->drupalPostForm('admin/structure/types/manage/child/translate/en/add', $edit, 'Save translation'); @@ -121,13 +121,13 @@ public function testNodeTypeTranslation() { self::assertEquals($node_type->getCountLabel(20), '20 children'); // Clear the count label second variant to test variant delta preserving. - $edit = ['label_count[1]' => '']; - $this->drupalPostForm($node_type->urlInfo('edit-form'), $edit, 'Save content type'); + $edit = ['label_count[0][1]' => '']; + $this->drupalPostForm($node_type->toUrl('edit-form'), $edit, 'Save content type'); $node_type = NodeType::load('child'); // Check that the variants delta has been preserved. - $variants = explode(PluralTranslatableMarkup::DELIMITER, $node_type->get('label_count')); + $variants = explode(PluralTranslatableMarkup::DELIMITER, $node_type->get('label_count')[0]); self::assertEquals($variants[0], '1 copil'); self::assertEquals($variants[1], ''); self::assertEquals($variants[2], '@count de copii'); diff --git a/core/modules/rest/tests/src/Functional/EntityResource/NodeType/NodeTypeResourceTestBase.php b/core/modules/rest/tests/src/Functional/EntityResource/NodeType/NodeTypeResourceTestBase.php index 12df01f571..99aa300f90 100644 --- a/core/modules/rest/tests/src/Functional/EntityResource/NodeType/NodeTypeResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/EntityResource/NodeType/NodeTypeResourceTestBase.php @@ -61,7 +61,7 @@ protected function getExpectedNormalizedEntity() { 'help' => NULL, 'label_count' => NULL, 'label_plural' => NULL, - 'label_singular' => NULL, + 'label_singular' => [], 'langcode' => 'en', 'name' => 'Camelids', 'new_revision' => TRUE, diff --git a/core/profiles/standard/config/install/node.type.article.yml b/core/profiles/standard/config/install/node.type.article.yml index 9d6f11a0b9..13de4e6d33 100644 --- a/core/profiles/standard/config/install/node.type.article.yml +++ b/core/profiles/standard/config/install/node.type.article.yml @@ -10,4 +10,5 @@ preview_mode: 1 display_submitted: true label_singular: article label_plural: articles -label_count: "1 article\x03@count articles" +label_count: + - "1 article\x03@count articles" diff --git a/core/profiles/standard/config/install/node.type.page.yml b/core/profiles/standard/config/install/node.type.page.yml index 2c1de802da..01dd16a83d 100644 --- a/core/profiles/standard/config/install/node.type.page.yml +++ b/core/profiles/standard/config/install/node.type.page.yml @@ -10,4 +10,5 @@ preview_mode: 1 display_submitted: false label_singular: page label_plural: pages -label_count: "1 page\x03@count pages" +label_count: + - "1 page\x03@count pages"