diff --git a/core/config/schema/core.entity.schema.yml b/core/config/schema/core.entity.schema.yml index 6a4bc1a..60f214b 100644 --- a/core/config/schema/core.entity.schema.yml +++ b/core/config/schema/core.entity.schema.yml @@ -367,8 +367,5 @@ bundle_config_entity: type: label label: 'Indefinite plural name' label_count: - type: sequence + type: plural_label label: 'Count label' - sequence: - type: label - label: 'Plural variant' diff --git a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBundleBase.php b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBundleBase.php index 131af79..6b3380b 100644 --- a/core/lib/Drupal/Core/Config/Entity/ConfigEntityBundleBase.php +++ b/core/lib/Drupal/Core/Config/Entity/ConfigEntityBundleBase.php @@ -32,11 +32,9 @@ /** * A definite singular/plural count label. * - * The label is an array having the plural variants as items. - * - * @var string[] + * @var string */ - protected $label_count = []; + protected $label_count; /** * Deletes display if a bundle is deleted. @@ -94,7 +92,14 @@ public static function postDelete(EntityStorageInterface $storage, array $entiti * {@inheritdoc} */ public function getSingularLabel() { - return $this->label_singular = $this->label_singular ?: Unicode::strtolower($this->label()); + if (empty($this->label_singular)) { + // Provide a fallback in case label_singular is not set yet. + if ($this->isNew()) { + return ''; + } + $this->label_singular = Unicode::strtolower($this->label()); + } + return $this->label_singular; } /** @@ -102,8 +107,13 @@ public function getSingularLabel() { */ public function getPluralLabel() { if (empty($this->label_plural)) { + // Provide a fallback in case label_plural is not set yet. + if ($this->isNew()) { + return ''; + } $arguments = ['@label' => Unicode::strtolower($this->label())]; - $this->label_plural = new TranslatableMarkup('@label items', $arguments); + $options = ['langcode' => $this->language()->getId()]; + $this->label_plural = new TranslatableMarkup('@label items', $arguments, $options); } return $this->label_plural; } @@ -113,14 +123,15 @@ public function getPluralLabel() { */ public function getCountLabel($count) { $index = $this->getPluralIndex($count); - if (isset($this->label_count[$index])) { - return new FormattableMarkup($this->label_count[$index], ['@count' => $count]); + $label_count = empty($this->label_count) ? [] : explode(PluralTranslatableMarkup::DELIMITER, $this->label_count); + if (isset($label_count[$index])) { + return new FormattableMarkup($label_count[$index], ['@count' => $count]); } $arguments = [ - '@label_singular' => $this->getSingularLabel(), - '@label_plural' => $this->getPluralLabel(), + '@singular' => $this->getSingularLabel(), + '@plural' => $this->getPluralLabel(), ]; - return new PluralTranslatableMarkup($count, '1 @label_singular', '@count @label_plural', $arguments); + return new PluralTranslatableMarkup($count, '1 @singular', '@count @plural', $arguments); } /** diff --git a/core/modules/book/config/install/node.type.book.yml b/core/modules/book/config/install/node.type.book.yml index 0c07a79..4deaa97 100644 --- a/core/modules/book/config/install/node.type.book.yml +++ b/core/modules/book/config/install/node.type.book.yml @@ -11,3 +11,6 @@ help: '' new_revision: true preview_mode: 1 display_submitted: true +label_singular: 'book page' +label_plural: '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 8ed965d..a6f19e8 100644 --- a/core/modules/forum/config/optional/node.type.forum.yml +++ b/core/modules/forum/config/optional/node.type.forum.yml @@ -11,3 +11,6 @@ help: '' new_revision: false preview_mode: 1 display_submitted: true +label_singular: 'forum topic' +label_plural: 'forum topics' +label_count: "1 forum topic\x03@count forum topics" diff --git a/core/modules/node/src/NodeTypeForm.php b/core/modules/node/src/NodeTypeForm.php index 6d160ab..f08286b 100644 --- a/core/modules/node/src/NodeTypeForm.php +++ b/core/modules/node/src/NodeTypeForm.php @@ -6,6 +6,7 @@ use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Form\FormStateInterface; +use Drupal\Core\StringTranslation\PluralTranslatableMarkup; use Drupal\language\Entity\ContentLanguageSettings; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -184,7 +185,7 @@ public function form(array $form, FormStateInterface $form_state) { ); $form['display']['plural'] = [ '#type' => 'fieldset', - '#title' => $this->t('Label variants'), + '#title' => $this->t('Singular and plural labels'), '#description' => $this->t('These are alternatives to the node type label for singular and plural cases.'), ]; $form['display']['plural']['label_singular'] = [ @@ -200,47 +201,20 @@ public function form(array $form, FormStateInterface $form_state) { '#default_value' => $type->getPluralLabel(), ]; - if (\Drupal::hasService('locale.plural.formula')) { - $langcode = $type->language()->getId(); - $plurals = \Drupal::service('locale.plural.formula')->getNumberOfPlurals($langcode); - } - else { - // We assume 2 plurals if Locale's services are not available. - $plurals = 2; - } - $label_count = $type->get('label_count'); - + $arguments = ['@plural' => $type->getPluralLabel() ?: $this->t('items')]; $form['display']['label_count'] = [ '#type' => 'fieldset', '#title' => $this->t('Count labels'), - '#description' => $this->t('Count labels are used to build a text representation of a certain number of @label_plural. Token @count is available and will be replaced with the number of @label_plural.', ['@label_plural' => $type->getPluralLabel()]), + '#description' => $this->t('Count labels are used to build a text representation of a certain number of @label_plural. Token @count is available and will be replaced with the number of @plural.', $arguments), '#tree' => TRUE, ]; + $plurals = $this->getNumberOfPlurals($type->language()->getId()); for ($i = 0; $i < $plurals; $i++) { - if ($i == 0) { - $title = $this->t('Singular form'); - } - elseif ($plurals == 2 && $i == 1) { - $title = $this->t('Plural form'); - } - else { - $title = $this->formatPlural($i, 'First plural form', '@count. plural form'); - } - if (isset($label_count[$i])) { - $default_value = $label_count[$i]; - } - else { - $arguments = [ - '@label_singular' => $type->getSingularLabel(), - '@label_plural' => $type->getPluralLabel(), - ]; - $default_value = $i == 0 ? $this->t('1 @label_singular', $arguments) : $this->t('@count @label_plural', $arguments); - } $form['display']['label_count'][$i] = [ '#type' => 'textfield', - '#title' => $title, - '#description' => $this->t('Text to use for this variant, @count will be replaced with the number of @label_plural.', ['@label_plural' => $type->getPluralLabel()]), - '#default_value' => $default_value, + '#title' => $this->getPluralVariantLabel($plurals, $i), + '#description' => $this->t('Text to use for this variant, @count will be replaced with the number of @plural.', $arguments), + '#default_value' => $this->getPluralVariantDefaultValue($i), ]; } @@ -268,6 +242,10 @@ public function validateForm(array &$form, FormStateInterface $form_state) { if ($id == '0') { $form_state->setErrorByName('type', $this->t("Invalid machine-readable name. Enter a name other than %invalid.", array('%invalid' => $id))); } + + // Pack the label_count values as a plural_label. + $label_count = array_filter($form_state->getValue('label_count')); + $form_state->setValue('label_count', implode(PluralTranslatableMarkup::DELIMITER, $label_count)); } /** @@ -315,4 +293,64 @@ public function save(array $form, FormStateInterface $form_state) { $form_state->setRedirectUrl($type->urlInfo('collection')); } + /** + * Returns a plural variant label given the variant delta and variants count. + * + * @param int $plurals + * The total number of plural variants. + * @param int $delta + * The plural variant delta. + * + * @return \Drupal\Component\Render\MarkupInterface + * The variant label. + */ + protected function getPluralVariantLabel($plurals, $delta) { + if ($delta == 0) { + return $this->t('Singular form'); + } + elseif ($plurals == 2 && $delta == 1) { + return $this->t('Plural form'); + } + return $this->formatPlural($delta, 'First plural form', '@count. plural form'); + } + + /** + * Retrieves a plural variant from the backend or assures a decent fallback. + * + * @param int $delta + * The plural variant delta. + * + * @return \Drupal\Component\Render\MarkupInterface|string + * The plural variant default value. + */ + protected function getPluralVariantDefaultValue($delta) { + static $label_count; + + /** @var \Drupal\node\Entity\NodeType $type */ + $type = $this->getEntity(); + + if (!isset($label_count)) { + $label_count = $type->get('label_count'); + $label_count = $label_count ? explode(PluralTranslatableMarkup::DELIMITER, $label_count) : []; + } + + if (isset($label_count[$delta])) { + // A value was stored in the backend. + return $label_count[$delta]; + } + + $singular = $type->getSingularLabel(); + $plural = $type->getPluralLabel(); + + if ($type->isNew() || ($delta == 0 && empty($singular) || ($delta > 0 && empty($plural)))) { + // Either the node type is not yet saved (we don't even know the entity + // label) or we cannot assure a decent fallback. + return ''; + } + + // Provide a fallback default value. + $arguments = ['@singular' => $singular, '@plural' => $plural]; + return $delta == 0 ? $this->t('1 @singular', $arguments) : $this->t('@count @plural', $arguments); + } + } diff --git a/core/profiles/standard/config/install/node.type.article.yml b/core/profiles/standard/config/install/node.type.article.yml index 2a13b53..9d6f11a 100644 --- a/core/profiles/standard/config/install/node.type.article.yml +++ b/core/profiles/standard/config/install/node.type.article.yml @@ -10,6 +10,4 @@ preview_mode: 1 display_submitted: true label_singular: article label_plural: articles -label_count: - - '1 article' - - '@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 60f4101..2c1de80 100644 --- a/core/profiles/standard/config/install/node.type.page.yml +++ b/core/profiles/standard/config/install/node.type.page.yml @@ -10,6 +10,4 @@ preview_mode: 1 display_submitted: false label_singular: page label_plural: pages -label_count: - - '1 page' - - '@count pages' +label_count: "1 page\x03@count pages"