Make WordPress Core

Opened 2 years ago

Last modified 2 months ago

#57588 new defect (bug)

The picking of plural form #0 is hard-coded for singular strings

Reported by: jaanise's profile jaanise Owned by:
Milestone: Awaiting Review Priority: normal
Severity: minor Version: 6.1
Component: I18N Keywords: 2nd-opinion close
Focuses: Cc:

Description

If a translation with plural forms exist, but a simple (without count) message is requested, the plural form with index 0 is returned regardless of the MO file's Plural-Forms definition.

For example, if there is a PO file with the following Plural-Forms:

"Plural-Forms: nplurals=3; plural=n%10==0||( n%100 >= 11 && n%100<=19)? 0 :(n%10==1 && n%100!=11 ? 1 : 2);\n"

(You can see that one item would be in plural form ID=1, not ID=0.)

And this translation entry:

msgid "Product"
msgid_plural "Products"
msgstr[0] "Prod 0,10,11"
msgstr[1] "Prod 1,21,31"
msgstr[2] "Prod 2,3,4"

And you have this PHP code:

<?php
  esc_html_e('Product', 'my_payment');
  echo _n('Product', 'Product', 2,'my_payment');
  echo _n('Product', 'Product', 1,'my_payment');
?>

You will get this output:

Prod 0,10,11
Prod 2,3,4
Prod 1,21,31

As you can see, the first message is incorrectly selected for count 1.
The following ones are correctly selected for counts 2 and 1.

The selection of the hardcoded plural form ID=0 happens here: https://core.trac.wordpress.org/browser/trunk/src/wp-includes/pomo/translations.php?rev=54469#L108

If a not-counted message is requested and the available translation turns out to be count-dependable, translate should probably either forward the call to translate_plural passing count 1, or return the untranslated fallback or an empty string (with a notice) if this is considered as a non-existing translation.

Although asking for a not-counted string but having count-dependable translations is not a correct situation in itself, it can easily occur also due sloppy programming in third party themes or plugins, or maybe occur during changes to translation files or translatable strings.

Change History (3)

#1 @swissspidy
2 months ago

  • Focuses template removed
  • Keywords 2nd-opinion close added

Although asking for a not-counted string but having count-dependable translations is not a correct situation in itself, it can easily occur also due sloppy programming in third party themes or plugins, or maybe occur during changes to translation files or translatable strings.

That is indeed true. I have even seen this in big plugins such as WooCommerce.

If a not-counted message is requested and the available translation turns out to be count-dependable, translate should probably either forward the call to translate_plural passing count 1, or return the untranslated fallback or an empty string (with a notice) if this is considered as a non-existing translation.

Because of the above, making this change sounds like a breaking change to me at this point, so I am inclined to close this issue as a wontfix.

Curious to hear other thoughts though.

#2 @jaanise
2 months ago

Returning translation #0 is just wrong. If the code asks for not-counted string, I would guess it's almost always intended to be for count "1", not for the count that happens to be with index #0 in the PO file definition. Different languages may have the count "1" version under different indexes, even the same language may have it under different indexes in different PO files (defined by different Plural-forms) (which is not a good and widespread practice, but it is possible, it is allowed by the format, and, for example, there are two different Plural-form definitions actually used in Latvian translations).

Using explicitly count "1" would not break the result in most cases, most people won't notice anything (including the sloppy programmers and those who test their plugins only in English, for example) but it would fix/patch the sloppy programming cases for other languages and cases where count "1" is not under index #0.

Last edited 2 months ago by jaanise (previous) (diff)

#3 @swissspidy
2 months ago

Related: [57513]

I'm open to considering it if it doesn't cause any back compat issues. Maybe a (failing) test case showing the issue would help.

Note: See TracTickets for help on using tickets.