I’ve written a WordPress plugin that will convert the page title and post title to ‘title case’ capitalization. Title case is also often referred to as “headline style”, and incorrectly as “initial caps” or “init caps”. Title case means that the first letter of each word is capitalized, except for certain small words, such as articles, coordinating conjunctions, and short prepositions. The first and last words in the title are always capitalized.
This plugin may be useful if you’re trying to give the titles on your site a consistent appearance, but it’s no substitute for writing a good title. There are way too many exceptions and rules to make a simple script behave correctly all of the time.
The plugin is smart enough to not capitalize the following:
- Coordinating conjunctions (and, but, or, nor, for)
- Prepositions of four or fewer letters (with, to, for, at, and so on) (limited)
- Articles (a, an, the) unless the article is the first word in the title
But the plugin isn’t perfect. It won’t capitalize an article that is the last word in the title. It fails on subordinating conjunctions. It conservatively de-capitalizes only some of the prepositions, hopefully reducing the chance of incorrect behavior. For example, it leaves the word over caps, because over can be an adverb, an adjective, a noun, or a verb (caps) or a preposition (not caps), and determining how a word is being used in a title is really beyond the scope of a humble plugin.
The plugin requires you to edit it for certain product names, like “iPod”, and cool-people names, like “Olivia d’Abo” or “Jimmy McNulty”. It’s not savvy enough to know that acronyms, like “HTML”, should be all caps unless they’re used in particular ways, such as in the case of “Using the .html Suffix”, unless you tell it. That said, editing the plugin for these particular words is very easy.
Even with all these limitations, it beats using CSS to {text-transform: capitalize} the titles or just applying PHP’s ucwords()
to the entire thing. But I’m guessing that dissatisfaction with one or both of those two methods is what brought you to this page in the first place.
On the upside, it capitalizes any word following a semicolon or a colon, e.g.: “Apollo: A Retrospective Analysis”. It also capitalizes any word immediately preceded by a double or single quote, but only if you haven’t bypassed WordPress’s fancy quotes feature.
How it works
The plugin first finds all words that begin with a double or single fancy WordPress quote and adds a space behind the quote. It capitalizes all of the words in the title with ucwords()
, then selectively de-capitalizes some of the words using preg_replace()
. It then uses str_ireplace()
, a case-insensitive string replace function, to correct the odd capitalization of certain other words. Finally, it removes the spaces behind the quotes.
The code
This is what the code looks like. It should be pretty easy to follow what’s happening.
<?php
function ardamis_titlecase($title) {
$title = preg_replace("/“/", '“ ', $title); // find double quotes and add a space behind each instance
$title = preg_replace("/‘/", '‘ ', $title); // find single quotes and add a space behind each instance
$title = preg_replace("/(?<=(?<!:|;)W)(A|An|And|At|But|By|Else|For|From|If|In|Into|Nor|Of|On|Or|The|To|With)(?=W)/e",
'strtolower("$1")', ucwords($title)); // de-capitalize certain words unless they follow a colon or semicolon
$specialwords = array("iPod", "iMovie", "iTunes", "iPhone", " HTML", ".html", " PHP", ".php"); // form a list of specially treated words
$title = str_ireplace($specialwords, $specialwords, $title); // replace the specially treated words
$title = preg_replace("/“ /", '“', $title); // remove the space behind double quotes
$title = preg_replace("/‘ /", '‘', $title); // remove the space behind single quotes
return $title;
}
add_filter('wp_title', 'ardamis_titlecase');
add_filter('the_title', 'ardamis_titlecase');
?>
Download
Download the plugin, upload it to your site, and activate it.
Download the Title Case Capitalization WordPress plugin
Further customization
The plugin won’t alter words written in all caps or CamelCase. You could use ucwords(strtolower($title))
to convert the entire $title
to lowercase before applying ‘ucwords’. This may fix instances where someone has typed in a bunch of titles with the caps lock key on. But you’ll then have to compensate for words that should be all caps, like ‘HTML’, ‘NBC’, or ‘WoW’, in $specialwords
.
An alternative using a ‘foreach’ loop
It’s possible to do something similar using a foreach
loop. This isn’t as graceful, in my opinion, but I suppose it’s possible that someone may find it works better.
<?php
function ardamis_titlecase($title) {
$donotcap = array('a','an','and','at','but','by','else','for','from','if','in','into','nor','of','on','or','the','to','with');
// Split the string into separate words
$words = explode(' ', $title);
foreach ($words as $key => $word) {
// Capitalize all but the $donotcap words and the first word in the title
if ($key == 0 || !in_array($word, $donotcap)) $words[$key] = ucwords($word);
if (preg_match("/^“/", $word))
$words[$key] = '“' . ucwords(substr($word, 7));
elseif (preg_match("/^‘/", $word))
$words[$key] = '‘' . ucwords(substr($word, 7));
}
// Join the words back into a string
$newtitle = implode(' ', $words);
return $newtitle;
}
add_filter('wp_title', 'ardamis_titlecase');
add_filter('the_title', 'ardamis_titlecase');
?>
Credits
Thanks to Chris for insight into the preg_replace
code at http://us2.php.net/ucwords. Thanks to Thomas Rutter for insight into the foreach
code at SitePoint Blogs » Title Case in PHP.