How good is Yii2's Inflector? I tested it against 71,000 English words
After sixteen years of hand-rolled pluralise helpers, I tested Yii2's Inflector class against 71,633 English nouns, alongside Doctrine, Symfony and a naive helper.
I've been building web applications with the Yii PHP framework since 2010, and in that time I've written more than a few little helper functions for turning "category" into "categories". There was usually a regex for the words ending in y and another for the ones ending in s or x. If a model called Person ever turned up, we'd have to rethink the whole concept and hardcode a mapping or two.
So I was a bit surprised, reviewing some code an AI coding assistant had written for me recently, to see it calling Inflector::pluralize(). It's a class that has sat in yii\helpers since Yii 2.0, and somehow in all that time I'd never come across it. I read through it with some interest, and it left me with an obvious question - after sixteen years of hand-rolled helpers, is the framework's version actually any better?
Reading up about the Inflector class also led me down a bit of a rabbit hole, exploring various poems about the English language, some of which I'd come across before and some that I hadn't.
How comprehensive are PHP frameworks?
I think this says a lot about how comprehensive a framework like Yii is, to the point where the docs are almost unnavigable. I've found you can't possibly know every feature and option, and I tend to only find the useful bits when I (or in this case an AI assistant) go looking for something specific. The Inflector does far more than plurals, too. There's camel2id() for turning PostTag into post-tag, slug() for URLs, ordinalize() for turning 21 into "21st", and sentence() for joining a list into "apples, pears and plums". I've almost certainly written my own version of at least half of those over the years.
How I tested it
The obvious way to find out how good it is was to throw a lot of English at it. I put together a small test repo, with some help from an AI assistant, which takes 71,633 nouns from SCOWL, a public English word list, along with every plural it lists for each one. It runs each noun through Inflector::pluralize() and each plural back through singularize(), and counts how many come out right. Where English allows more than one plural, "cacti" and "cactuses" for example, either counts as a pass.
To give the numbers some context I ran the same words through Doctrine's inflector (the one Laravel uses), Symfony's EnglishInflector, and a naive helper that adds s, es or ies, which is pretty much what I'd have written myself. The code and the full results are on GitHub at jgalley/yii-inflector-test.
Is Yii2's Inflector better than Doctrine or Symfony?
The test showed that most English nouns are regular, which means a naive helper gets you most of the way there. On SCOWL's most common words it got 98.8% of plurals right, and Yii got 99.1%. Not a huge gap for a whole class.
The more interesting numbers come from the words the naive helper gets wrong, which is where a library should earn its keep. There are 143 of those among the common nouns, and Yii gets 77.6% of them, so Person does come out as "people" after all. Doctrine does a little better at 81.1%.
| Common nouns | The 143 naive misses | Leaves plurals alone | |
|---|---|---|---|
| Naive helper | 98.8% | 0% | 0% |
| Yii2 | 99.1% | 77.6% | 98.5% |
| Doctrine | 98.8% | 81.1% | 98.3% |
| Symfony | 98.2% | 64.3% | 0% |
Symfony's plurals look respectable on paper, but its pluralize() pluralises words that are already plural, so "aardvarks" comes out as "aardvarkss". Yii and Doctrine both leave those alone.
Where does it get plurals wrong?
I found this anonymous poem about English plurals on World Wide Words, and it opens with "We'll begin with a box, and the plural is boxes, / But the plural of ox should be oxen, not oxes." Yii gets both of those right. It's the next verse where things start to wobble. "Then one fowl is a goose, but two are called geese", except in Yii, where two are called gooses. It copes with "a lone mouse or a whole nest of mice", and it knows "the plural of house is houses, not hice", but ask it for more than one blouse and you get blice.

Blice comes from a rule written for mouse and louse, which also happens to match blouse, and the test found most of the misses trace back to a handful of rules like it. Yii works through an ordered list of regular expressions and the first match wins, so:
- anything ending in s is assumed to be plural already, so bias and gas stay as they are
- there's no rule for z, so buzz becomes buzzs
- a rule meant for wolf and shelf also catches gulf, which becomes gulves
- virus becomes viri, which isn't the plural of anything in English
- singularising caches gives you cach
The other methods have their moments too. camel2id('HTMLParser') gives htmlparser rather than html-parser, and slug('1/2 price') gives 12-price, which is a very different offer.
Perhaps Gerard Nolst Trenité had the right idea. His poem The Chaos, first published in 1920 and all about English pronunciation, finishes with "My advice is: GIVE IT UP!"
Should you use Yii2's Inflector?
I think so. It's better than the helper I'd have written, it already knows about people, children and mice, and it's sitting there in every Yii 2 project whether you use it or not. I'd check the words your own app actually uses though, especially if you let Gii generate your models, since Gii uses it to name your relations. If one comes out wrong, the special cases are a public array, so Inflector::$specials['blouse'] = 'blouses'; sorts it out. Yii 2 does have end-of-life dates of its own coming up, though, and my Yii development page covers what comes next.
And if nothing else, it'll save me writing another pluralise helper.