<p>First, are you sure you're going about this the best way? Are the uppercase words really mixed into unformatted / free-form text so much that you can only use string replacement? Sounds like a weird API to me. If you can somehow separate content from 'special' placeholders you could use something more fitting, like the translation API.</p>
<p>If you really want to go the find/replace route, you're right, using a Twig extension to have that logic in one place is the way to go. Start by creating a Twig extension in a module file and registering it with Craft, see the documentation on <a href="https://craftcms.com/docs/3.x/extend/extending-twig.html#register-a-twig-extension" rel="nofollow noreferrer">Extending Twig</a> for details. Once you have the extension set up, add a <a href="https://twig.symfony.com/doc/2.x/advanced.html#filters" rel="nofollow noreferrer">filter</a> with an appropriate name that does the replacement (using <a href="https://www.php.net/manual/en/function.str-replace.php" rel="nofollow noreferrer">str_replace</a> or <a href="https://www.php.net/manual/en/function.preg-replace.php" rel="nofollow noreferrer">preg_replace</a>).</p>
<p>You'll want to expose the list of replaced words to your editors, to avoid having to touch the code whenever a new replacable word needs to be added. There are different ways to achieve this; a simple solution would be a global set with a <a href="https://craftcms.com/docs/3.x/table-fields.html" rel="nofollow noreferrer">Table field</a>. The table field can have two columns, one for the original strings and one for the replacements. If you're absolutely sure all you need to do is a transformation from uppercase to title case, you could also use just one column or a text field with multiple lines. But in my experience, there will definitely an edge-case where you want a custom replacement, so better to be safe in this regard.</p>
<p>In the filter function, use the <a href="https://docs.craftcms.com/api/v3/craft-services-globals.html" rel="nofollow noreferrer">globals service</a> (<code>\Craft::$app-&gt;globals</code>) to get the global set and retrieve the table field's entries from that. Then it's just a matter of converting that to two arrays (one for original values, one for replacements) and passing it to <code>str_replace</code>.</p>

CC BY-SA 4.0
2022-02-24T19:17:55.687Z
I'm not sure what sort of clean utopia APIs you're used to but it's not at all uncommon in B2B that you get product titles,  descriptions or shipping terms and what not in all uppercase or some other weirdness because vendors are lazy or don't know better. Then you end up having to account for "proper" brand names (eg FedEx or Green Bay Packers) and sentence case to get everything looking clean.  FWIW your table field is a good approach, something I thought of as well.
RitterKnight
CC BY-SA 4.0
2022-02-25T10:15:45.737Z
@RitterKnight Yes, but those labels are usually in their own fields, not in freetext content. For example, in an API response with JSON data, you might get something like `"BRAND": "FEDEX", "STATUS": "IN_TRANSIT"`. In this case, I would treat those labels as machine-names and use translations (or the table field approach) to display that information in the frontend. I just found it a bit unusual that those upper-case machine-names should be mixed in with regular content / text copy, requiring a find/replace approach to make them human-readable.
MoritzLost
CC BY-SA 4.0
2022-02-28T16:05:20.127Z
It's sounding like I had a similar idea with the Twig filter. Thanks for the tips on getting started!
I hadn't thought of the translation API, might give that a try and see how it works - probably a quicker attempt than to write a Twig filter (for me at least)
Jaytrix
CC BY-SA 4.0
2022-03-01T08:59:59.183Z
@Jaytrix Yeah, I'd consider translations if the list of replaced words is somewhat static – but editors won't be able to add new words, at least not without additional plugins. Or if the number of possible phrases the API will return is fixed, maybe translate them wholesale? Anyway, if the solution works for you, don't forget to mark my answer accepted :)
MoritzLost
CC BY-SA 4.0
2022-02-24T15:47:34.247Z
2022-02-24T15:47:34.247Z
MoritzLost
<p>We have some content that contains words that should be presented in uppercase - the content comes via an API and is in all uppercase, we change it to title case to make it presentable.</p>
<p>I had started manually converting the words with <code>{{ description|replace(&quot;Abc&quot;, &quot;ABC&quot;) }}</code> but this will get tedious as more content becomes available (with more words to convert).</p>
<p>My only thoughts so far is to make a Twig filter, but I'm not sure where to start with creating one (interested to learn though).</p>

CC BY-SA 4.0
2022-02-24T15:31:45.803Z
Are you trying to convert from upper case to title case or the reverse? The first paragraph says you want to go from uppercase to title case, but the code example does the exact opposite …
MoritzLost
CC BY-SA 4.0
2022-02-28T15:42:01.777Z
@MoritzLost Apologies if I wasn't clear.
The content arrives all in uppercase and we convert it to title case. Within the content there may be certain words or acronyms that we want to return to uppercase

