4.6.x common.inc format_plural($count, $singular, $plural)
4.7.x common.inc format_plural($count, $singular, $plural)
5.x common.inc format_plural($count, $singular, $plural)
6.x common.inc format_plural($count, $singular, $plural, $args = array(), $langcode = NULL)
7.x common.inc format_plural($count, $singular, $plural, array $args = array(), array $options = array())

Formats a string containing a count of items.

This function ensures that the string is pluralized correctly. Since t() is called by this function, make sure not to pass already-localized strings to it.

For example:

$output = format_plural($node->comment_count, '1 comment', '@count comments');

Example with additional replacements:

$output = format_plural($update_count, 'Changed the content type of 1 post from %old-type to %new-type.', 'Changed the content type of @count posts from %old-type to %new-type.', array(
  '%old-type' => $info->old_type,
  '%new-type' => $info->new_type,


$count: The item count to display.

$singular: The string for the singular case. Make sure it is clear this is singular, to ease translation (e.g. use "1 new comment" instead of "1 new"). Do not use @count in the singular string.

$plural: The string for the plural case. Make sure it is clear this is plural, to ease translation. Use @count in place of the item count, as in "@count new comments".

$args: An associative array of replacements to make after translation. Instances of any key in this array are replaced with the corresponding value. Based on the first character of the key, the value is escaped and/or themed. See format_string(). Note that you do not need to include @count in this array; this replacement is done automatically for the plural case.

$options: An associative array of additional options. See t() for allowed keys.

Return value

A translated string.

See also



Related topics

44 calls to format_plural()
aggregator_view in modules/aggregator/aggregator.admin.inc
Displays the aggregator administration page.
CommentHelperCase::performCommentOperation in modules/comment/comment.test
Perform the specified operation on the specified comment.
comment_multiple_delete_confirm_submit in modules/comment/comment.admin.inc
Process comment_multiple_delete_confirm form submissions.
comment_node_search_result in modules/comment/comment.module
Implements hook_node_search_result().
DrupalWebTestCase::tearDown in modules/simpletest/drupal_web_test_case.php
Delete created files and temporary files directory, delete the tables created by setUp(), and reset the database prefix.

... See full list


includes/common.inc, line 1859
Common functions that many Drupal modules will need to reference.


function format_plural($count, $singular, $plural, array $args = array(), array $options = array()) {
  $args['@count'] = $count;
  if ($count == 1) {
    return t($singular, $args, $options);

  // Get the plural index through the gettext formula.
  $index = function_exists('locale_get_plural') ? locale_get_plural($count, isset($options['langcode']) ? $options['langcode'] : NULL) : -1;

  // If the index cannot be computed, use the plural as a fallback (which
  // allows for most flexiblity with the replaceable @count value).
  if ($index < 0) {
    return t($plural, $args, $options);
  else {
    switch ($index) {
      case "0":
        return t($singular, $args, $options);
      case "1":
        return t($plural, $args, $options);
        $args['@count[' . $index . ']'] = $count;
        return t(strtr($plural, array(
          '@count' => '@count[' . $index . ']',
        )), $args, $options);


Vlad Stratulat’s picture

All guides describe to use this function like that:

  format_plural($nodes, '1 node', '@count nodes');

This is wrong for languages which using singular method for numbers like 21, 31 and so on.

Let's take module CAPTCHA for example. In "Status report" this module show how many submissions were blocked. If we will translate CAPTCHA into Russian for example (my case), then whenever we will have 21, 51, 141 (and so on) blocked submissions, CAPTCHA would report that only 1 post submission was blocked. This is not right.

So i have a suggestion to write singular string with @count prefix instead of digit 1. The code would be following:

  format_plural($nodes, '@count node', '@count nodes');

Please share this information with everyone!

SebCorbin’s picture

If you write your translation with @count it will be replaced in singural AND in plural

msgid "1 sheep"
msgid_plural "@count sheep"
msgstr[0] "@count (russian word)"
msgstr[1] "@count (russian words)"

Translators must be careful about this...

Damien Tournoud’s picture

This is the expected usage:

  format_plural($nodes, '1 node', '@count nodes');

The plural formula of the destination language is going to take care of multiple plural forms. The best practice is to not have @count in the singular form.

manarth’s picture

In English (and, generally, Romance languages), 1 is singular, and singular always implies 1. 0, and n>=2 are plural.

This isn't necessarily the case for other languages.

In Russian, "If the number is 1, or the number ends in the word 'один' (example: 1, 21, 61) (but not 11), then you should use the case (singular)" - http://www.russianlessons.net/lessons/lesson11_main.php

This means that we cannot rely on the singular form having '1' of something: 21 could also select singular. This suggests to me that we should use @count in both the singular and plural versions:

format_plural($nodes, '@count node', '@count nodes');

Should we therefore change the documentation to reflect this practice, or have I misunderstood something about how the pluralisation and translation work together?

cosolom’s picture

No. You need write

format_plural($nodes, '1 node', '@count nodes');

Then go to translations page (admin/config/regional/translate/translate), find your strings and translate it. For russian it will be:

1 node => 1 материал
@count nodes => @count материала
@count[2] nodes => @count[2] материалов

jurcello’s picture

For french this fails for 0, because it gets the singular than. That's why I used @count also in the singular form.

kappaluppa’s picture

I needed to use this in field.tpl and also wanted to have an option for zero comments. With the help of some #drupal-support IRC buds, this works for me (the link is to an anchor tag down by the comments section of the page):

if ($element['#object']->comment_count == 0) { 
    $output = t('Add a comment'); } 
    else { 
    $output = format_plural($element['#object']->comment_count, '1 Comment', '@count Comments'); 
     print '<a href="#comments">' . $output . '</a>';
jim005’s picture

my working code... in .tpl with the right translation for "Add new comment" and a other way to create link to comment div anchors. Hope that can help someone.

if ($node->comment_count == 0) { 
	$comment_text_link = t('Add new comment'); } 
else { 
	$comment_text_link = format_plural($node->comment_count, '1 ' . t('comment'), '@count ' . t('comments'));
print l($comment_text_link, $_GET['q'], array('fragment' => 'comments')); 
Damien Tournoud’s picture

This is wrong. You want:

$comment_text_link = format_plural($node->comment_count, '1 comment', '@count comments');

format_plural() takes care of both the pluralization and the translation.

rbrownell’s picture

Here is just some sample code that I figured out. Hopefully it will benefit someone someday.

print format_plural(count($content['field_price']['#items']), 'Price', 'Prices');

This prints Price or Prices based on the number of items in a Field Collection. I had to include the PHP Count function because Drupal's format_plural wouldn't work without it.

caspervoogt’s picture

the singular and plural arguments seem to only accept plain text - no HTML. In some cases it would be handy to have output like this:


.. but the function won't accept HTML.

izus’s picture

In Drupal 8 this is now \Drupal::translation()->formatPlural

See the change notice : https://www.drupal.org/node/2173787

AlexBorsody’s picture

Yes there should be docs here for 8 https://www.drupal.org/developing/api/8/localization take this example

$error_text = \Drupal::translation()->formatPlural($free_places,
						  'Too many people for this campground. There is 1 available spot for this site on @date',
						  'Too many people for this campground. There are @count available spots for this site on @date',
						  ['@date' => $date]