TGMPA / TGM-Plugin-Activation

TGM Plugin Activation is a PHP library that allows you to easily require or recommend plugins for your WordPress themes (and plugins). It allows your users to install, update and even automatically activate plugins in singular or bulk fashion using native WordPress classes, functions and interfaces. You can reference bundled plugins, plugins from the WordPress Plugin Repository or even plugins hosted elsewhere on the internet.
http://tgmpluginactivation.com/
GNU General Public License v2.0
1.76k stars 431 forks source link

Incorrect use of _n() in several places #747

Open tobifjellner opened 6 years ago

tobifjellner commented 6 years ago

Some languages have very tricky ways of building correct phrases when you're counting something in the phrase. For instance, depending on the number, Russian uses three different formats in a phrase. If you have the following pair of strings in your code: One girl is waiting at the stairs/%d girls are waiting at the stairs then the Russian translation will consist of three translations. The first one will be used for 1, 21, 31, 41, 51, 61... girls The second one will be used for 2, 3, 4, 22, 23, 24, 32, 33, 34, 42, 43, 44 girls and the third one will be used for all other numbers. (5-20, 25-30, 35-40...)

Some languages have even more complicated schemes and will have 5-6 different translated strings for every occurrence of _n().

For this to be meaningful, the number itself needs to be included in the phrase, like this: The following 21 plugins have been updated: (Note that in this case Russian will use singular!)

If you just want to split between singular and plural but there is no need to include the number, then you should not use _n(), but rather treat this as two separate phrases:

The following plugin was updated and The following plugins were updated (for n > 1)

I'd recommend this latter approach for most of the cases where :n() is used in TGMPA

SergeyBiryukov commented 3 years ago

Just adding some context that might help unblock the issue :)

Technically _n() can handle this use case too, but only if we use a custom Plural-Forms expression that would deviate from the one recommended on gnu.org:

Three forms, special cases for numbers ending in 1 and 2, 3, 4, except those ending in 1[1-4] The header entry would look like this:

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

Languages with this property include: Slavic family Russian, Ukrainian, Belarusian, Serbian, Croatian

We'd have to add a fourth form for single case specifically, which is not really feasible for a few reasons.

Similar issues were fixed in WordPress core a few years ago, see these changesets:

and these comments for more context:

There is now a note for this in the plugin i18n handbook that should hopefully help avoid any future confusion:

Note that some languages use the singular form for other numbers (e.g. 21, 31 and so on, much like ’21st’, ’31st’ in English). If you would like to special case the singular, check for it specifically:

if ( 1 === $count ) {
    printf( esc_html__( 'Last thing!', 'my-text-domain' ), $count );
} else {
    printf( esc_html( _n( '%d thing.', '%d things.', $count, 'my-text-domain' ) ), $count );
}