Most of my projects would benefit if I'd translate them into multiple languages. To do this properly, I must translate every text/button/popup/form etc. that I have in my apps.
A common way to do this, with REACT, is to use the react18next bundle. This bundle provides all the functions and components needed for i18n (internationalization) and for translating an app.
All you have to do is: initialize it and provide a JSON object or file for every language you need.
const resources = {
en: {
translation: {
"Welcome to React": "Welcome to React and react-i18next"
}
},
fr: {
translation: {
"Welcome to React": "Bienvenue à React et react-i18next"
}
}
};
As simple as that is, there is a big downside to it: By default, all translations are stored somewhere in the codebase! In almost every project in which I have worked so far, there was a programmer needed to change translations/text or to just fix spelling mistakes.
This is not only expensive, this is also very inefficient. It would be way better if anybody, on the team, could do necessary changes "on the fly".
My solution
My own projects all have some sort of blog, which runs on a Typo3 CMS. Since translations are basically just another form of content, the obvious solution here is to provide and mange translations in that very same CMS.
So let's do this!
Benefits:
Using Typo3 instead of a language file or even just a JSON object comes with a few benefits.
It's:
- very easy to maintain
- extremely easy to create new translations
- no extra place where "content" is stored
- can be done by a monkey
Of course, you can use any headless CMS for this. Doesn't have to be Typo3!
How it works
So here is how I build it:
- my react-app sits on the root URL /
- the backend URL for the app is /api/
- the blog API is reachable via /blogapi/
- all translations are located at /translations/[language]
My problem here is that the /blogapi and /translations/[language] routes can not be handled by the CMS directly, since it is not even running on the same system as the app.
To make this work, I'm using a proxy server that redirects incoming requests to the correct backend.
Typo3 Backend
Content
This is how it looks in the backend: There is only one page that stores all the translations! When something needs to be changed, added or fixed, I can now just edit the content element in Typo3, and I'm done. No coding, no deployments, no "testing" and I can do that from my phone if need be.
Every time I add a new language to my app, I now just have to:
- create a new site language in Typo3
- configure the entry point
- create a new translation of the main content element.
This can now be done by any typo3 or content admin - no need for developers anymore!
The combination of the TYPO3 Headless API extension and a little typoscript gets me a pretty well formatted output, too.
{
"Signup": "Registrieren",
"Login": "Anmelden"
}
If you want to see for yourself, you can check it out here:
- /translations/ (English/Default)
- /translations/de (German)
React
On the React side, I added a bundle called i18next-http-backend to fetch the translations from a URL instead of a source file or JSON object.
Here is how that looks:
i18n
.use(HttpApi)
.use(initReactI18next)
.init({
fallbackLng: "en",
interpolation: {
escapeValue: false,
},
backend: {
loadPath: (lng, ns) => {
const baseUrl = "https://bewerbungshelferlein.de/translations/";
switch (lng) {
case "en":
return baseUrl;
case "de":
return baseUrl+`de`;
}
},
requestOptions: {
cache: "no-store",
},
},
});
For adding a complete new language, I still need to modify the React code to make this work.
Conclusion
I think this is a very powerful solution that will take away some (a lot?) work from your dev team and make it faster to implement text changes. The Bewerbungshelferlein app I used for this example will be live soon (I hope) and then you can see this live in action.