While I was wrong in my original post (sorry for this) I think that the signature desync with the well known gettext library it was originally inspired from (and supposedly almost identical as advertised in Drupal 6) may be confusing.

Confusing to people that are used to gettext but not Drupal, but also confusing for maintainance. If the translation system ends up being pluggable with D8MI, having signatures that differs from the most popular translation system is making potential integration with it harder for people that would do it.

I also think it's more consistent to keep the same arguments and argument count in both plural forms.

See http://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/Plura...

Because I want to be as objective as I can about this, I have also to say that they state that the english string can contain the literral "one" or "1" instead of the replacement pattern, because english has only singular form (for the "1" value for n). Considering that fact, I think that it should be documented this way into the function signature instead of giving the directive that it must contain the full string (without the @count parameter), which is not true, both will work fine in the end.

Side note: Drupal 6 and Drupal 7 signature are the same, they specify not to set the @count in the singular form, but I remember in the old days seing "1" on the screen where it was "0". It may have been fixed now.

Original post

You are using format_plural() this way:

format_plural($options['cron_limit'], '1 item per cron batch.', '@count items per cron batch.')

The second parameter is the singular form, but in some languages, 0 is a singular, in some others, it's not. What happens is that depending on the choosen plural formula, you can end up with "1 item processed" when it's in reality 0, which is a bug.

You should fix it everywhere like this:

format_plural($options['cron_limit'], '@count item per cron batch.', '@count items per cron batch.')

I may help with patches, but I can't promise you to do it. I spotted this error pretty much everywhere in the code.

Comments

Damien Tournoud’s picture

Status: Active » Closed (works as designed)

Nope, those are perfectly correct.

Note that there is an issue with automatically detected plural forms, which you are probably bumping into: #532512: Plural string storage is broken, editing UI is missing. Using potx to extract the strings and importing the translation as a .po file is the only working method for translating plural forms.

Damien Tournoud’s picture

Also, see the documentation for format_plural() for usage instruction. It is clearly specified that you should *not* use @count in the singular (or the Drupal 7 implementation of format_plural() is not even going to work).

pounard’s picture

Project: Search API » Drupal core
Issue summary: View changes

Fixed issue original post.

pounard’s picture

Title: Wrong usage of format_plural() everywhere » Wrong signature of format_plural() - desync with the original gettext it was inspired from
Version: 7.x-1.x-dev » 8.x-dev
Component: Framework » language system
Status: Closed (works as designed) » Active
Issue tags: +D8MI

@Damien Tournoud

  $args['@count'] = $count;
  if ($count == 1) {
    return t($singular, $args, $options);
  }

Drupal 7 implementation will work fine, even without respecting the documented signature. I think it should be redocumented because putting the @count in there is a good practice. EDIT: Moved details into issue description.

pounard’s picture

Category: bug » feature

Forgot to change the status, this is not a bug.

Damien Tournoud’s picture

Status: Active » Closed (works as designed)

Nope. The best practice is to not use @count in here. There is nothing wrong with that, it guarantees that the singular form and the plural form are different and it makes the English singular string nicer.

Damien Tournoud’s picture

Just for the record, gettext itself acknowledge this:

In the English singular case, the number – always 1 – can be replaced with "one":

printf (ngettext ("One file removed", "%d files removed", n), n);

pounard’s picture

Title: Wrong signature of format_plural() - desync with the original gettext it was inspired from » Not totally exact signature of format_plural() - desync with the original gettext it was inspired from
Status: Closed (works as designed) » Active

After some reading I have to agree I was partly wrong, my bad experiences were from older buggy D6 version.

But just because you I want to play with you:

It's not really a best practice at all, it's a "can do" practice. In our very own case it's exactly the same (both work fine, and the opposite would be a bug), but it's not better nor worse:

In the English singular case, the number – always 1 – can be replaced with "one"

(source).

In the end it just creates a visual argument count mismatch between multiple forms (pure syntactic sugar). People may prefer the hardcoded "1", I think that english people mostly will, while it's not that sure that every people in the world would.

Actually, I guess it's a good (not best) practice in the case you would want to write the word "one" but doesn't really have any advantages when you need to put the number 1 instead. It's a pure matter of taste (which is subjective and not subject to any technical reason).

