Multi language design models. Results of a knowledge network day.
This forum post is the result of a knowledge network day on the 25th of augus 2013 about designing multi language Mendix projects. The participants where Roeland Salij of Mendix, Querijn Chorus of Nobel, René Smit of Intermediad and me, Ronald Catersels of Daywize. I would like to thank these participant for sharing their knowledge. This post is the result of this meeting so that when a Mendix developer needs to design a multi language environment knows how to approach this. The reason to organize this day was because when building a test project there are many ways that lead to Rome… But what is the best way? I could easily design multiple ways to achieve this, but each solution had its drawbacks. Therefore I decided to organize a day about this subject with Mendix partners who already tackled (or wrestled) with this problem. We all know that the user interface is not the problem. This is all handled by Mendix in the modeler. But know about the data fields that also needs to be presented in more languages. Even after this day I still think it could or should be handled by the modeler without the need of the solution architect to design it specifically. My ideal solution would be that I could just click on a attribute in my entity and select translatable attribute and that the model would handle everything for me according to the language settings in the model. But this is probably wishful thinking by me that is not yet technical feasible. But maybe Johan and his team of wizards can make this happen sometime in the future. Until then the designer has to make some design decisions. The design solution presented by Roeland from Mendix is in our opinion the best solution. Only the design solution from Intermediad came real close to this solution. I will discuss each solution in this forum post and make some comments about drawbacks and advantages. In total 8 different solutions where presented this day. 1 The Mendix solution The first thing I noticed about this solution is the use of a calculated attribute in the TranlatableEntity something that Mendix always tell you only to do if all else fails because of the performance drawbacks a calculated attribute can have on your application. The reason why a calculated attribute can be used here is because it only retrieves over an association the object with the right translation. This is the microflow that is used to retrieve the object (note: Apply entity access is set to true): The advantage of this solution is that retrieving and showing the translatable object is relative simple. Only one microflow is necessary and the rest are standard forms. The drawback could be the performance loss because using a calculated object. But since this microflow is only a simple retrieve this loss is very small. One other drawback of this solution is that this one in not a solution that comes to mind easily. Only Intermediad had a solution that came real close to this one. 2 The Intermediad solution This solution comes real close to the Mendix solution but has some other drawback compared to the Mendix solution. Because of commits on the main object when showing the translation the data about by whom the last record was saved becomes useless while in the Mendix solution this also is preserved. 3 All data in one entity In this solution all the data is kept in one Entity. The non persistent objects are used to set booleans that are used to show the right translation and hide the other translations. Advantage of this solution is that all data is in one entity. Searching objects are easy because for each language there is a search field. Drawback of this solution is that custom microflows are needed when creating new objects or edit existing one. And the forms are complex because of the Edit condition of visible object and because when showing a grid in the right language needs separate forms for each language. 4 One entity per language with reference to main object. The advantage of this solution is that it is easy to display all the languages in one form, but this also is a drawback of this solution. Forms can become complex and synchronizing all the languages to make sure everything is filled out needs to be done. 5 For every language a separate entity. Here all the data is in one entity and each language has its own entity. This way forms are easy. The drawback is that microflows are needed to show the right form. And here also there needs to be a synching mechanism to keep all the languages in line. 6 All the data in one entity. In this solution all the objects are places in one entity and a relation is set to language. Advantage here is that all is done in one form with xpath. Drawback is to sync all the objects. If an object is changed the translated objects needs also be adjusted. 7 Translatable attribute in non persistent object. In this solution the non persistent objects are created with the right translation. The advantage of this solution is that a relative small number of microflows and forms are needed. The major drawback here is the loss of search attributes because of working with non persistent objects (I still do not grasp this why this is not possible with non persistent objects. Since all objects are in memory it seems to me that only a different search is needed. From a user interface perspective it is something I cannot explain to my customers why I cannot display search fields in certain forms.) And the second drawback here could be performance loss whit a lot of objects. I would not advise this when a lot of objects need to be created. 8 Default object with tooltip forms to show the translation. In this solution all the data is in one default language. This could be an elegant solution in multinationals where there is one language that is used when working in a multi national environment. The advantage is that the forms are easy and no custom microflows are needed. The drawback is that not the standard tooltip solution can be used. The formloader widget is needed to retrieve the right form. If some of the limitations of tooltips forms could be removed in the modeler than this could be an interesting solution. Again many thanks to the participants of this knowledge day. I hope that this post keep developers on the right track when creating multi language Mendix solutions. Any comments are welcome and I will keep this post updated with new insights on this subject. Regards, Ronald Catersels Daywize
I have recreated this:
Showing translated fields (in my case product name, product description) using TranslatedProduct, calculated values, microflows with apply entity access on and entity access rules with xpath constraints in data views and data grids.
My xpath constraint looks like this: [Translate.ProductName_Language/System.Language/System.User_Language='[%CurrentUser%]']
Relative short lists of translated names and descriptions.
Adding an index to the description field seems unnecessary, because it is not used in the retrieve.
The key field seems unnecessary.
I have added default values.
I don't want to create a translation model for each different object.
I want to create a single excel import to import translated objects and fields.
Why add an index to the description field?
What is the use of the key field?
How would you expand your model for other objects and fields?
How does it impact performance if I create parent classes TranslatedObject and TranslatedField, but still use the association TranslatedProduct_TranslatedName in the calculated value?
Giel van Altena
We're currently working on solution 1 and are experiencing some difficulty getting the TranslatableEntity.Name in a reference selector. The settings won't allow us to set the displayed attribute to the associated translation. With a page as selection method it works on the Select page, but when returning to the main object you see its original Name attribute. Have tried some widgets to get this to work but it looks like we're going to have find a workaround for this in the domain model or alter the page to stop using ref selectors.
UPDATE: Situation example. I want the CurrentName to show up in the refselector we are using on page with MainObejct as page parameter, instead of the OriginalName. Our modeler version is 7.5.0 and it will only allow us to select the direct attributes of the associated object..