The Forms created using form builder needs to support internationalization. The implementer configures the form in one locale. The end users opening up the form in their respective locale should be able to see it in their specific language. A sample form definition is here.
The Form Definition currently supports Label, ObsControl (Represents single obs), ObsGroupControl (Represents an obs_group) apart from various UI elements like TextBox, NumericBox. Having all the labels in all possible locales can make the form definition bloated and huge. For ObsControl & ObsGroupControl, we want to leverage the concept names in various locales. Some concepts like Chief Complaint can have huge number of answers and we do not want to store all the locale strings for all the answers inside the form definition.
Handling the labels
The workflow for handling the labels will be
- Implementer Interface provides support for adding/editing translation keys as a new app. User can manage keys using UI. The keys are stored in a custom table in the database.
- Implementer will create a form
- Drag-and-drop some controls
- Modifies the labels and selects a translation keys created using the app in step 1. The UX of this workflow can be further improved. this is just a high level idea.
The advantages are
- It’s easy to provide CRUD on the keys in database table.
- It’s easy to export and load it in systems like Transifex and also easy to import back once the translations are done.
We are planning to explore the openmrs Custom Messages module.
Handling the concepts
OpenMRS supports concept names in various locales out of the box. We want to leverage it. User will have a facility to override the usage of concept name with a custom label. The custom labels will follow the above approach.
Response from the Server
The form definition request will be a coarse grained API performing these things
- Get the form defn from form_resource table
- Parse the list of concepts associated to form definition and get the concept_names in user specific locale
- Query the locale strings associated to this form from our custom table.
- Merge the strings from 2 & 3 as one locale file
- The API response includes the form_defn with the locale information.
Once the locale strings are available on the client side, we are planning to use a standard react i18n library like react-i1nify, i18n-react
Request you to please validate the approach. Thank you.
I like the idea of avoiding the form definition bloat!
Could you share the database table structure?
Thanks @dkayiwa. We are still in the process of design. Meanwhile, any suggestions are welcome.
Server-rendering of the form is discarded ? It seems easier to implement than manipulating the DOM.
Hi @bharatak - thanks for posting this! A few thoughts:
I agree with the idea of supporting Concept Names. I could see an implementation wanting to specify this either on the control-level or on the form-level (eg. all concepts on a form should use the same name type/tag). I think this is most valuable for large value sets (eg. all diagnoses) as you have described.
Beyond concept names, my view is that defaulting to standard message properties is the way to go. As the original author of the custommessages module, I think having a separate table can work, and I would support you taking this module, stripping out all of the UI stuff that was added in for 1.9, and adding a new modern OWA for managing custom messages. That being said, like my comment about form definitions in another post, I would personally rather see these messages stored, managed, and able to be version controlled a text-based configuration file (eg. within the .OpenMRS directory). For us, regardless of where and when the content is authored, we want to be able to version control this and reproduce our running implementation without needing to export from set of tables on a production system.
Outside of this, I do think it is still useful to retain the ability to define some translations in-line, particularly for small forms. In htmlformentry, we support an additional set of tags where you can do this. You might want to consider supporting this within your form definition json, as another alternative for users to consider.
Interested in others thoughts. @ball?
Are you suggesting creating the form definition on the server side for the specific locale dynamically and send it back to client?
No, I was just curious about how you render the form, if at server or client side. Not important.
+1 to @mseaton’s suggestion to support providing message codes via messages.properties files in the implementation config that can be version-controlled.
To expound on one aspect of this: the default behavior should be to display concepts using their locale-preferred name. The form author should be able to override this by providing specific text (either as a message code or static text).
The author should also be able to override it by specifying a ConceptNameTag, and then the framework should first try to display by fetching a name (in the right locale) with that tag, falling back to the locale-preferred name if none is found. (I don’t know whether it’s more valuable to support this at the form level or the control level.)
When we built the OpenMRS Ebola system, we started from the CIEL dictionary, but added a few names that we tagged as “Ebola preferred”, and drove the UI with this tag.