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
Thank you for the above snippet, it works great!
It’s very beautifully
Thanks! Works perfectly.
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!
Nice! The other pluralize() solutions I found were severely lacking.
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.
Good catch Alix. Updated
One Trackback
[...] 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 [...]