Interactive Builder for Form Translations within the Form Builder (Interactive Translation Builder?)

4 Must-Do’s

1. Problem Description: Have you clearly defined the user problem(s) you intend to solve, and what value this creates? Write down a story, user insight, or quote about this problem (this is important because (1) this will motivate your team, and (2) without this your problem might not actually be a big problem for the users themselves).
2. User Stories: Have you clearly written at least 3 user stories and use cases
3. Market Analysis: Have you surveyed what the market is doing here (e.g. comparison to other EMRs, or paper approaches; and don’t forget about learning from historic/existing OMRS instances)? Have you written down any possible gaps in your understanding of your users or their workflows? Have you reviewed the topic in FHIR to see what requirements or fields the global community references? (Eg if working on insurance, should look here)
4. Technical Considerations & Dependencies: Have you outlined what you need from cross-functional areas for success of the feature? E.g. do you need the platform to support a new API call? Have you explained how you’ve addressed dev concerns, such as designs that may not be feasible, or will be extra time-intensive to implement? 

Optional/Encouraged

Sketches: Have you added a drawing or description of how the feature could work to solve the problem at hand? (Pictures of sketches are ok!) 
Project Management: Have you created the Epic and JIRA tasks so you can share work clearly? Roll-out plan: Do you have an idea whether this will be an experiment, gradual roll out, and when? Have you added this to the timeline view? Have you planned how you will promote and/or work with communications folks in order to help this feature reach the widest audience and have the biggest impact it can?

Later but should do

QA Plan: Have you mentioned the plan for QA, such as how you will discover and address edge cases? Does your team/squad have a plan for automated tests to be added to new components (unit tests) or workflows (e2e tests)?
Safety & Tech Risks: Is there any reason you could regret rolling out this feature? (e.g. possible patient harm, heavy tech debt like introducing an unsupported library) Have you thought through the risks for this particular solution? And, how to reduce/address those? 

This checklist was inspired by this article. Additional Business Analyst Resources here.

 Problem Statement

Current translations for forms in OpenMRS are restricted to:

  • Pre-boot form translations only: Translations for forms can only be loaded during instance initialization via config files (example). This means that you can only add translations for predefined forms that are also loaded during initialization, and there is no in-built feature to support adding translations for forms you create/import on the form builder.

  • Form translation config files are not intuitive: The translation files for forms are not very intuitive, and can be confusing unless done by a person who knows what they are looking at. In addition, forms are usually not always made by technical personnel, so adding form translations must also be a more user-friendly feature.

Current workflow to add translations for a form:

  1. Users have to add the form into a configuration folder that can be picked up by the initializer e.g - https://github.com/openmrs/openmrs-content-referenceapplication-demo/blob/main/configuration/backend_configuration/ampathforms/ampath_poc_adult_return_visit_form_v1.6_core-demo.json

  2. Users then have to create the translation file for each language into a configuration folder for the form that they added e.g - https://github.com/openmrs/openmrs-content-referenceapplication-demo/blob/main/configuration/backend_configuration/ampathformstranslations/Ampath%20POC%20adult%20return%20visit%20form_translations_fr-core_demo.json

  3. The openmrs instance must then be created to see this in effect.

How do you update the translations? Well, you have to do the above workflow from step 2 all over again.

 

Project Size

Large

Why we need it?

In the day and age of content packages, this would be a method for people to re-use forms but customize it to their language in a user-friendly way.

Project Idea

Similar to the interactive builder, a UI that would enable users to add the translations for a form for any language.

Here’s a (very high level) flow of how that might look like:

  1. A separate UI editor(from the interactive builder) to manage translations

  2. Preview the form in selected language and add language options

    Screenshot 1.1
  3. Adding the translation strings

    Screenshot 1.2

Obviously, this is not how the UI should look and neither are these mockups for the project. These are merely a guide to understand the use case.

