Problem/Motivation
Entity types can define now plurals for their labels starting with #1850080: Entity type labels lack plurality, cannot generate UI text based on label if plural is needed. It's possible now to have the variants "content item" (singular) and "content items" (plural) for nodes. We want the same for bundles. We want to be able to have "article" (singular) and "articles" (plural).
It's not the same as for entity types. Entity types can define the label plural variants in the annotation while for bundles the site builder should be able to add such variants. Thus we need to store the variants in the bundle config entity and provide UI for site builders.
Proposed resolution
Create the foundation that allows bundle config entities to store plural labels and add this ability to the node_type
bundle entity as a start.
- Create a new interface
EntityBundleWithPluralLabelsInterface
that defines 6 new methods:setSingularLabel()
getSingularLabel()
setPluralLabel()
getPluralLabel()
setCountLabel()
getCountLabel()
These are similar to those implemented to entity types.
- Add a common implementation for the new 6 methods in a new trait
EntityBundleWithPluralLabelsTrait
, to be reused in most of the bundle config entities. - Create a
bundle_entity_with_plural_labels
schema to be used by bundles that want to support plural labels. The new schema contains the new storage keys:label_singular
,label_plural
,label_count
. - Allow more than one version for the count label. This is because, in the real world, a site might need different versions depending on the place these count labels are used. Let's see a hypothetical website scenario:
- On a page the count label could be a simple label as
1 article\x03@count articles
. - On a search results page we need a different version:
1 article was found\x03@count articles were found
. Note that we cannot build this version by deriving from the first one because of the was/were thing. - In other place something like
<span>1</span> article\x03<span>@count</span> articles
. - In a 3rd place, because the count is displayed in other
<div ...>
or even is rendered in a different theme hook, justArticle\x03Articles
, without the count part.
Similar with translated strings, were we are able to store contextualised translations and then retrieve them by passing the context identifier, we allow
label_count
to store multiple versions, identifiable by a context string identifier. - On a page the count label could be a simple label as
- Bundles declared via
hook_entity_bundle_info()
, are able to declare such labels by using the keys:label_singular
,label_plural
andlabel_count
. This will be documented inentity.api.php
[see #108, #109]. - Bundles supporting plurals labels, regardless if they are defined as config entities or via
hook_entity_bundle_info()
, are able to process the count label, given a count, by using the new service methodentity_type.bundle.info::getBundleCountLabel()
. This is a new method exposed byEntityTypeBundleInfoInterface
[see #108, #109] - Make
NodeTypeInterface
extend alsoEntityBundleWithPluralLabelsInterface
. - Make
NodeType
use theEntityBundleWithPluralLabelsTrait
trait. - Make
node.type.*
schema extendbundle_entity_with_plural_labels
. - Add plural labels to all node types shipped with Drupal core.
- The UI for editing node type plural labels is added in a follow-up: #2938251: Allow edit of bundle plural labels in the node type form.
Remaining tasks
- #2938251: Allow edit of bundle plural labels in the node type form
- Open issues for each bundle type that requires label plurals.
User interface changes
None. The UI changes are split in #2938251: Allow edit of bundle plural labels in the node type form.
API changes
New interface \Drupal\Core\Config\Entity\EntityBundleWithPluralLabelsInterface
:
setSingularLabel()
getSingularLabel()
setPluralLabel()
getPluralLabel()
setCountLabel()
getCountLabel()
Data model changes
The node type bundle config entity has new keys/values: label_singular
, label_plural
, label_count
.
Comment | File | Size | Author |
---|---|---|---|
#144 | 2765065-144.patch | 40.45 KB | ajaypratapsingh |
#141 | interdiff_140-141.txt | 2.07 KB | ranjith_kumar_k_u |
#141 | 2765065-141.patch | 40.34 KB | ranjith_kumar_k_u |
#140 | 2765065-140.patch | 40.22 KB | karishmaamin |
#138 | 2765065-138-unofficial-8.9.x.patch | 41.09 KB | Siggy |
Issue fork drupal-2765065
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
claudiu.cristeaThis is a first try, a PoC
Comment #3
claudiu.cristeaComment #5
Gábor HojtsyI don't think the proposed resolution works because bundles are user created and may therefore be in any language (unlike entity types defined in code). So there may be a number of plural variants. See Drupal\views\Plugin\views\field\NumericField for example, especially:
Comment #6
Gábor HojtsyThat is, #5 for the counted singular/plural case. The general singular/plural case that is above is simpler and would the same I think regardless of language of the bundle configuration.
Comment #7
Gábor HojtsyComment #8
claudiu.cristea@Gábor Hojtsy,
I agree but there's only one form for label_plural. This is also true for #1850080: Entity type labels lack plurality, cannot generate UI text based on label if plural is needed.
When it comes to count labels, the patch allows multiple (>2) variants.
.
Comment #9
Gábor HojtsyRight, sorry the screenshot mislead me by showing the single plural case, which is all too common ;) Looking at the implementation it would be nice to harmonize the form elements and descriptions with the ones in views, config translation, etc. (same patterns used there). Other than that there are two main problems that I found while reviewing and two not so big ones:
Minor: This would be nicer to call entity_bundle or somesuch for clarity?
Config translation stores and manages translations as overrides (think deep array merge). Therefore storing the count labels as a sequence does not work because if the original was English and the translation was Polish (more plural forms), there would be new keys appearing in the config, which is not supposed to happen with overrides. The config is supposed to have the same keys regardless of overrides.
Also this way the plural variants are not translatable (strings are not, labels are). And if there would be 2 English source strings, you could only have 2 Polish translations. See and use the plural_label config schema type.
Should the default value not be whatever was stored? :)
This assumes the language of the config is the language of the current UI interface language, however there is no relation between the two. You may be editing English configuration in Polish and vice versa. The right number of plural forms based on the *language of the configuration itself* should be exposed. See again the views formatter code above.
is available.'),
...
+ $title = $this->t('Singular');
...
+ $title = $this->t('Plural');
...
+ $title = $this->t('Plural variant #@variant', ['@variant' => $i]);
Use labels in sync with views formatter, config translation, etc.
Comment #10
claudiu.cristea@Gábor Hojtsy, thank you for review.
#9.1: True. As is extending
config_entity
I rename itbundle_config_entity
.#9.2: Right about
type: string
vs.type: label
. I changed that. Butsequence
vs.plural_label
the problem is the same in terms of overriding on translation. In terms of storage I like more sequence (an indexed array) because: (1) it's more readable when you inspect the config as YAML and (2) it removes the need of imploding/exploding a string. In factplural_label
is only storing an array/sequence as a concatenated string. But in terms of override is the same. Let's see what is happing when translating an English node-type in Polish. The label_count is a sequence with 2 items and in Polish will have only 2 items. When you visit the Polish node-type edit form, the form will still expose 3 text fields. The first 2 copied from English and the 3rd one filled with the fallback value. After the user make changes and submits the form, in the Polish version of the node-type config entity all 3 variants will be stored. The same happens if we useplural_label
.#9.3: It defaults to stored value but falls back to a default value.
#9.4: Correct. Changed.
#9.5: Changed.
Still needs tests.
Comment #11
claudiu.cristeaSorry, you are right on #9.2. Only now I enabled the
config_translation
module and saw that i cannot add the 3rd variant there. Will change that in the next patch.Comment #12
Gábor HojtsyThis does not solve the problems I outlined. When the original config is in English, you'll have two items in this sequence and therefore the Polish translation can only have two items, even though it needs 3. A translation of one label can only be another one label. If your original configuration is Polish, your English translation would need to have translations for each 3 variants from Polish, even though that is nonsensical for English. Using plural_label, config translation understands the variance in element numbers required AND uses the exact same keys regardless of language.
Using a sequence does not work for multilingual use cases, unless you also reimplement plural handling with sequences too both in config_translation and language module's config override handler. That would mean a dependent issue that blocks this one, and I don't think that is a good idea anyway, since then we'd have two different ways to represent and translate plurals in configuration.
Comment #14
claudiu.cristea@Gábor Hojtsy, fixed that & many others.
Comment #15
claudiu.cristeaComment #16
claudiu.cristeaComment #17
claudiu.cristeaTests were added in #16.
Comment #18
claudiu.cristeaDo not add
label_singular
,label_plural
,label_count
toconfig_export
if were already added in annotation.Comment #19
Gábor HojtsyThanks for the update!
It should say these are separated with PluralTranslatableMarkup::DELIMITER
It may still already have a label even if not yet saved, no?
We don't place @todo in core without an issue number opened for it :)
The elements are not required in the form, so it looks odd to say in the summary that they are.
is available and will be replaced with the number of @plural.', $arguments),
Do we say "token" elsewhere like this? I don't think so.
Comment #20
claudiu.cristeaThank you for review, @Gábor Hojtsy!
#19.1: Done.
#19.2
Hm. You mean by implementing JS stuff?
#19.3: I've opened #2766857: Provide a PluralTranslatableMarkup::getPluralVariantIndex() factory method and changed the @todo.
#19.4: OK. I completely removed the "missed" state message to avoid cluttering the vertical tab label.
#19.5: "Placeholder" sounds better?
Comment #21
claudiu.cristea@Gábor Hojtsy, I added a patch also in #2766857-3: Provide a PluralTranslatableMarkup::getPluralVariantIndex() factory method. If that is accepted we change this accordingly.
Comment #22
claudiu.cristeaAddressed #19.2
Comment #23
Gábor HojtsyLooks good to me now. Sounds like this would be down to the usability review.
Comment #24
claudiu.cristeaThank you for review, @Gábor Hojtsy. Do you think you can take a look also at #2766857: Provide a PluralTranslatableMarkup::getPluralVariantIndex() factory method? That would help here to avoid the code duplication (
ConfigEntityBundleBase::getPluralIndex()
is a copy/paste from PluralTranslatableMarkup).Comment #25
Bojhan CreditAttribution: Bojhan as a volunteer and commentedI am completely lost why we would want to expose this in the UI. It seems like a very specific thing, cant this be done in code?
Comment #26
claudiu.cristea@Bojhan, In fact these are forms of the label. As we let the site builder to enter the bundle label why wouldn't we allow the same with the label plural form?
Comment #27
Gábor Hojtsy@Bojhan: in other words because you create node types on the UI and not in code. When you create a "Fish" content type, that needs plural forms and depending on language, it may have different plurals. Eg. in English the plural would be "Fish" as well :) Not so for Article -> Articles or Mouse -> Mice as in the screenshots. For more interesting languages, eg. Polish or Romanian there are even more plural variants. Then when we display counters, pagers, etc. we print "@count fish", "@count articles", "@count mice" etc, we need to use the right forms if we want to make sense in the given human language.
Comment #28
Bojhan CreditAttribution: Bojhan as a volunteer and commentedI understand the why :) It just makes for a lot of clutter. Perhaps we can avoid having it in the vertical tab? Its very non-critical information.
Comment #29
claudiu.cristea@Bojhan, this is the reason I hide it in an non-active vertical tab. Or you mean the tab label?
Comment #30
Bojhan CreditAttribution: Bojhan as a volunteer and commentedYup, the label.
Comment #31
claudiu.cristea@Bojhan, OK, I removed that. However, don't you think it would be helpful as UX if we just show a message there if plurals are missed, like "Needs plural labels", or similar?
I also converted the new NodeTypePluralLabelsTranslationTest test into a BrowserTestBase.
Comment #33
claudiu.cristeaFailures seems unrelated
Comment #35
claudiu.cristeaRan Drupal\Tests\dblog\Kernel\Migrate\d6\MigrateDblogConfigsTest locally and passes. Strange
Retesting
Comment #36
Bojhan CreditAttribution: Bojhan as a volunteer and commentedComment #37
penyaskitoGábor approved this change in #23, and Bohjan performed the Usability review on #28, #30 and #36. I did a cursor review of the patch and looks good, so let's RTBC it.
Comment #38
claudiu.cristeaI think this needs a change record and possibly, being a new feature, should be included in the release notes.
Comment #39
claudiu.cristeaAdded draft CR: https://www.drupal.org/node/2773615
Comment #40
claudiu.cristeaUpdating screenshots to match the RTBC patch.
Comment #41
catchTagging as beta deadline for 8.2.x (it could go into 8.3.x if it doesn't make it in time). Also nice one getting this RTBC, feels like only a couple of days since we even talked about it.
Comment #42
claudiu.cristea@catch, yes it was very fast. But this was possible thanks to @Gábor Hojtsy and @Bojhan on reviewing the issue.
Only a small fix: We need to preserve the count label plural variants deltas.
Comment #43
alexpottHow come this change is not accompanied by a change in the tests?
Comment #44
claudiu.cristea@alexpott, tested that change.
Comment #45
penyaskitoRemarks at #43 have been covered.
Comment #46
tim.plunkettNit: subsequent lines of an @todo should be indented two extra spaces
Why does one use formatPlural and the other doesn't?
\Drupal\node\NodeTypeInterface
Also should use the interface
Shouldn't need the & on &$entity_types, remove please
is the \x03 really how it's saved? AFAIK i've seen other yaml with multiline strings with regular newlines
This is very close, but at least that & should be removed.
Comment #47
claudiu.cristea@tim.plunkett, thank you for review.
#46.1: OK.
#46.2: The first builds the labels and, reading the code, it's obvious why. That one is producing the same labels as in
\Drupal\views\Plugin\views\field\NumericField
. The 2nd, specifically that return, is a fallback default value, when we have no labels stored in the backend but we're still able to build a decent fallback. Why we're not using formatPlural? Simply because we cannot predict any plural variant. We use t() only for words ordering inside the string (in other languages the order might be reversed). So, we provide the same plural default value fallback for all @count > 1 plural variants.#46.3, 4: OK, even I disagree. That was supposed to help in IDE. Now
$node_type->getSingularLabel()
is highlighted in PhpStorm and the IDE is yelling "Method 'getSingularLabel' not found in \Drupal\node\NodeTypeInterface" because the method is in other NodeType interface. I think we should re-consider that kind of commenting because that is NOT type-hinting, but only a DX helper.#46.5: Fixed.
#46.6: That special char is NOT a newline, it's
PluralTranslatableMarkup::DELIMITER
.I'm moving back to RTBC as changes are only nits to documentation.
Comment #48
tim.plunkett6: well it's equivalent to CTRL-C, but yes I got it confused with \x0A. The docs on PluralTranslatableMarkup::DELIMITER are helpful, thanks.
+1 for RTBC
Comment #49
alexpottI've just realised we are missing a few things:
Comment #50
claudiu.cristea@alexpott, thank you for your comments.
#49.1: I don't think we should provide any upgrade path. The labels are site builder decisions, we cannot predict that. Neither on labels of standard profile. If such a site is updated then the site builder will have to visit the page and manually enter his desired labels. Imagine that on a site installed prior this patch the site builder has set the 'article' main label to 'Super-mega article'. The site updates. Who give us the right to set the plural labels to 'articles'? This should be entirely a manual process.
#49.2:
No, please re-read the IS. In this issue we are providing the foundation for all bundle types to define such plural label variants. Some of them might provide UI to allow site builder to set them. Some of them will decide to set such labels through the code and, probably, some will ignore this feature. But we should provide all of them with the chance to declare such label variants. This issue is not about the NodeType specifically but about all bundle types. I choose to implement here the UI for NodeType because is the most popular and also to provide an example for other core or contrib implementations. After committing this we ca decide to open a new follow-up issue for taxonomy vocabularies. But if we don't, probably someone will create a contrib for that. The foundation is there. In custom modules a lot will provide the labels directly in the code (in default config YAMLs) but will use the same foundation.
#49.3: I cannot reproduce that. If I'm adding a new content type all the fields are empty (expected). If I save the form without entering any of them, next time I visit the form I see them filled with the fallback values because now there is a main label and the form is able to build some decent fallbacks.
admin/structure/types/add
Saving without entering any value.
admin/structure/types/manage/mouse
Comment #51
claudiu.cristeaDiscussed with @alexpott on IRC to go with #49.2.
Comment #52
xjm(Removing release notes tag; we can retag for whichever release notes whenever the change is committed.)
Comment #53
claudiu.cristeaDiscussed with @alexpott on IRC abut this feature. @alexpott suggested that we should make the interface & trait more generic and use them on both, on entity type and on bundles. But this seems a headache and would not bring too much benefit because:
Having all this differences, I don't think it makes too much sense add this level of abstraction. The only benefit would be the interface but the methods will have to be overwritten in implementations. Should I go with only a common interface or we remain on #51?
Comment #55
claudiu.cristeaThe tests for 8.3.x are passing. We should unblock this issue.
Comment #56
claudiu.cristeaHere's a use case for this new feature #2764007: Capitalize only first letter for the existing entity autocomplete label.
Comment #58
claudiu.cristeaAdapted for branch 8.3.x. Removed
t()
from BTB according to https://www.drupal.org/node/2783189#t. Nits.Comment #59
claudiu.cristeaComment #60
claudiu.cristeaRemoved t() also from WTB.
Comment #61
pfrenssenDid a quick review, found only a few nitpicks. I agree with #53 that it's better to have separate traits for entities and entity types - if we have to override all 3 methods in the trait then it's not a good abstraction.
Missing type hint
@var string
.This is actually
ETX
("End of TExt"), notEXT
.Just out of curiosity, is there a reason the first two values are using single quotes and the last one is using double quotes?
Oh wow :D
I'm not even pretending to know what is going on here :D
This is really interesting, that languages can have multiple plural forms. I guess some forms are more appropriate in specific contexts like labels on submit buttons or table column headers? Or whether it is mentioned on its own, or part of a running text?
Comment #62
pfrenssenUpdating status and removing outdated tag.
Comment #63
claudiu.cristea@pfrenssen, thank you for review. Rerolled and fixed #61.
#61.2: Double quotes are required when using control characters like
\x03
. Quoting from https://symfony.com/doc/current/components/yaml/yaml_format.html#strings:#61.3, 4:
No. The correct plural variant is determined by the number of items (count) to be represented. That formula is how gettext is telling how many variants of plurals has a specific language. This is the
nplurals=3;
part. That means the Romanian language has 1 variant for singular and 2 variants for plural. The 2nd part is telling how to find what variant of plural to use depending of the count. In this case (Romanian):plural=((n==1)?(0):(((n==0)||(((n%100)>0)&&((n%100)<20)))?(1):2));
If the count (n) is 1 use the 1st variant (delta 0 = the singular). If count is 0 or inside one of the next intervals 2..19, 101..119, 201..219, 301..319, etc., use the 2nd plural variant (delta 1). Otherwise use the 3rd one. This looks strange for a native English speaker as in English there's only singular and 1 variant of plural. In English the gettext plural formula would be
nplurals=2; plural=(n != 1);
. Here's a list with plural variants per language: http://docs.translatehouse.org/projects/localization-guide/en/latest/l10...Comment #64
claudiu.cristeaComment #66
ckaotikWhat bugs me is that both this and #1850080: Entity type labels lack plurality, cannot generate UI text based on label if plural is needed assume that entity type labels should be lowercased. This is simply incorrect for certain languages. For example, in English an image medium would be labeled as "image"/"images", while in German it's "Bild"/"Bilder".
Can we please not do this? Re-introducing the capitalization on a per use case basis is a PITA and simply cannot create correct results. Why not assume that the label is capitalized correctly for the given language, as seen in the screenshot examples in the summary?
Comment #68
claudiu.cristea@ckaotik, that is only the fallback, the default value. Once, you've entered your value that will be used.
Comment #69
claudiu.cristeaRerolled (including converting the update path test to a functional test).
Comment #71
claudiu.cristeaFixing the hal/rest tests.
Comment #73
claudiu.cristeaEnsure a fallback for the case the plural variant index cannot be computed (i.e. the 'locale' module is off).
Comment #75
claudiu.cristeaBetter test that a plural variant is available.
Comment #76
pfrenssenIt would be easier to read if the
$index
variable is defined on a separate line.Also the "fallback to a single plural variant" is a bit confusing, but I don't know how to explain it better.
This
implements EntityBundleWithPluralLabelsInterface
should be moved toNodeTypeInterface
.When I was testing this patch in my project I had some trouble because the
#default_value
is being set here to$type->getSingularLabel()
.These methods that return the singular/plural/count labels fall back to the name of the bundle if these values are not populated yet. But setting these fallbacks as a
#default_value
is not a good idea, because then if the form is saved these values are stored in the database.This happened to me when I edited a pre-existing node type, and I just edited the node type description and saved the form. This caused the fallback values to be written, even though I hadn't even opened the "Display settings" vertical tab.
A good solution would be to show the labels as a
#placeholder
, and use the actually stored data (without fallback value) for#default_value
.Comment #77
claudiu.cristeaRecently, in the project I'm working, I've faced this situation: I needed more than one version of the count label, depending on the place I used that label. For example on a page I need a simple label as
'1 article\x03@count articles'
, in other place something like'<span>1</span> article\x03<span>@count</span> articles'
and in a 3rd place just'Article\x03Articles'
. But how to accomplish this with the current patch? The patch from #75 only allows us to store and use a single version of the count label but in the real world having multiple arbitrary versions is not so uncommon.To overcome this problem I'm proposing that we allow multiple versions to be stored in the bundle entity. Then we can retrieve the desired version by passing a context string identifier to
::getCountLabel()
. In fact we are doing the same with translated strings were we are able to store contextualised translations and then retrieve them by passing the context identifier. It's the same here. This patch deals with this allowing storage and retrieval of multiple versions of count label.WARNING: In this patch the
NodeTypeForm
is not yet fixed to allow multiple versions. Neither the corresponding tests are allowing this in this stage. That part should be reworked. This patch is only a PoC to show the idea.It also, fixes #76.1 and #76.2. The placeholder stuff needs more thinking.
Comment #79
claudiu.cristeaFix the rest/hal tests
Comment #80
idimopoulos CreditAttribution: idimopoulos as a volunteer commentedThese are some remarks for brainstorming.
Why do we need a singular label? I can imagine that if you define the "Article" to have a singular label of "Basic Page", then in some cases the "Basic Page" will show and in some cases, the label "Article" will show. Even if this is allowed, then the title of the entity bundle will only be used as "Administrative title" so the whole field name should change.
Generally, I think this will create some confusion as it is kind of not needed extra information.
This 'plural_label' is the opposite of 'label_plural' above and while this is a sequence, it can still confuse. maybe something like count_plural, or label_count_plural (which seems like a child of the label_count above).
This provides a fallback in case the property is not set while the interface declares that it returns null if the property is not set.
In this method, it actually never returns empty as the label is always mandatory. The only case is when the entity is created which I guess, in that case, it does not matter if the return is "";
Then again, the property will be saved as "" which will return falsely later on and will not collide with the NULL return type that the interface declares. I think this can be reworked a bit.
This is more or less the same as above.
I think the keyword "Returns" is more appropriate.
I have a feeling, that if this patch is to be accepted, the community will still find this type machine name too weird :/
Comment #81
idimopoulos CreditAttribution: idimopoulos as a volunteer commentedComment #83
claudiu.cristea#80.1
I don't want to copy/paste all the arguments that were already discussed when these label versions were added in #1850080: Entity type labels lack plurality, cannot generate UI text based on label if plural is needed to entity types. For a background discussion, please follow that issue, especially #3, #8, #27 to #32.
#80.2
plural_label
is a type of data. Please seecore/config/schema/core.data_types.schema.yml
.label_plural
is the name of the bundle config entity property. It has this representation because it follows this unified pattern:label_(singular|plural|count)
. We want to keep the same key names as in #1850080: Entity type labels lack plurality, cannot generate UI text based on label if plural is needed.#80.3, 4
The unit test that I just added, proves that the return of these methods is typed as
string|null
, but I agree that the interface@return
docs might be confusing so I fixed the docs.#80.5
Good point. Fixed.
#80.6
Well, I think the community like when a specifier is descriptive. I like it too :)
Other changes:
EntityBundleWithPluralLabelsTrait
, especially when some plural labels are missed and we want to assure fallback values.Comment #84
claudiu.cristeaMore IS fixes.
Comment #85
claudiu.cristeaComment #87
claudiu.cristeaThis umami thing is something new. Improved docs & tests, fix coding standards. IS fixes
Comment #88
idimopoulos CreditAttribution: idimopoulos as a volunteer and at Randstad Digital for European Commission and European Union Institutions, Agencies and Bodies commentedUpdates seem fine to me. I am leaving this ticket under review though since it is a core patch that brings a lot of upgrades and it should be accepted with more than one (or a couple) reviews.
Comment #89
idimopoulos CreditAttribution: idimopoulos as a volunteer and at Randstad Digital for European Commission and European Union Institutions, Agencies and Bodies commentedI discussed this morning with @pfrenssen and @claudiu.cristea, we agreed to have the ticket in RTBC since there is enough test coverage and it is quite new functionality (no regression issues).
Comment #91
claudiu.cristeaRerolled.
Comment #92
larowlanc/p error `The singular' => 'The plural'
The english here is a bit disjointed.
`A list defining` perhaps?
Feels like we're overloading a primitive when a value object would make the API cleaner.
I'm the first to admit that i18n isn't my area of expertise, but this feels like we're overloading the return values.
I get that we use that for database storage purposes, but I'm not convinced we should base our APIs around it, it feels like it should be an internal implementation detail of PluralTranslatableMarkup.
I did some searching around po files (like I said, no expert) and it looks to be a Drupalism? Correct me if I'm wrong.
Edit: ah but we need to store them in config files.. so just an array might be simpler - instead of a value object
I think a constant instead of -1 would be good. But that would make it a public API, so if we don't want that, leave as is
we can return here and avoid the elseif
Can we add a case here that checks that Xss:filterAdmin is being run, e.g. add one with script tags in it
Do we need to update migration templates for d6/d7 to add these keys to the destination mappings?
Comment #93
claudiu.cristeaStraight reroll.
Comment #96
claudiu.cristea@larowlan,
#92.1: Fixed.
#92.2: It's "definite" vs. "indefinite". But true, because I missed the "of" word just before, it was confusing.
#92.3:
Yes, it is. This is the we are storing the variants in the config backend. See the schema of
plural_label
incore/config/schema/core.data_types.schema.yml
. I really don't like this separator approach. IMO this should be an array (which might contain gaps, like missing one variant). But this should be handled on core level, for sure not here. I only followed the actual way to store a the label plural variants. EDIT: See https://www.drupal.org/project/drupal/issues/2829919#92.4: OK.
#92.5: Fixed.
#92.6: I'm not sure I get it. If I'm adding tags in the string template they are preserved as I know, only the placeholders are sanitized. Stripping dangerous protocols is performed only on placeholders prefixed with
:
.Good point. I added the same behavior as for the post update.
Comment #97
claudiu.cristeaComment #98
idimopoulos CreditAttribution: idimopoulos at Randstad Digital for European Commission and European Union Institutions, Agencies and Bodies commentedThis ticket is quite important for us. I see that the interdiff contains the changes from the latest remarks and the rest are answered.
I am putting this back in RTBC and I am kindly assuming that the conversation will not result into further issues.
Comment #99
alexpottChanneling my inner German tells me that these mb_strtolower() is not going to be correct in many cases. This was pointed out in #66 by @ckaotik. Not sure that this makes the situation any worse but at some point we have to tackle this problem. It would be great to have @Berdir's thoughts.
be built
and there are some extra spaces in one of the comments.the
language
property is not defined but it also appears to not be used so it can be removed.Plural
notPLural
I think the NULL case should be an empty array. It's odd to have an optional nullable param before a required param. Or pass in
[NULL]
instead as that's what we're converting it too.Comment #100
Berdir1. Yes, similar problem as #2507235: EntityType::getLowercaseLabel() breaks translation. The problem is that the idea of word-used-in-a-sentence-means-lowercase does not apply to all languages, I don't know how many other languages are like German, but a lot of user interfaces in German are awful right now due to all those lowercase labels.
I guess this is a bit different as it's only a fallback and could be set explicitly, but I'm not sure how to set/translate that properly in German either way. At least the new interface doesn't really make it clear to me when I should use getSingularLabel() vs the existing bundle label method?
Comment #101
claudiu.cristeaThank you for review.
#99.1: @Berdir, this is the same as for entity types labels. You can use the singular in a phrase context, such as
t('Buy a @singular.', ['@singular' => $node_type->getSingularLabel()])
to produce Buy a fruit. In English the singular label will be "fruit" while in German, capitalized (if configured correctly). On a table header we can use the canonical bundle label "Fruit". The indefinite plural can be used in contexts such ast('I would like some @plural', ['@plural' => $node_type->getPluralLabel()])
, to produce I would like some fruits. For a background discussion, please follow the arguments that were already discussed when these label versions were added in #1850080: Entity type labels lack plurality, cannot generate UI text based on label if plural is needed, especially #3, #8, #27 to #32.Now, let's take the case of German language. On an existing site this concept of singular/plural/count labels doesn't exist. So, when this change will apply, nothing is happening because the methods are there but not used. As soon the new interface is used, but not configured, will start to show some fallback labels. In German language the developer in will see a lower-cased label but this is only a fallback, so he's able to add the correct singular/plural/label. But this is true for all languages -- the fallback guarantees nothing, it's just a guide to configure the correct labels.
#99.2, 3, 4: Fixed.
#99.5: We need to iterate over that value, so I choose to pass
[NULL]
.Comment #102
claudiu.cristeaBut I would be the first happy to drop all the fallbacks. Just that I tried to follow #1850080: Entity type labels lack plurality, cannot generate UI text based on label if plural is needed.
Comment #103
jonathanshawIf it's good enough for entity types, it has to be good enough for bundles.
As @claudiu points out these are fallbacks and can be overridden.
Let's commit this improvement, and file a follow-up for "Fallback labels for entity types and bundles do not allow for inter-language variation in capitalisation". There we could conceivably explore ways of improving this so that languages can declare whether nouns should be capitalised, and using that language information in these labels. But that's likely to be a complex subject with usefulness and ramifications far beyond bundle labels.
RTBC per #98.
Comment #104
claudiu.cristea#103 missed to change the status.
Comment #105
jonathanshawWhoops :)
Comment #107
Chi CreditAttribution: Chi commentedSymfony now offers Inflector component. Which seems useful for such things.
https://symfony.com/doc/master/components/inflector.html
Comment #108
BerdirYes, unlike the entity type lowercase issue, this is only a fallback and can be overridden, that's true. So it is better than that.
That it is equally good/bad as the entity type labels and shouldn't block that is a fair argument, but it's also true that adding those entity type labels resulted in a mess on german sites, also because there it's not something you can update in configuration. That should make it easier to deal with it. Although there is no UI yet ;)
One thing I'm wondering about is whether the config schema definition should have a context key so that it can be translated separately. That might help dealing with conflicts where words are both noun and verb and might need to be translated differently in german. See recent improvement in workflow translation labels.
> Open issues for each bundle type that requires label plurals.
We should probably create an issue for this? Also, introducing a new entity API and only having a single implementation for it is a bit atypical these days, usually we at least add a test implementation in a test entity type too, e.g. for \Drupal\entity_test\Entity\EntityTestBundle.
The API also doesn't really support bundles that aren't config entities, usually extra per-bundle information is added through the bundle info service: \Drupal\Core\Entity\EntityTypeBundleInfo. that would mean it would have to be array keys instead of methods, but the methods defined in the trait could be defined on that service.
I think it would be useful to have @plach comment on this as well.
Comment #109
plachI spoke with @Berdir about this and I'm mostly +1 on #108. The main issue I had with it was the suggestion to move the trait methods to
EntityTypeBundleInfo
: ideally that's a bundle definition factory and those methods belong to an hypothetical bundle definition class.After discussing this, we agreed that we are fine with keeping the trait and the config entity definition as-is to populate the bundle info but the main API to retrieve this info should be the
EntityTypeBundleInfoInterface
provided by the service. It might make sense to add the fallback logic itself toEntityTypeBundleInfo
via protected methods though. This would allow to introduce this additions for any entity type, using our native entity bundle API, without having to rely on individual bundle config entity types and traits.As @Berdir suggested, we should validate this solution by testing it also via a test entity type and we should provide the bundle definition additions via code, so we have proof that both approaches work the same way.
The patch does not apply anymore, btw.
As a side note, we should really open a follow-up to introduce a proper bundle definition class mimicking entity type and field definitions.
Comment #110
plach+1 also on
Comment #115
claudiu.cristeaThe fallback labels are bringing a lot problems and I would advise that we don't add fallback at all. Let's break with #1850080: Entity type labels lack plurality, cannot generate UI text based on label if plural is needed, I feel that it's a wrong path for many reasons, most of them were described in the above comments. Do you need to display a singular, plural or a count label? All right, then configure one. Be explicit.
Comment #117
anmolgoyal74 CreditAttribution: anmolgoyal74 at OpenSense Labs for DrupalFit commentedComment #118
claudiu.cristeaI think I've covered #109, except the tests. #110 still not addressed.
Comment #119
claudiu.cristeaChanges made since the last MR update:
hook_entity_bundle_info_alter()
. In this case this would end up with creating confusion between, for instance, the label returned by$node_type->getSingular()
and\Drupal::service('entity_type.bundle.info')->getBundleInfo('node')['page']['label_singular']
. They might be different. The only authority of providing labels should be theentity_type.bundle.info
service.EntityTypeBundleInfo::getBundleCountLabel()
. Don't like confusions created by "magic" implicit things.node_post_update_plural_variants()
has been modernized to useConfigEntityUpdater
.hook_entity_bundle_info()
.Still to be done:
Comment #120
claudiu.cristeaAn unofficial 8.9.x patch for whom might concern.
Comment #121
claudiu.cristeaFix the 8.9.x - unofficial patch.
Comment #122
claudiu.cristeaIn the last MR update:
Still to be done:
Comment #123
claudiu.cristeaIt seems that my assumption, in #119.1 is not correct. The standard
$entity->label()
also returns the unaltered value as this test proves. So, probably is good the add the getters back.Comment #124
claudiu.cristeaPatch was wrong.
Comment #126
claudiu.cristeaIn the last MR update:
Still to be done:
Comment #127
claudiu.cristeaAlso the unofficial 8.9.x version of #126.
Comment #128
claudiu.cristeaIn the last MR update:
Still to be done:
Comment #130
claudiu.cristeaFix the unofficial 8.9.x version.. The MR to be reviewed is https://git.drupalcode.org/project/drupal/-/merge_requests/87#note_5809
Comment #131
pfrenssenFor reference, there is more information about non-English languages that have more than 2 plural formulas in comment #2765065-63: [PP-1] Allow plurals on bundle labels.
Comment #135
pfrenssenRebased on 9.4.x and opened new merge request.
Comment #136
pfrenssenHere's also the latest patch rolled for 9.3.x.
How are we supposed to handle multiple issue branches? The main branch to focus on now is
2765065-bundle-plurals-9.4.x
. Should we close the old ones?Comment #137
pfrenssenMade a merge error in the 9.3.x patch in #136. Here is a corrected version.
Comment #138
Siggy CreditAttribution: Siggy commentedFix the unofficial 8.9.x version (for 8.9.20) previous version broke at 8.9.15.
Comment #139
jonathanshawLooks like #137 needs reroll
Comment #140
karishmaamin CreditAttribution: karishmaamin at Specbee commentedRe-rolled 137 against 9.4.x. Please review
Comment #141
ranjith_kumar_k_u CreditAttribution: ranjith_kumar_k_u at Zyxware Technologies commentedFixed CS errors.
Comment #144
ajaypratapsingh CreditAttribution: ajaypratapsingh at Srijan | A Material+ Company for Drupal India Association commentedrerolled patch #130 on drupal 9.5.x
Comment #145
tvb CreditAttribution: tvb commentedComment #147
nod_Needs another reroll to fix the commit checks with a D10.1 patch as well.
Comment #151
claudiu.cristeaPostponed on #3409588: Add validation constraint to type: plural_label; remove work-around from views.field.numeric:format_plural_string
Comment #152
Wim LeersDespite this being blocked, I think this can already be reviewed. Posted some architectural/update path questions on the MR.
Comment #153
Wim LeersForgot: +1 for the principle! This is a blocker for improving usability. 👍