Singular or Plural setting to a variable. PHP
Asked Answered
F

12

7

There are a lot of questions explaining how to echo a singular or plural variable, but none answer my question as to how one sets a variable to contain said singular or plural value.

I would have thought it would work as follows:

$bottom="You have favourited <strong>$count</strong> " . $count == 1 ? 'user':'users';

This however does not work.

Can someone advise how I achieve the above?

Filterable answered 8/10, 2012 at 17:45 Comment(5)
Explain the outcome a bit more detailed than "it does not work".Umiak
possible duplicate of Ternary operator and string concatenation quirk?Umiak
mario, I believe his problem is $bottom is always equal to only 'users' regardless of the ternary operation and concatenationCaldarium
This link contains the most usable function i could find kavoir.com/2011/04/…Timoteo
Symfony now offers a the Inflector component converts English words between their singular and plural forms. symfony.com/doc/master/components/inflector.htmlBarbary
C
6

This will solve your issue, thanks to mario and Ternary operator and string concatenation quirk?

$bottom = "You have favourited <strong>$count</strong> " . ($count == 1 ? 'user':'users');
Caldarium answered 8/10, 2012 at 17:53 Comment(0)
B
39

You can try this function I wrote:

/**
 * Pluralizes a word if quantity is not one.
 *
 * @param int $quantity Number of items
 * @param string $singular Singular form of word
 * @param string $plural Plural form of word; function will attempt to deduce plural form from singular if not provided
 * @return string Pluralized word if quantity is not one, otherwise singular
 */
public static function pluralize($quantity, $singular, $plural=null) {
    if($quantity==1 || !strlen($singular)) return $singular;
    if($plural!==null) return $plural;

    $last_letter = strtolower($singular[strlen($singular)-1]);
    switch($last_letter) {
        case 'y':
            return substr($singular,0,-1).'ies';
        case 's':
            return $singular.'es';
        default:
            return $singular.'s';
    }
}

Usage:

pluralize(4, 'cat'); // cats
pluralize(3, 'kitty'); // kitties
pluralize(2, 'octopus', 'octopii'); // octopii
pluralize(1, 'mouse', 'mice'); // mouse

There's obviously a lot of exceptional words that this function will not pluralize correctly, but that's what the $plural argument is for :-)

Take a look at Wikipedia to see just how complicated pluralizing is!

Bimah answered 4/6, 2013 at 19:17 Comment(1)
@Francesco Sure it does. Usage: pluralize(3, 'Ranch', 'Ranches'). The 3rd argument is only optional for the most basic words.Bimah
T
28

You might want to look at the gettext extension. More specifically, it sounds like ngettext() will do what you want: it pluralises words correctly as long as you have a number to count from.

print ngettext('odor', 'odors', 1); // prints "odor"
print ngettext('odor', 'odors', 4); // prints "odors"
print ngettext('%d cat', '%d cats', 4); // prints "4 cats"

You can also make it handle translated plural forms correctly, which is its main purpose, though it's quite a lot of extra work to do.

Tinsmith answered 7/10, 2009 at 21:6 Comment(3)
actually it would be printf(ngettext('%d cat', '%d cats', 4), 4); // prints "4 cats"Reaganreagen
That's not cool in combination with printf. Maybe PHP has something new today? :-)Segno
This answer is not correct. ngettext is a plural version of gettext; essentially, this is a transation function; in many cases this is not appropriate solution.Oenomel
G
7

The best way IMO is to have an array of all your pluralization rules for each language, i.e. array('man'=>'men', 'woman'=>'women'); and write a pluralize() function for each singular word.

You may want to take a look at the CakePHP inflector for some inspiration.

https://github.com/cakephp/cakephp/blob/master/src/Utility/Inflector.php

Gann answered 7/10, 2009 at 21:1 Comment(1)
That link is currently dead; source can be found here: github.com/cakephp/cakephp/blob/…Bimah
C
6

This will solve your issue, thanks to mario and Ternary operator and string concatenation quirk?

