Some pages might want to show lists of books, or blog entries, etc. We have a name for each node, but a plural equivalent. These plurals ought to be declared in english in the module, and available for translation as usual. Or perhaps there is some other better way to do this.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

dado’s picture

I agree. This is important for usability for my node-to-node associations module. Also, perhaps the
hook_node_name
function should take a second argument which specifies "singular" [default] or "plural".

Also, I guess flexinode would have to support this w/ an additional field on its node types config form?

chx’s picture

hook_node_name is ancient past :) however it is entirely possible to add a 'plural' key to hook_node_info.

killes@www.drop.org’s picture

I agree with chx. The question is: Is one plural form enough for every language. Or do certain languages need more than one?

moshe weitzman’s picture

This may not handle languages with plural form properly, but I propose the pattern below. Note the format_plural() use ... Comments welcome


function blog_node_info() {
  return array('blog' => array('name' => format_plural(%count, 'blog entry', 'blog entries'), 'base' => 'blog'));
}

pwolanin’s picture

I don't quite understand how this would work within a module- would this require changes to existing code? How about a something like this:

function blog_node_info($count=-1) {
  if ($count < 0) {
    return array('blog' => array('name' => t('blog entry'), 'base' => 'blog'));
  }
  else {
    return array('blog' => array('name' => format_plural($count, 'blog entry', 'blog entries'), 'base' => 'blog'));
  }
}
moshe weitzman’s picture

format_plural already handles the switch that you are introducing. see its definition

pwolanin’s picture

Title: Node modules should declarare a plural form of their name » Node modules should declare a plural form of their name

Ok, I'm staring at http://api.drupal.org/api/4.7/function/format_plural

Here are some uses of it in existing modules:

poll.module:
format_plural($node->votes, '1 vote', '%count votes')
comment.module:
format_plural($all, '1 comment', '%count comments')

Where do you envision this new feature of hook_node_info being used?

Maybe the code needs to be something like:

function blog_node_info() {
  return array('blog' => array(('name' => t('blog entry'), 'base' => 'blog', 'singular' => '1 blog entry', 'plural' => '%count blog entries');  
}

And then there could be an additional function in node.module that would return a translated string for an enumerated number of nodes of type. This could follow the pattern of node_get_types(), node_get_name($node), etc. that use the _node_names($op = '', $node = NULL). So, essentially, this would require an additional two $op values for _node_names.

function node_get_enumerated_names($count, $node){
  return format_plural($count,_node_names('singular',$node),_node_names('plural',$node));
}

and where we change the latter part of _node_names to be:

  switch ($op) {
    case 'base':
      return $node_names[$type]['base'];
    case 'list':
      return $node_list;
    case 'name':
      return $node_list[$type];
    case 'singular':
      return $node_names[$type]['singular'];
    case 'plural':
      return $node_names[$type]['plural'];
  }

(of course, putting in some code to take care of modules that don't define 'singular' or 'plural' might be a good idea too)

moshe weitzman’s picture

Oops. My pseudocode was unclear. I added a param to the function. Hopefully this is clear:


function blog_node_info($count = 1) {
  return array('blog' => array('name' => format_plural($count, 'blog entry', 'blog entries'), 'base' => 'blog'));
}

pwolanin’s picture

Will your prototype work as a drop-in replacement for the current function? One does not always want an enumerated name. For example, the list of node types at /node/add. I think your code would give mean I'd see the option to create "1 book page" or "1 forum topic".

Also, the function _node_names() caches the results of calls to hook_node_info in a static array.

killes@www.drop.org’s picture

The problem with format_plural is that it requires the %count parameter in order to work for multiple plural forms that some languages have. However, we'd don't want the count parameter in the final output.

An idea would be to do the following:

function blog_node_info($count = -1) {
  if ($count < 0) {
    return array('blog' => array('name' => t('blog entry'), 'base' => 'blog'));
  }
  else {
    return array('blog' => array('name' => strtr(format_plural($count, 'blog entry', '%count blog entries'), $count, ''), 'base' => 'blog'));
  }
}

This would remove the number from the output.

pwolanin’s picture

Are there any modules now that directly use hook_node_info()? In node.module, this hook is used only to get the information into the _node_names() function and through that to the various "public" functions like node_get_name().

No where in the core modules (that I can find) is hook_node_info() invoked except in _node_names(). In contrast, node_get_name() is frequently used (e.g. taxonomy.module, tracker.module, etc).

The scheme I suggest in #7 essentially follows the logic currently used in node.module and extends it in a way that I think is more consistent with the current API and usage.

pwolanin’s picture

Status: Active » Needs review
FileSize
4.07 KB

patch attached that exactly implements my suggestion above. Works fine with Drupal CVS, PHP 4.4.2, MySQL 4.1.19.

The function name "node_get_enumerated_names" seems a little too long/inobvious. Any other suggestions?

simple test code:

<h2>My site has the following content:</h2>

<?php
$types = node_get_types();
foreach ($types as $type => $name ){
  $result= db_query("SELECT n.nid FROM {node} n WHERE n.type = '%s'",$type);
  $count=db_num_rows($result); 
  print node_get_enumerated_names($count, $type)."<br />";
}
?>
pwolanin’s picture

Or, as an option to avoid adding another "public" function to node.module, one could use the rest of my patch and rewrite node_get_name as:

function node_get_name($node, $count = -1) {
  if ($count < 0) {
    return _node_names('name', $node);
  }
  else {
    return format_plural($count,_node_names('singular',$node),_node_names('plural',$node));
  }
} 

Gábor Hojtsy’s picture

I was already in need of this functionality before on a Hungarian site, and solved it with a hack, so I would prefer a nice solution myself too :) Looked at the patch in #12.

First I would prefer not adding another function, but modifying node_get_name() as showed in #13. Otherwise I have a hard time thinking of a better solution. The node_name() hook should be the place to specify this piece, but this information is cached, and plurals could end up in any number of strings depending on the language, so the $count parameter is needed to identify the right translation in the system (and so the number should be in the output, as the translated version is only valid for that exact number).

There is no general plural translation of a string, which could be used, or at least not one we can get through format_plural(). If you also need a generic plural version, stripping the number off is not a good solution, but another field should be introduced which provides the cacheable t('stories'), t('book pages'), t('forum topics') generic plural version, for wihich the translators need to come up with some translation.

Look at the Polish translation for example, which has three plural versions, with a quite complex formula: Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);

msgid "1 new comment"
msgid_plural "%count new comments"
msgstr[0] "1 nowa odpowiedź"
msgstr[1] "%count nowe odpowiedzi"
msgstr[2] "%count nowych odpowiedzi"

BTW the -1 special parameter is not used in Drupal, but NULL should be used for testing a missing parameter:

function node_get_name($node, $count = NULL) {
  if (!isset($count)) {
    return _node_names('name', $node);
  }
  else {
    return format_plural($count,_node_names('singular',$node),_node_names('plural',$node));
  }
} 
Gábor Hojtsy’s picture

Status: Needs review » Needs work
moshe weitzman’s picture

@Goba - i see that you are not satisfied with the last patch here, but can you suggest an alternative? i could not work out a proposal from your post.

pwolanin’s picture

@moshe - I took the only essential criticism/suggestion as replacing the -1 with NULL, which is easily done.

Gábor Hojtsy’s picture

I also posed a question, whether you need general plural versions t('stories'), t('book pages') and such without numbers. The current patch is only useable if you intend to have a specific number with the pluraled node name. Note that even if you have a generic plural version, you should not use it in sentences, like t('update these %nodenames', array('%nodenames', t('stories)), since different languages have different versions of the plural word depending on what sentence and position it gets into.

pwolanin’s picture

@Goba - my use case for this patch was primalily for lists/tables of conent were a specific number would be indicated.

Gábor Hojtsy’s picture

@pwolanin: OK, I think after fixing the -1 to NULL issue I noted this seems to be a good solution for the problem. Maybe this should be coupled with a generic plural form specification too, where nodes can specify t('stories') and such. I mean another key to node_info (wrapped only for easy reading):

return array(
  'story' => array('name' => t('story'), 'base' => 'story',
  'plural-1' => '1 story', 'plural-count' => '%count stories', 'plural-generic' => t('stories'))
);
pwolanin’s picture

Status: Needs work » Needs review
FileSize
5.46 KB

Patch updated for latest HEAD, and using node_get_name() as the interface as per above, modified so $count=NULL is the default 2nd parameter.

sample code:

$types = node_get_types();
foreach ($types as $type => $name ){
  $result= db_query("SELECT n.nid FROM {node} n WHERE n.type = '%s'",$type);
  $count=db_num_rows($result); 
  print node_get_name($type,$count)."<br />";
}
Jaza’s picture

The CCK in core patch will have a big effect on the nature of this patch, once it gets committed. Personally, I would definitely like to see this patch get in after the CCK patch has landed.

I think that we should be adding 'name_plural', as an element in the array returned by hook_node_info(), and as an extra field in the new 'node_type' DB table that will be introduced with the CCK patch. This will mean that modules will be able to access the singular and the plural name of a node type very easily, using code such as this:

$type = node_get_types('type', $node);
$msg = t('You are looking at %count %type nodes right now.', 
array('%count' => $count, '%type' => theme('placeholder', 
format_plural($count, $type->name, $type->name_plural))));

format_plural() should not be used in hook_node_info or in node_get_types(), IMO. Modules can make use of this function directly when they wish to actually prepare text for presentation, if need be. What they should be provided with is simply the raw singular and plural strings of the node type name.

Also note that with the CCK patch going in, translation of (singular or plural) node type names will not be an issue, as the names of all node types will be editable by the site admin.

pwolanin’s picture

I haven't been following the CCK patch closely- this patch can certainly be postponed. I assume that module-defined node types will still be supported?

Also, part of my goal with the way I structured the patch above was to minimize the effect on the API.

Gábor Hojtsy’s picture

Jaza, your expectations on format_plural() usage are not right. Format_plural does return a string with a number in it, which is put in place where it is sufficient in the given language (maybe at the beginning, middle or end). This also means that format_plural() is used with a first param which contains '1 thing' and a second param which contains '%count things'. The node name is not directly reuseable here.

// ! Node_get_types accepts no parameters, and returns an array, not object
$type = node_get_types('type', $node);
// ! Count should be generated into the string by format_plural.
$msg = t('You are looking at %count %type nodes right now.', 
array('%count' => $count, '%type' => theme('placeholder', 
format_plural($count, $type->name, $type->name_plural))));

Maybe you can provide a better usage example, which helps us understand your intentions?

pwolanin’s picture

Ok, I'm a little puzzled now as to how to proceed now that the new content system is in core.

Seems like this would require 2 (or 3) additional columns in the node_type table?

Also, this function seems to need work:

http://api.drupal.org/api/HEAD/function/_node_types_build

Unless I'm wrong, a module-defined type will never have its machine-readable type changed, right? So a lot of this seems redundent and dating to before the story and page modules were removed as separate entities.

pwolanin’s picture

Status: Needs review » Needs work

setting back to "needs work". I think both this patch, and some of the related node functions.

Jaza’s picture

@pwolanin:

Unless I'm wrong, a module-defined type will never have its machine-readable type changed, right?

The CCK patch made it so that module-defined types can't have their machine-readable type name changed by default. However, such types can still override the default behaviour, and can allow their machine-readable type name to be changed. The stuff in _node_types_build() remains in there to support that.

Anyway, this is off-topic - if you find bugs with the new node type system, please file them as separate issues. ;-)

pwolanin’s picture

Ok, fundamentally I think after the CCK patch having plural verions defined requires extra node_type DB columns since any custom or user-modified type must be able to have the user define the plural forms as well. Is this correct?

moshe weitzman’s picture

yes, i would think so since simple node types are purely defined in the database ... i haven't looked much into new node system though

moshe weitzman’s picture

Version: x.y.z » 6.x-dev

@pwolanin - any chance you will get back to this?

@gabor - has the new language system changed anything relevant to this patch? i don't think so, but just checking.

Gábor Hojtsy’s picture

Nothing changed in core to make this either easier or harder.

pwolanin’s picture

I'll take another look

chx’s picture

Version: 6.x-dev » 7.x-dev
Priority: Normal » Critical
moshe weitzman’s picture

bump. anyone?

pwolanin’s picture

i think this needs some comment from Gabor - any user-defined types would require i18n for translation, right? Is a single plural form sufficient?

moshe weitzman’s picture

Title: Node modules should declare a plural form of their name » Content types should declare a plural form of their name

Update title for the modern Drupal. Yes, I think we can assume that a number is going along with the plural name.

Owen Barton’s picture

FileSize
5.05 KB

Adding an older patch I wrote for a (mostly duplicate) issue at #300801: Collect the plural name of content types. Patch needs updating.

mitchell’s picture

subscribe

moshe weitzman’s picture

Version: 7.x-dev » 8.x-dev
Priority: Critical » Normal
effulgentsia’s picture

Subscribe. Would be really nice for Views / SimpleViews, so you could build UIs that say something like "Show [published articles] tagged with [term1] sorted by [newest first]", where each bracket represents a drop-down. I guess, currently, our guidelines dictate that it would need to be "Show [published article content] tagged with [term1] sorted by [newest first]", which isn't quite as nice.

dboulet’s picture

To add another use case: I am needing this to build a Wordpress-type content overview dashboard block that displays "5 articles, 6 basic pages, 2 webforms, ...".

eaton’s picture

Tagging this as an issue for the Snowman project for D8. The ability to cleanly generate things like listing pages, blocks, and other UI help for content types relies on having sensible pluralization.

Bojhan’s picture

lala

Gábor Hojtsy’s picture

Unfortunately, depending on the language of the site, the "a plural" form would not be enough. Many languages define multiple plural forms depending on the number of items. You can look for some examples in the Polish Drupal translation let's say: http://localize.drupal.org/translate/languages/pl/translate?project=&sta...

You'll find pieces like "1 invitation sent" / "@count invitations sent" have different translations depending on the number of @count:

  • Wysłano 1 zaproszenie.
  • Wysłano @count zaproszenia.
  • Wysłano @count zaproszeń.

So for many languages, there is not one but multiple plural forms for a singular form and which one to use depends on the number of items. (When the number of items is available). We should only be able to get away with one plural vatiant input for this, if we never use it at places where the number of items is known, which will be very tempting I think... (such as "@count $nodes were deleted", where $nodes would be the plural version of the type).

You can find rules for how plurals are selected from multiple variants for different languages at http://translate.sourceforge.net/wiki/l10n/pluralforms. You'll see Irish has 5 different variants, Arabic has 6 (all include the singular form).

eaton’s picture

So for many languages, there is not one but multiple plural forms for a singular form and which one to use depends on the number of items. (When the number of items is available). We should only be able to get away with one plural vatiant input for this, if we never use it at places where the number of items is known, which will be very tempting I think... (such as "@count $nodes were deleted", where $nodes would be the plural version of the type).

Just out of curiosity (and because I'm shameless in the particular use case I'm thinking of this for), would text like "Recent articles" be affected by the problems you describe? Or is it just in places where there is a discrete number of things being referred to?

Gábor Hojtsy’s picture

In other words, the number of input fields and the rules of which value to use should "ideally" be language dependent on the node type configuration then. If you have an Irish site, you'd have 4 plural fields (on top of the 1 singular) and the system would know the rules to use for them when the data is requested. The "language the site is in", "how many fields are needed" and "what rules to follow to pick the right one" are all data managed by locale module, and currently all configuration is assumed to be in the default language (language_default()). If your default language is not English, we can assume you have locale module enabled practically (you probably also use interface translation), in which case all this data is available to Drupal. However, this is user configuration and not to be stored in the interface localization database. Our discussion above in 2006 about using format_plural() dated back to when node types were defined by hooks, not by a UI, so you could wire in the English defaults to your code.

Now this issue is about providing a UI for something that potentially needs to be different based on the configuration language (site default language) being used. Date formats have a one-off special implementation for this in Drupal 7, but no other configuration component has similar support. I believe instead of coming up with yet another one-off solution here, it would like the best idea to keep this on hold until we have the Drupal 8 configuration management storage and retrieval system, which should support variants based on language or other factors natively, making one-off hacks unnecessary.

Gábor Hojtsy’s picture

@eaton: to my best knowledge it is problematic at places only where we know the number of things referred to. And I can easily see this can propel into uses in those areas after it lands :|

eaton’s picture

@eaton: to my best knowledge it is problematic at places only where we know the number of things referred to. And I can easily see this can propel into uses in those areas after it lands :|

Sigh.

Yeah, I can definitely see that being a problem... Once the plural form exists, it'd probably be impossible to keep people from misusing it unknowingly. On the other hand, is it possible to construct reasonably correct grammar using the current system? The UX implications of always saying, "article content" instead of "articles" makes my heart heavy. Hrm.

langworthy’s picture

sub

andypost’s picture

Issue tags: +D8MI

Suppose this should be related to CMI translation. For D8 we have improved plural storage but node-name is out of scope of interface translation

tkoleary’s picture

How has plural storage been improved in D8?.

Gábor Hojtsy’s picture

@tkoleary: I don't think content types are converted yet to CMI (the new D8 config system) and therefore no translation support there yet either. The translation support built for CMI is not ready either (in part waiting on conversions and waiting on reviews for several important components).

mitchell’s picture

Title: Content types should declare a plural form of their name » Entity types should declare a plural form of their name
Component: node system » entity system
Status: Needs work » Active
bojanz’s picture

I've posted a lengthy proposal at https://drupal.org/node/1850080#comment-7541435
The point of it is that we also need a new singular label.

amateescu’s picture

Title: Entity types should declare a plural form of their name » Entity bundles should declare a plural form of their label

The title change in #53 was incorrect, this issue is dealing with bundle labels, not entity type labels. So #1850080: Entity type labels lack plurality, cannot generate UI text based on label if plural is needed is definitely related, but not a duplicate :)

mitokens’s picture

moshe weitzman’s picture

jhedstrom’s picture

Version: 8.0.x-dev » 8.1.x-dev

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

moshe weitzman’s picture

Praise the Drop. This is finally partially Fixed, after 11 years. See https://www.drupal.org/node/2689949. Now we just need plual labels for bundles.

amateescu’s picture

Status: Active » Closed (fixed)

Plural labels are added to all core entity types (including those that act as bundles) in #2702799: [meta] Add plural labels to core entity types, so we can finally close this now!

claudiu.cristea’s picture

Sorry to add this question here but I cannot find the right issue. Is there an issue for adding plural label to each bundle?

claudiu.cristea’s picture

Status: Closed (fixed) » Needs work

I don't think this was fixed. This is not the same as #1850080: Entity type labels lack plurality, cannot generate UI text based on label if plural is needed. That one provided "content type" > "content types". We need: "page" > "pages", "article" > "articles". But from #1850080: Entity type labels lack plurality, cannot generate UI text based on label if plural is needed I would replicate the plural fields: label_plural, label_count (singular, plural). All these new properties will be stored in the node-type (and vocabulary?) entity and will be exposed through UI.

I cannot figure out how the plural will be stored in the entity to be fully translatable given there are languages with >1 plurals.

Gábor Hojtsy’s picture

EntityType::getCountLabel() introduced there would get you the right placeholdered value for a given number in the current interface language. Is that what you are looking for?

Gábor Hojtsy’s picture

BTW I got examples in IRC and indeed, this is not entirely resolved for user definable bundles, where the plural variants would need to be entered.

claudiu.cristea’s picture

Status: Needs work » Closed (duplicate)

Discussed with @catch on IRC to close this one in favour of #2765065: [PP-1] Allow plurals on bundle labels.