When we browse all over the internet, most samples use %d in place of "1", and I guess it's because they use low level functions to process the pattern replacement (such as printf or sprintf or others), and probably don't want to make a case (code runtime branch) "1" -specific.

I say the function documentation is not accurate, both "1" and "@count" are definite valid forms, and that's where I was wrong in the beginning. And because both are definitely valid, and because most people seem to use the pattern replacement for "1" all over the world outside Drupal, I'd say it'd be good to provide an example using this, and telling that both forms are equivalently valid.

EDIT:

it guarantees that the singular form and the plural form are different

It doesn't matter because the plural form is just a placeholder for english plural form. The translation index is the singular form, it theoritically doesn't matter having the same string for both.

Damien Tournoud’s picture

Status: Active » Closed (works as designed)

This is not a game.

See #384866-18: Clarify documentation for format_plural() for rationale about why we need to strongly recommend not using @count.

pounard’s picture

Status: Closed (works as designed) » Active

Nothing wrong here.

sounds like a good rationale to me.

pounard’s picture

Kidding of course, but there's a real problem here, core is not handling plural as it should if it isn't working when the singular and the plural form are the same. Basically in gettext, the singular is the key for the translation, but the plural is never supposed to be, this is a flaw by design.

I'd like to have Gabor opinion about this, but this reveals a real design flaw, and I think it could be improved. I'm really looking forward to see translation backend pluggability, and this could be a blocker to have such restriction.

EDIT: It might look as if I was taking this lightly, but I'm really not. Gettext is a really mature product and I'd really like us to move forward towards at least API signature compatibility with it, because it's a well known system.

anrikun’s picture

Component: locale.module » language system

The second parameter is the singular form, but in some languages, 0 is a singular, in some others, it's not. What happens is that depending on the choosen plural formula, you can end up with "1 item processed" when it's in reality 0, which is a bug.

I agree with this, there is a bug here.
For instance, Ubercart displays "1 Item" when cart is empty and locale is French.
Why is this a feature request and not a bug?

plach’s picture

Component: language system » locale.module
Damien Tournoud’s picture

Component: language system » locale.module
Status: Active » Closed (works as designed)

@anrikun: most probably it means that the translation is wrong.

@pounard: the bug you described has been fixed in Drupal 8 already.

Just to let this to rest again: the arguments of format_plural() are the *English form*. Other languages are implementing different plural rules, and that's their problem. The arguments of format_plural() needs to be proper for English, and that's really the end of the story.

Damien Tournoud’s picture

And to conclude, there is no mismatch with the gettext library, which explicitly specifies:

In the English singular case, the number – always 1 – can be replaced with "one":

printf (ngettext ("One file removed", "%d files removed", n), n);

(source)

anrikun’s picture

Please Damien, explain me how this is supposed to work:
According to your source, in French, Plural-Forms is defined as follows:

Two forms, singular used for zero and one
Exceptional case in the language family. The header entry would be:

Plural-Forms: nplurals=2; plural=n>1;

Languages with this property include:

Romanic family
Brazilian Portuguese, French

If singular is used for zero, then obviously "1 fichier supprimé" will be displayed for zero, instead of "0 fichier supprimé"
If there is no bug, how are we supposed to handle zero in French?

Is comment at http://localize.drupal.org/node/4734#comment-32254 the right solution?

Damien Tournoud’s picture

@anrikun: the lists of plural forms are independent between languages. Form 0 in French isn't the translation of Form 0 in English.

See #410272-5: Localized read count for threads shows "1 read" for any number of reads ending with 1 for possible causes for three possible causes of your particular issue. Most likely you are translating through the UI, and are bumping into a bug in Drupal 7 where plural forms are not auto-detected properly. Use a potx and a PO editor instead.

Damien Tournoud’s picture

Of course, each language needs to follow its own plural rules, or it's never going to work. French has two plural forms, and they both needs the @count placeholder.

Those English forms:

  • 1 item
  • @count items

Need to be translated in French (assuming a plural formula of nplurals=2; plural=n>1;) into:

  • @count élément
  • @count éléments

If you want more control over the "count = 0" and the "count = 1" form, use a different plural formula.

anrikun’s picture

All right, it's all clear now!
Thank you for this useful information Damien!

anrikun’s picture

Issue summary: View changes

Added more precisions