Hello Backendless Community,
Here is the solution I implemented to make my app multilingual.
It supports:
- User selecting a language
- Language translations for UI (page data)
- Language translations for object data (table data)
I didn’t yet implement saving/remembering the user’s preferred language for future sessions. That would be pretty straightforward to do.
In my solution, app administrators manually enter translations in the backend. We usually enter translations in the database directly, but I also created pages for admin users to manage translations via custom UI. My solution is not one that translates content using an external tool at runtime such as Google Translate. All translation logic is in the app.
My app currently supports English and Spanish, but this solution can support any number of languages. I followed the ISO code standard for languages: en, es, etc… One can easily support country-level variants such as en-CA, es-MX, etc. if desired.
In my logic, English (en) is considered the default language. This means that whenever a localization for a given language is not defined, the logic will return the English value as a fallback.
-BACKEND-
For UI Translations…
I store localization definitions for app UIs (pages and components) in a database table, which looks like this:
I personally use a key-value structure, and prefix “LOCALIZATIONS_” for keys to differentiate, because I happen to be using this table for a number of configuration elements. You’re welcome to set up a dedicated table for localizations as desired.
I use “LOCALIZATIONS_[Page or Component Name]” as a naming convention to retrieve the JSON definition of localizations for a given UI.
The JSON content per entry is a collection that looks like this:
{
“back”: [
{
“value”: “BACK”,
“language”: “en”
},
{
“value”: “VOLVER”,
“language”: “es”
}
],
“exit”: [
{
“value”: “EXIT”,
“language”: “en”
},
{
“value”: “SALIDA”,
“language”: “es”
}
]
}
“back” and “exit” are keys that the UI uses to retrieve a localized string value.
For object data translations…
I add a JSON column named “localizations” to any table that requires translated properties.
For example, consider a Sport table with columns: objectId, name (string), description (string), localizations (JSON).
The content in the localizations column provides translations for the name and description properties:
{
“name”: [
{
“value”: “Baseball”,
“language”: “en”
},
{
“value”: “Béisbol”,
“language”: “es”
}
],
“description”: [
{
“value”: “Baseball is a bat-and-ball game played between two teams of nine players each, that take turns batting and fielding.”,
“language”: “en”
},
{
“value”: "El béisbol es un juego de béisbol entre dos equipos de nueve jugadores cada uno, que se turnan para batear y lanzar. ",
“language”: “es”
}
]
}
-FRONTEND-
The user selects their preferred language using a Select component the app header, which is a reusable component. The components options are value/label pairs en/English and es/Español.
When the user selects a language, I set the session language in App Data using a custom function to ensure that the selection applies to all pages.
setSessionLanguage custom function is simple:
When my app starts, I call setSessionLanguage to set the language to “en”, which is our default language. The user can then change it after.
I also made a corresponding getSessionLanguage function:
To retrieve localizations in UI Builder, I created two custom functions:
- getLocalizedUIValue: to get a localized value for a UI component such as a Text component
- getLocalizedObjectPropertyValue: to get a localized object property value such as the name property of a Sport
The custom function implementations are:
All the logic is encapsulated into 4 convenient custom functions that can be called from anywhere in my app to display translated content. It all works really well.
Of course, there’s always room for improvement, so please feel free to share feedback.
Hope this helps!
Marc