Greg.Randall

Title Case

October 29th 2019

A while back I was working on a WordPress website someone had built where all the titles were all caps, and I needed to fix that.

At first this problem looks pretty simple– just run all the titles through the simple PHP function ucwords. ucwords will take a string like “HELLO WORLD” and convert it to “HELLO WORLD”? Ok so, ucwords only uppercases words not lowercases words? So “HELLO WORLD” apply strtolower which makes “hello world”, then apply ucwords to get “Hello World”. Already this is more complicated than I wanted to get into.

So when you start throwing strings with ‘the’, ‘a’, ‘of’, etc. into the mix things get messier. Our solution of strtolower -> ucwords will make a string like “THE QUICK BROWN FOX JUMPED OVER A LAZY DOG” into “The Quick Brown Fox Jumped Over A Lazy Dog”. Clearly we don’t want “a” capitalized. So we find a list of words that shouldn’t be capitalized:

Alright. Great. Let’s make all of those words not capitalized.

$title = "THE QUICK BROWN FOX JUMPED OVER A LAZY DOG";
$title = strtolower($title);
$title = ucwords($title);
$lowercase_words = array('a ', 'aboard ', 'about ', 'above ', 'across ', 'after ', 'against ', 'along ', 'amid ', 'among ', 'an ', 'and ', 'anti ', 'around ', 'as ', 'at ', 'before ', 'behind ', 'below ', 'beneath ', 'beside ', 'besides ', 'between ', 'beyond ', 'but ', 'by ', 'concerning ', 'considering ', 'despite ', 'down ', 'during ', 'except ', 'excepting ', 'excluding ', 'following ', 'for ', 'from ', 'in ', 'inside ', 'into ', 'like ', 'minus ', 'near ', 'of ', 'off ', 'on ', 'onto ', 'opposite ', 'or ', 'outside ', 'over ', 'past ', 'per ', 'plus ', 'regarding ', 'round ', 'save ', 'since ', 'so ', 'than ', 'the ', 'through ', 'to ', 'toward ', 'towards ', 'under ', 'underneath ', 'unlike ', 'until ', 'up ', 'upon ', 'versus ', 'via ', 'with ', 'within ', 'without ', 'yet');

$title = str_ireplace($lowercase_words, $lowercase_words, $title);

echo $title;

That outputs “the Quick Brown Fox Jumped over a Lazy Dog”. Which is also not what we want. We need the first letter of the first word to be capitalized too. We’ll add in ucfirst to capitalize the first letter.

$title = "THE QUICK BROWN FOX JUMPED OVER A LAZY DOG";
$title = strtolower($title);
$title = ucwords($title);
$lowercase_words = array('a ', 'aboard ', 'about ', 'above ', 'across ', 'after ', 'against ', 'along ', 'amid ', 'among ', 'an ', 'and ', 'anti ', 'around ', 'as ', 'at ', 'before ', 'behind ', 'below ', 'beneath ', 'beside ', 'besides ', 'between ', 'beyond ', 'but ', 'by ', 'concerning ', 'considering ', 'despite ', 'down ', 'during ', 'except ', 'excepting ', 'excluding ', 'following ', 'for ', 'from ', 'in ', 'inside ', 'into ', 'like ', 'minus ', 'near ', 'of ', 'off ', 'on ', 'onto ', 'opposite ', 'or ', 'outside ', 'over ', 'past ', 'per ', 'plus ', 'regarding ', 'round ', 'save ', 'since ', 'so ', 'than ', 'the ', 'through ', 'to ', 'toward ', 'towards ', 'under ', 'underneath ', 'unlike ', 'until ', 'up ', 'upon ', 'versus ', 'via ', 'with ', 'within ', 'without ', 'yet');

$title = str_ireplace($lowercase_words, $lowercase_words, $title);

$title = ucfirst($title);

echo $title;

Finally we get our desired output of “The Quick Brown Fox Jumped over a Lazy Dog”.

We aren’t really catching a whole lot of edge cases here though. What if a title has a hyphenated word in it? The second half of the word won’t be capitalized. What if we have acronyms that should be all uppercase? What happens if the title is in a language that doesn’t follow english rules of capitalization? What if someone’s name is “McDonald”?

I fixed a few more of the edge cases and put the code up on GitHub’s Gist. A quick search of GitHub and Gist reveal many title case functions. It’s a hard problem and I don’t know that mine is the best but it worked on all the titles that I have so far thrown at it.