Internationalization with API Platform: the other way
Tags: symfony, php, api, i18n
Published: 2020-09-16 07:09:10

We recently saw the great article of Locastic on this tricky subject of implementing translations in API and specifically in API Platform

![API Platform, API Platform everywhere!](https://dev-to-uploads.s3.amazonaws.com/i/p1oawmzj5l4tuhzsw2ec.jpeg)
*API Platform, API Platform everywhere!*

We recently saw [the great article of Locastic](https://medium.com/locastic/having-troubles-with-implementing-translations-in-apiplatform-7861294fb7c6) on this tricky subject of implementing translations in API and specifically in [API Platform](https://api-platform.com/)

For one of our project, we also find a pretty neat solution to implement intl in our beloved API Platform!

---

**First of all**, we have locale parameters and locale Entity to manage locales stuff and language reference.

We add some parameters:

{% gist https://gist.github.com/Nightbr/b22ec4012699185a303f81408b8e0dfa %} 

You can also use **Locale Entity** and add new locales in database. The Locale Entity has priority over **parameters**. If there is no Locale in database, it will use parameters config.

Our **Locale Entity** 🏁

{% gist https://gist.github.com/Nightbr/03daa5a69e8df257c7d1d1e76d94736c %}

A little **LocaleRepository** to handle the switch between config and parameters:

{% gist https://gist.github.com/Nightbr/4f622e5c5a1ef1991b28759c267bd61f %}

Note: We use autowiring to pass parameters _parametersDefaultLocale_ and _parametersAvailableLocales_ to the constructor.

---

**Now we need to translate our Entities !**

We choose to use [Doctrine Translatable Extension](https://github.com/Atlantic18/DoctrineExtensions/blob/master/doc/translatable.md) to manage our Translatable Entities.

Pretty simple! We only followed the Doctrine Translatable Extension doc to give our translatable behavior to our Entities. Here is an example of a translatable entity:

{% gist https://gist.github.com/Nightbr/71c8eeae311270a3f2ee13734f310c49 %}

{% gist https://gist.github.com/Nightbr/823625d2b9747450d526377ba191635b %}

Pretty easy, isn’t it? 👌

---

> But how can this work? Where is the magic trick? How can I know which locale is use or how can I add new languages and translations?

Here is the magic trick, we have a **LocaleListener!**

{% gist https://gist.github.com/Nightbr/4ae0006a72ff721efec57c485bb5663e %}

When you call the API (_GET, POST, PUT, PATCH_), you want to retrieve data (or post data) for a specific locale. You can do this by passing the locale in the header of your request:

```
X-LOCALE: fr
```

If your locale is null or not supported, it will use the default locale.

---

❤️ I love this solution because it is simple and use standard library such as **Doctrine Translatable** which is mainly use in **Symfony** application.

Add to that, it is stateless and stay **REST compliant** (when we _GET/POST/PUT_… we stay in the Entity context).

If you want multi-language editable field, just create it with your favorite frontend framework and change the header _X-LOCALE_ to the correct language on the _POST/PUT_ request.

For example, we retrieve available locales through the API locale endpoint to display flags 🇫🇷 and edit button ✏️. When you click on edit button, it will go to the edit form with the correct language data thanks to the correct _X-LOCALE_ header in the _GET_ request. And when you submit the form, it calls a _PUT_ on the entity with the correct _X-LOCALE_ header set to the selected language !

![Example of frontend UI](https://dev-to-uploads.s3.amazonaws.com/i/mzwgv1n8r8jryzv975iw.png)
Example of frontend UI

_Note: with the approach we have the same entity id for all languages. The company id=42 will always be the company 42 in different languages. Only Translatable Annotated field will change. So be sure it is ok with your use case. I don’t think there is a unique and perfect solution for the intl problem._

Thanks for reading and feel free to ask anything in comment! 🚀

From Medium:

{% medium https://medium.com/@titouanbenoit/internationalization-with-api-platform-the-other-way-5ce9c446737f %}

Demo Repository:

{% github Nightbr/api-intl %}