Mendix: Optimize runtime language translations

Nirmal Kumar
Mendix Community
Published in
4 min readJul 4, 2020

--

Introduction

In this article I will be talking about Runtime Translations, how to do it default in Mendix (out-of-the-box), its pitfalls and alternate solutions to increase performance.

In our current product, we had to support multiple languages to cater to the internationalization requirement. At this moment we support 15 languages. The entire product is easily translatable with out of box Mendix translation functionality.

IMAGE_1: Language list in our product

However in our product we developed features which allows users to add dynamic content which decides what has to be rendered on the screens. For example, Users can configure their instance to add dynamic list of checkbox items out of predefined list. Similarly they also can add drop-downs. We allow users to add the translations for values of these items per language too. And these values must be shown as per the language setting of the user, that’s the whole purpose right.

Mendix out-of-box solution

We had an entity called Translation which is now linked to language.

IMAGE_2: Translation entity linked to language

Then, we used Calculated attributes, passed user language to get the translations of the user language. This comes as a saviour for small scale applications with less concurrent users. Below is the Microflow we used for the calculated attribute, which retrieves appropriate translation to be shown based on the User’s language.

IMAGE_3: Retrieval of Translation provided language or retrieve default

Problems with out-of-box solution

The actual problem is, we had to link the Translation entity with couple of other entities to retrieve translation depending on the type of entity, also to reduce the query complexity. Nevertheless, it is still complicated. When an entity is associated with another entity, there will be one dependency table created. So, any retrieval has to go through 3 tables via joins, which complicates the entire retrieval. Also, the calculated attributes are always executed during every retrieval. So, if there is a database call, this will certainly affect the performance.

Alternate solution

With my Java experience, I came up with an alternate way to do this. Which not only cuts down the DB calls for this requirement, but also increases performance. In Java, we have something called ResourceBundle which is used for internationalization. This is also how Mendix translations works. Look in the deployment folder under model/i18n to see Mendix translation.

IMAGE_4: Mendix generated ResourceBundle’s

My solution to resolve this issue and reduce the Database calls to zero for translation retrievals, as well as to increase the performance, was to go with ResourceBundle for the custom translations tool.

Create ResourceBundle

  • I wrote a Microflow which collects all translations per language in the system. Passed on the Translation list along with language to a custom written Java program
  • This Java program will make sure to create a ResourceBundle for the language with all the possible values. ResourceBundle works with Key=Value pair approach. So, I decided to use the key as <SomeuniqueId-for-Translation>.Value=<Translation for that language>
Custom generated ResourceBundle’s
  • Write another Java program to retrieve the value of translation from the Resourcebundle file given the key and language. As per IMAGE_3, in the out of box solution, we must specifically handle the default translation value logic. But with ResourceBundle approach, it is handled already.
  • NOTE: this retrieval logic must still be called with Calculated attribute, except there wont be any database calls or complicated queries involved

Advantages of using this solution

  • No database calls, almost zero for retrieving translations
  • Increased performance
  • ResourceBundles are cached. So, each retrieval does not go to file system

Conclusion

Hope this article is helpful to those who wanted to support runtime translations and are experiencing performance issues. I deliberately avoided explaining ResourceBundle here, because this is a technical topic which requires some Java expertise. I have included some links below on ResourceBundle if you would like to try it out yourself.

References

--

--