Implementation

  1. A UI editor needs to be implemented to manage the translation strings for each question (interactive translation builder)

    1. We need to display all the translatable strings within the form (e.g. - question labels, answer labels) within the UI and allow the user to enter the respective string for it in a different language.

      1. For example, refer to screenshot 1.2. The translation builder should display Was this visit scheduled (the label of the question on line number 64 on the JSON) as a translatable string. The user should be able to add the translation this string.

    2. Manage translations for different languages

      1. Users should be able to add translations for different languages for a translatable string.

  2. Preview the form in a specific language.

    1. Currently, the form builder has a Preview tab, that allows you to preview a form (as how an end user using a form would see it). How this works is, the JSON (that can be seen in the Schema Editor tab gets rendered by the form-engine - https://github.com/openmrs/openmrs-esm-form-builder/blob/eff9e72db3964140f0c1068d9086397a45236520/src/components/form-renderer/form-renderer.component.tsx#L83

    2. Currently you’d see if you change the language to French and launch the Adult HIV Return Visit form, the form would be displayed in French. How the translations for the form get loaded is, each translation file is saved as a formResource of a form. This is because translations for a form are separate from the form itself. The translations are saved as a formResource to the form. The backend module o3-forms , when you request a form, adds the translations to the form json. You can see this if you look at the response of the API call for getting a call (e.g, make an API call to https://test3.openmrs.org/openmrs/ws/rest/v1/o3/forms/107c32e8-a318-30bf-acfc-a0244f3a795a on postman, see fig 1.1). The backend module got these translations because it was saved as a configuration file, and it can only do this if the translation files are saved in the database as a formResource for the relevant form. We can’t render the translations this way while a user edits the translations because they aren’t saved to the database, and we shouldn’t be saving them to the database and refetching it every time an edit is made.

    3. So what you need to do is update the translations object in the form’s JSON schema in the schema editor, similar to how when you create/update a question using the interactive builder, it updates the form’s JSON schema in the schema editor. Please look at the form, the above point and the translation file for the form to understand the structure of the form and translations and where the translations should be in the JSON schema. The translation strings SHOULD NOT replace the labels itself of a question, all translation strings should be in the translation object in the form JSON.

    4. This can be complicated when managing multiple languages. When changing languages, it should be checked if we can maintain the strings for all languages within the schema, i.e. if it is possible to do something like:

    5. "translations": { "fr" : { ... }, "it" : { ... } }
    6. If not, we should fallback to an user only being able to edit translations for only one language at a time, and show a danger prompt saying that they’ll lose their changes if they switch languages and ask them to download the translations before they switch.

    7. Since this schema that has the translations is what gets passed to the form-engine, it should be able to render the form in a specific language.

    8. There should be a dropdown where a user can select which language to preview the form in.

Possible complication: currently in patient chart where the forms are being used, you need to change the overall language of the entire application (through the top navbar) in order for the form to be rendered in that language. We need to figure if we can render a form in a specific language without changing the overall language of the entire application.

image-20250307-094526.png
Response for the API call for a form (fig 1.1)
  1. Users should be able to download the translation resource file (check the reference materials to see what the file format should be) for a specific language.

    1. The current scope of the project isn’t to save these translations to the backend. Its to allow users to download the JSON document of translations that they can add to their Initializer configuration.

    2. The user just needs to able to see an option to download the translation files for a specific language. e.g. - for this form -https://github.com/openmrs/openmrs-content-referenceapplication-demo/blob/main/configuration/backend_configuration/ampathforms/ampath_poc_adult_return_visit_form_v1.6_core-demo.json the user needs to be able to download the translation file for example for French, which should be formatted to this - https://github.com/openmrs/openmrs-content-referenceapplication-demo/blob/main/configuration/backend_configuration/ampathformstranslations/Ampath%20POC%20adult%20return%20visit%20form_translations_fr-core_demo.json(this is the format that the file a user downloads should be in, and each language should have its own file like this that contains the translation strings for that language)

Although the idea itself seems simple, there’s a considerable amount of work that would require to make the entire UI and to manage multiple translations, and actually making the translation file resource itself.

 Reference materials

  1. An example form translation file in English - https://github.com/openmrs/openmrs-content-referenceapplication-demo/blob/main/configuration/backend_configuration/ampathformstranslations/Ampath%20POC%20adult%20return%20visit%20form_translations_en-core_demo.json

  2. An example form translation in French - https://github.com/openmrs/openmrs-content-referenceapplication-demo/blob/main/configuration/backend_configuration/ampathformstranslations/Ampath%20POC%20adult%20return%20visit%20form_translations_fr-core_demo.json

  3. Conventions for the form translation file - https://github.com/mekomsolutions/openmrs-module-initializer/blob/b5a6cabd5bccba78c1fd13710d1e929adc1e42bf/readme/ampathformstranslations.md

  4. The original form itself - https://github.com/openmrs/openmrs-content-referenceapplication-demo/blob/main/configuration/backend_configuration/ampathforms/ampath_poc_adult_return_visit_form_v1.6_core-demo.json

  5. The form builder’s source code - https://github.com/openmrs/openmrs-esm-form-builder

  6. The backend form module - https://github.com/openmrs/openmrs-module-o3forms

  7. The form engine source code - https://github.com/openmrs/openmrs-esm-form-engine-lib

  8. Learn about the O3 Form Builder - https://www.youtube.com/playlist?list=PL5jj7JoBifSkI_MBt1uKGTCEkk11KuZAL and https://www.youtube.com/playlist?list=PL5jj7JoBifSm-jke5ofzZiGbS_n8phHaG

FAQ

No. The translation builder isn’t to add translations that are in the form builder UI. It’s only to add translations for the strings inside the form. Like the form name, label of a question in the form. For example take the adult hiv return visit form. That shouldn’t be the name in French. Take a look at the resources section in the project wiki and look at the French translation file for the form and compare it with the JSON file of the form to understand what the translation strings are. So the strings like "addPage" and "addSection" that are in the translations folder in the Interactive Builder are part of the builder's own functionality—they're not the ones intended for translation of the form content. The Translation Builder is solely for managing the translatable text within the form itself.

I don’t know if we can localize the language change to a specific part of the user interface, but basically what should happen is, a user should be able to change the language of a form just to be able to preview only the form in the selected language. Ideally, this would be separate from the overall language switcher in the navbar. So unless you change the overall language from the navbar, the layout shouldn’t need to change for RTL languages. But if you a user does change the overall language, the layout of the editor should update if its a RTL language. The language change within the Translation Builder should only affect the form preview for that specific form, without altering the overall UI layout (e.g., RTL adjustments) unless the user changes the overall language from the navbar.

Related content