PHP Pluralize Method

I recently found myself wanting a rails-esque pluralize function like that found in the Rails Inflector class. After inspecting the Rails implementation, and playing around a bit, I was able to get a PHP version working as a Smarty variable modifier. Thank goodness for the rails version, I have no idea how I would go about listing all the various kinds of singular / plural nouns. Where would one go for a list of those kinds of things?

 
class MyClass 
{
    public static function conditionallyPluralize( $string, $count )
    {
        if ( intval( $count ) !== 0 )
            return MyClass::pluralize( $string );
 
        return $string; 
    }
 
    public static function pluralize( $string ) 
    {
 
        $plural = array(
            array( '/(quiz)$/i',               "$1zes"   ),
	    array( '/^(ox)$/i',                "$1en"    ),
	    array( '/([m|l])ouse$/i',          "$1ice"   ),
	    array( '/(matr|vert|ind)ix|ex$/i', "$1ices"  ),
	    array( '/(x|ch|ss|sh)$/i',         "$1es"    ),
	    array( '/([^aeiouy]|qu)y$/i',      "$1ies"   ),
	    array( '/([^aeiouy]|qu)ies$/i',    "$1y"     ),
    	    array( '/(hive)$/i',               "$1s"     ),
    	    array( '/(?:([^f])fe|([lr])f)$/i', "$1$2ves" ),
    	    array( '/sis$/i',                  "ses"     ),
    	    array( '/([ti])um$/i',             "$1a"     ),
    	    array( '/(buffal|tomat)o$/i',      "$1oes"   ),
            array( '/(bu)s$/i',                "$1ses"   ),
    	    array( '/(alias|status)$/i',       "$1es"    ),
    	    array( '/(octop|vir)us$/i',        "$1i"     ),
    	    array( '/(ax|test)is$/i',          "$1es"    ),
    	    array( '/s$/i',                    "s"       ),
    	    array( '/$/',                      "s"       )
        );
 
        $irregular = array(
	    array( 'move',   'moves'    ),
	    array( 'sex',    'sexes'    ),
	    array( 'child',  'children' ),
	    array( 'man',    'men'      ),
	    array( 'person', 'people'   )
        );
 
        $uncountable = array( 
	    'sheep', 
	    'fish',
	    'series',
	    'species',
	    'money',
	    'rice',
	    'information',
	    'equipment'
        );
 
        // save some time in the case that singular and plural are the same
        if ( in_array( strtolower( $string ), $uncountable ) )
	    return $string;
 
        // check for irregular singular forms
        foreach ( $irregular as $noun )
        {
	    if ( strtolower( $string ) == $noun[0] )
	        return $noun[1];
        }
 
        // check for matches using regular expressions
        foreach ( $plural as $pattern )
        {
	    if ( preg_match( $pattern[0], $string ) )
	        return preg_replace( $pattern[0], $pattern[1], $string );
        }
 
        return $string;
    }
 
}

Works like a charm!

EDIT: Sho Kuwamoto took this example and ran with it, creating a really robust and complete pluralization solution for PHP (and ActionScript!). Check out his improvements here.

7 Comments

  1. Posted July 17, 2007 at 11:04 am | Permalink

    Thank you for the above snippet, it works great!

  2. Posted August 5, 2007 at 10:32 am | Permalink

    It’s very beautifully

  3. Posted September 6, 2007 at 1:23 am | Permalink

    Thanks! Works perfectly.

  4. Posted December 17, 2007 at 7:59 am | Permalink

    Hi Paul. Thanks for doing this. As it turns out, I needed more accurate pluralization for my project, so I tweaked the rules and added a singularizer as well. The code can be found here.

    Thanks again for doing this!

  5. Posted March 18, 2008 at 2:54 am | Permalink

    Nice! The other pluralize() solutions I found were severely lacking.

  6. Posted April 30, 2010 at 8:00 am | Permalink

    It should be:

    if (intval($count) !== 0)

    Otherwise you’ll end up with something like “0 apple” instead of “0 apples”. Same goes for negative numbers.

  7. Posted April 30, 2010 at 8:35 am | Permalink

    Good catch Alix. Updated :)

One Trackback

  1. By Simple PHP Pluralize | Nerdy Dork on April 13, 2009 at 4:12 pm

    [...] recently wrote a simple function that did the task for me. I know there are PHP Pluralize functions out there, but they are a bit overkill for my needs. I got this idea from the way Django templates [...]

Post a Comment

Your email is never shared. Required fields are marked *

*
*