First of all, we have locale parameters and locale Entity to manage locales stuff and language reference.
We add some parameters:
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 🏁
A little LocaleRepository to handle the switch between config and parameters:
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 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:
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!
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:
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 !
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! 🚀