$bottom = "You have favourited <strong>$count</strong> " . ($count == 1 ? 'user':'users');
Caldarium answered 8/10, 2012 at 17:53 Comment(0)
M
6

Enjoy: https://github.com/ICanBoogie/Inflector

Multilingual inflector that transforms words from singular to plural, underscore to camel case, and more.

Morril answered 14/7, 2015 at 1:15 Comment(0)
P
4

If you're going to go down the route of writing your own pluralize function then you might find this algorithmic description of pluralisation helpful:

http://www.csse.monash.edu.au/~damian/papers/HTML/Plurals.html

Or the much easier approach would probably be to use one of the ready-made pluralize functions available on the Internet:

http://www.eval.ca/2007/03/03/php-pluralize-method/

Parasynapsis answered 11/10, 2009 at 9:35 Comment(0)
J
1

For $count = 1:

    "You have favourited <strong>$count</strong> " . $count == 1 ? 'user' : 'users';
=>               "You have favourited <strong>1</strong> 1" == 1 ? 'user' : 'users';
=>                                                        1 == 1 ? 'user' : 'users';
=>                                                          true ? 'user' : 'users';
// output: 'user'

The PHP parser (rightly) assumes everything to the left of the question mark is the condition, unless you change the order of precedence by adding in parenthesis of your own (as stated in other answers).

Janey answered 8/10, 2012 at 18:2 Comment(0)
A
1

Custom, transparent and extension-free solution. Not sure about its speed.

/**
 * Custom plural
 */
function splur($n,$t1,$t2,$t3) {
    settype($n,'string');
    $e1=substr($n,-2);
    if($e1>10 && $e1<20) { return $n.' '.$t3; } // "Teen" forms
    $e2=substr($n,-1);
    switch($e2) {
        case '1': return $n.' '.$t1; break;
        case '2': 
        case '3':
        case '4': return $n.' '.$t2; break;
        default:  return $n.' '.$t3; break;
    }
}

Usage in Ukrainian / Russian:

splur(5,'сторінка','сторінки','сторінок') // 5 сторінок
splur(4,'сторінка','сторінки','сторінок') // 4 сторінки
splur(1,'сторінка','сторінки','сторінок') // 1 сторінка
splur(12,'сторінка','сторінки','сторінок') // 12 сторінок

splur(5,'страница','страницы','страниц') // 5 страниц
splur(4,'страница','страницы','страниц') // 4 страницы
splur(1,'страница','страницы','страниц') // 1 страница
splur(12,'страница','страницы','страниц') // 12 страниц
Alarise answered 18/7, 2017 at 11:1 Comment(0)
H
0

You can try using $count < 2 because $count can also be 0

$count =1;
$bottom = sprintf("You have favourited <strong>%d %s</strong>", $count, ($count < 2 ? 'user' : 'users'));
print($bottom);

Output

You have favourited 1 user
Highboy answered 8/10, 2012 at 17:50 Comment(0)
S
0

This is one way to do it.

$usersText = $count == 1 ? "user" : "users";
$bottom = "You have favourited <strong>" . $count . "</strong> " , $usersText;
Snafu answered 8/10, 2012 at 17:51 Comment(1)
oh, I see what you were trying to accomplish. I have edited my answer.Snafu
T
0

In laravel, Str class has plural helper funcion:

use Str;
Str::plural('str');

Or you may use Pluralizer class:

use Illuminate\Support\Pluralizer;
Pluralizer::plural('str')
Tieback answered 21/10, 2023 at 10:35 Comment(0)
P
0
  /**
 * Function that will return the correct word related to quantity.
 * @param type Int $quantity
 * @param type String $singular
 * @param type String $plural
 * @param type Boolean $showQuantity
 * @return type String
 */
function pluralize( $quantity, $singular, $plural, $showQuantity=true ) {
    return ( $showQuantity ? $quantity." " : "" ) . ( $quantity > 1 ? $plural : $singular );
}


pluralize(3,'função','funções');
pluralize(1,'função','funções', false);
Petite answered 13/6, 2024 at 21:24 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Madrepore

© 2022 - 2025 — McMap. All rights reserved.