Translatable formatted text in webdev (with Laravel example)
Tags: laravel, webdev, localization, tutorial
Published: 2024-03-26 02:13:06


I have always struggled with translating formatted text inside my Laravel projects. for context, formatted text is any text (letter, word, multiple words, …) that has a different style than the rest of the text, often making you use a span to style it.

For example the following is a normal h2 (secondary heading) text:
```html
<h2>
  Design, Build and Ship faster with our services!
<h2>
```
and we want the words “Design”, “Build” and “Ship” to have a different gradient color. let’s use TailwindCSS for this (you can use your preferred method)
```html
<h2>
  <span class="bg-gradient-to-r from-blue-600 via-green-500 to-indigo-400">
    Design
  </span>, 
  <span class="bg-gradient-to-r from-blue-600 via-green-500 to-indigo-400">
    Build
  </span>
  and 
  <span class="bg-gradient-to-r from-blue-600 via-green-500 to-indigo-400">
    Ship
  </span>
  faster with our services!
<h2>
```
As you can see, the text became messy and it is by no means easy to translate. if you’re using Laravel and want to translate this phrase you’d need to translate every word separately and then translate the rest of text and all of them should make sense in you own language and it is no simple task, in fact in some cases (for some languages) it is impossible.

## So, what is the solution?

well what if we had a simple way to do things a convention that will make it easier for the developer and for the end user to style the text as they wish without changing the source code but only by changing the translation.

what if we and the end user can only wrap the special text in a special set of characters and voila.

## My proposition

What if the code looked like this instead
```html
<h2>
  ``Design``, ``Build`` and ``Ship`` faster with our services!
<h2>
```

Or this

```html
<h2>
  ~~Design~~, ~~Build~~ and ~~Ship~~ faster with our services!
<h2>
```

Or like this

```html
<h2>
  {~Design~}, {~Build~} and {~Ship~} faster with our services!
<h2>
```

well you get the idea, wrap your text with any symbol you want as long as it will not interfere with any thing in your project or framework. ie: in Laravel i can’t use `{{ }}` or `{!! !!}`.

## The Rest is Easier than you think
To replace our special character with the span formatting we will use regex, yes it is that simple. Let’s look at an implementation:

```php
preg_replace_callback(
    '/``(.*?)``/s',
    fn ($matches) => <span class="..."> . $matches[1] . </span>,
    $text
);
```

The function above is a regex that scans the text given and replaces our special text with the output text we want.

## Now What
Let’s use it.

## Laravel Example
Let’s make a blade directive that takes in our special text and the style that we want to give it. it should look like this:
```php
@highlight("``Design``, ``Build`` and ``Ship`` faster with our services!", "<span class="...">","</span>")
```
now let’s make the logic (the blade directive)

```php
Blade::directive('highlight', function (string $expression) {
    $params = json_decode("[$expression]");
    $text = $params[0] ?? '';
    $opening = $params[1] ?? '';
    $closing = $params[2] ?? '';
    $translate = $params[3] ?? false;

    $text = trim($text, '"');
    $text = $translate ? __($text) : $text;

    return preg_replace_callback(
        '/``(.*?)``/s',
        fn ($matches) => $opening . $matches[1] . $closing,
        $text
    );
});
```

in the code above we take the expression that is given to the directive in the blade file.
We then make it a table inside a string and json_decode it to get the parameters.
Then we affect each parameter to a variable to hold it’s value, then we trim our text to not get the quotes with the text and we get it’s translation if the user made the last param as true.
And lastly we transform our special text using our regex while passing the second ($opening) and third ($closing) argument tag which is making our highlight() directive customizable.

P.S.: You can register the above code in your appServiceProvider in Laravel and use it in your blade files.

## Translation
in your translation file just put the special text as is and do the same with the translated text and you will get a beautiful text just like you want it to be.

```json
// ar.json
{
  "``Design``, ``Build`` and ``Ship`` faster with our services!": "``التصميم``، ``البناء`` و``الشحن`` بشكل أسرع مع خدماتنا!"
}
```

if the end user can update the translation from some user interface you only need the indicate to them that they can use these magic characters to make their own translation formatted.

## Thank you 🙏🏻
I hope this helped you, have a good Day!