Example I can think of
Content arrives as "HELLO, WE ARE THE FBI"
Convert to title case "Hello, We Are The Fbi"
We want to change FBI back to uppercase "Hello, We Are The FBI"
Jaytrix
<templating><content><twigextension><uppercase>
Uppercase certain words in string
# Uppercase certain words in string

(Asked by: username_0 on 2022-02-24)

We have some content that contains words that should be presented in uppercase - the content comes via an API and is in all uppercase, we change it to title case to make it presentable.

I had started manually converting the words with `{{ description|replace("Abc", "ABC") }}` but this will get tedious as more content becomes available (with more words to convert).

My only thoughts so far is to make a Twig filter, but I'm not sure where to start with creating one (interested to learn though).

**Tags:** templating, content, twigextension, uppercase

> **Comments:**
> **username_1**: Are you trying to convert from upper case to title case or the reverse? The first paragraph says you want to go from uppercase to title case, but the code example does the exact opposite …  
> **username_0**: @username_1 Apologies if I wasn't clear. The content arrives all in uppercase and we convert it to title case. Within the content there may be certain words or acronyms that we want to return to uppercase  Example I can think of Content arrives as "HELLO, WE ARE THE FBI" Convert to title case "Hello, We Are The Fbi" We want to change FBI back to uppercase "Hello, We Are The FBI"  

---

## 1 answers

### Answer by username_1 on 2022-02-24. Score: 2

First, are you sure you're going about this the best way? Are the uppercase words really mixed into unformatted / free-form text so much that you can only use string replacement? Sounds like a weird API to me. If you can somehow separate content from 'special' placeholders you could use something more fitting, like the translation API.

If you really want to go the find/replace route, you're right, using a Twig extension to have that logic in one place is the way to go. Start by creating a Twig extension in a module file and registering it with Craft, see the documentation on [Extending Twig](https://craftcms.com/docs/3.x/extend/extending-twig.html#register-a-twig-extension) for details. Once you have the extension set up, add a [filter](https://twig.symfony.com/doc/2.x/advanced.html#filters) with an appropriate name that does the replacement (using [str\_replace](https://www.php.net/manual/en/function.str-replace.php) or [preg\_replace](https://www.php.net/manual/en/function.preg-replace.php)).

You'll want to expose the list of replaced words to your editors, to avoid having to touch the code whenever a new replacable word needs to be added. There are different ways to achieve this; a simple solution would be a global set with a [Table field](https://craftcms.com/docs/3.x/table-fields.html). The table field can have two columns, one for the original strings and one for the replacements. If you're absolutely sure all you need to do is a transformation from uppercase to title case, you could also use just one column or a text field with multiple lines. But in my experience, there will definitely an edge-case where you want a custom replacement, so better to be safe in this regard.

In the filter function, use the [globals service](https://docs.craftcms.com/api/v3/craft-services-globals.html) (`\Craft::$app->globals`) to get the global set and retrieve the table field's entries from that. Then it's just a matter of converting that to two arrays (one for original values, one for replacements) and passing it to `str_replace`.

> **Comments:**
> **username_2**: I'm not sure what sort of clean utopia APIs you're used to but it's not at all uncommon in B2B that you get product titles,  descriptions or shipping terms and what not in all uppercase or some other weirdness because vendors are lazy or don't know better. Then you end up having to account for "proper" brand names (eg FedEx or Green Bay Packers) and sentence case to get everything looking clean.  FWIW your table field is a good approach, something I thought of as well.  
> **username_1**: @username_2 Yes, but those labels are usually in their own fields, not in freetext content. For example, in an API response with JSON data, you might get something like `"BRAND": "FEDEX", "STATUS": "IN_TRANSIT"`. In this case, I would treat those labels as machine-names and use translations (or the table field approach) to display that information in the frontend. I just found it a bit unusual that those upper-case machine-names should be mixed in with regular content / text copy, requiring a find/replace approach to make them human-readable.  
> **username_0**: It's sounding like I had a similar idea with the Twig filter. Thanks for the tips on getting started! I hadn't thought of the translation API, might give that a try and see how it works - probably a quicker attempt than to write a Twig filter (for me at least)  
> **username_1**: @username_0 Yeah, I'd consider translations if the list of replaced words is somewhat static – but editors won't be able to add new words, at least not without additional plugins. Or if the number of possible phrases the API will return is fixed, maybe translate them wholesale? Anyway, if the solution works for you, don't forget to mark my answer accepted :)  

---

