A Twig filter for titles currently exists that converts a string to capitalize it.
{{ entry.title|title }}
The above craft variable and twig filter changes
craft web development in ireland
to
Craft Web Development In Ireland
While the Twig filter for titles works great in 99% of cases, it's important to be aware of its limitations.
But what if your string already contains capitals or other variants that must remain in the current format?
Example
craft CMS web development using AI in ireland
This becomes
Craft Cms Web Development Using Ai In Ireland
This doesn't achieve what we want. So, a custom Twig extension to the rescue.
Strict Title Twig Extension
The original title filter from Twig uses PHP's mb_convert_case
public static function titleCase(string $charset, $string): string
{
return mb_convert_case($string ?? '', \MB_CASE_TITLE, $charset);
}
Lets create our own function. This is where unicode character properties in regex can save us.
A reproduction of mb_convert_case
without the problematic conversion to lowercase becomes:
public function mb_convert_case_utf8_variation($s): string
{
$arr = preg_split("//u", $s, -1, PREG_SPLIT_NO_EMPTY);
$result = "";
$mode = false;
foreach ($arr as $char) {
$res = preg_match(
'/\\p{Mn}|\\p{Me}|\\p{P}|\\p{Cf}|\\p{Lm}|\\p{Sk}|\\p{Lu}|\\p{Ll}|' .
'\\p{Lt}|\\p{Sk}|\\p{Cs}/u', $char) == 1;
if ($mode) {
if (!$res) {
$mode = false;
}
} elseif ($res) {
$mode = true;
$char = mb_convert_case($char, MB_CASE_TITLE, "UTF-8");
}
$result .= $char;
}
return $result;
}
Explanation
For each character, a regular expression is used to check if the character belongs to any of several unicode character classes. If the character is from one of these classes, $res
will be true.
The rest of the code inside the loop checks the $res
value. If $res
is true, and $mode
is false, that means we're transitioning from a non-matching character to a matching character, so mb_convert_case(
) is used to convert the character to title case and $mode
is set to true. If $res
is false and $mode
is true, then we're transitioning from a matching character to a non-matching one, so $mode
is turned off.
At the end of each loop iteration, whether the character was transformed to title case or not, it's appended to $result
.
Props to user Artefacto on this Stack Exchange post
How to Install
I have a custom module on my site where I have integrated this twig extension. I won't review that here, but you can read Soft Limit Function on a Craft CMS Text Field Using a Module for more info.
You can grab the full code for this Twig Extension