WordPress.org

Make WordPress Core

Opened 5 years ago

Last modified 11 months ago

#34308 closed enhancement

The _n*() functions don't cater for a string that represents exactly one item — at Version 1

Reported by: johnbillion Owned by:
Milestone: Priority: normal
Severity: normal Version:
Component: I18N Keywords: dev-feedback 2nd-opinion
Focuses: Cc:

Description (last modified by johnbillion)

The first and second parameters of _n() and _n_noop() are sometimes (incorrectly) thought to represent one item and more than one item. They actually represent the singular form and the plural form, and in languages that have complex plural structures the singular form can be used for numbers such as 21 and 31, not just 1.

Recent tickets concerning this: #28502, #33239, #34127, #34307.

The solution to requiring a string to represent exactly one item and another string to represent multiple items is usually to use some simple logic:

if ( 1 === $number ) {
  _e( 'Item updated' );
} else {
  printf( _n( '%s item updated', '%s items updated', $number ), number_format_i18n( $number ) );
}

This is fine in most cases, however a problem arises when you want to register strings for translation in advance of knowing the number. For this, _n_noop() is used, but in the example above we'd also need to use __() to register the string which represents exactly one item.

While working on #32532, I came across a situation that would benefit from the introduction of a variant of _n_noop() which also caters for a string that represents exactly one item.

In order to allow bulk_post_updated_messages to be provided in the post type labels array, the messages need to use _n_noop() as they're registered in advance of knowing the number. Unfortunately, the locked message is the ugly duckling here and also requires a string that represents exactly one item, in addition to the nooped singular and plural forms.

This means that either a new bulk message needs to be introduced into the array (ugh), or the value of the message needs to be an array containing two items: the 'one item' string, and the nooped singular and plural forms. Both of these options turn this otherwise peachy array of nooped labels into a mess.

The introduction of a function like _n_noop() but which also supports a string that represents exactly one item would allow us to do this:

array(
	'updated'   => _n_noop( '%s post updated.', '%s posts updated.' ),
	'locked'    => _XYZ_noop(
		'1 post not updated, somebody is editing it.',
		'%s post not updated, somebody is editing it.',
		'%s posts not updated, somebody is editing them.' )
	),
	'deleted'   => _n_noop( '%s post permanently deleted.', '%s posts permanently deleted.' ),
	'trashed'   => _n_noop( '%s post moved to the Trash.', '%s posts moved to the Trash.' ),
	'untrashed' => _n_noop( '%s post restored from the Trash.', '%s posts restored from the Trash.' ),
);

The translate_nooped_plural() function could be altered to support a $nooped_plural array which also contains an element representing exactly one item, return it if so, and return the singular form if not.

So, does this warrant the introduction of another l10n function?

Change History (1)

#1 @johnbillion
5 years ago

  • Description modified (diff)
Note: See TracTickets for help on using tickets.