Wiki Spaces


Get Help from Others

Q&A: Ask OpenMRS
Discussion: OpenMRS Talk
Real-Time: IRC Chat | Slack


Page tree
Skip to end of metadata
Go to start of metadata


Design of pretty handy and unobtrusive web widgets might be considered as the major task of creating good tool for in-line localization.

Mockups design

Technically, client side part of this tool can be done as java-script bookmarklet within custommessages module. Using of bookmarklet will not set bounds for potential translator what browser to use. Bookmarklets work everywhere. From the other hand, OpenMRS server might run in two modes: let's name them normal and translate modes. There is some special with these modes. Activation of translate mode just simply turns OpenmrsMessageTag to produce any text enclosed into span tags with the special css-class "translatable". Also, in this mode we will show link with bookmarklet code in the bottom of the page at strip with languages (see callout 1 on mockup below the text). But in normal mode it would be better to do not show that link just to avoid confusion of users. Since all coding work should be done on top of custommessages module, then the easiest way to inject the link with java-script bookmarklet code into OpenMRS core footer page is to use mechanism of module extension points

Please configure the Balsamiq Wireframes macro and select the wireframe to show. Learn more

The idea is next. Volunteer, who wants to help us to translate OpenMRS to French (for example), will need to switch his local OpenMRS server into translate mode and run OpenMRS in French locale. Thereafter, when this person moves mouse pointer over any "translatable" text on any OpenMRS core web page, the javascipt engine will handle this event and highlight that text with the rectange alike Chrome Firebug does (callout 1 on mockup below). If user wants to translate this text, he just clicks mouse on it and put his translations into popup dialog right below the translatable text (see callout 2 on mockup below this paragraph). To submit his translation he may click on Apply button. Javascript handles it and sends just created translation to local OpenMRS server. The server, in turn, processes the request and saves new translation into file. 

Please configure the Balsamiq Wireframes macro and select the wireframe to show. Learn more

Translator will not only be able to create new translations, he will be able to edit existing ones. To do this, he will need to click on any already translated text and correct it. This can be done by showing English variant of each text message within translations console popup. For example, when user sees that translation of menu item (lets say, - "Chercher/créer un patiente") needs some work, he just clicks on it and starts to edit. Translation console popup will contain read-only English variant "Find/Create patient" as original and editable "Chercher/créer un patiente". So, user can easily edit it. Mockup below illustrates this.

Please configure the Balsamiq Wireframes macro and select the wireframe to show. Learn more

All translations, which user does, not only can be saved to user local server, but also can be committed to the master OpenMRS server. This ability will be provided via translator admin dasboard. This dashboard will be done on the basis of custommessages module admin interface. In order to commit local changes user will need to press on Commit Messages link-button within translation admin page (see mockup below the paragraph). Local server, which receives commit requests, will check the connection with master OpenMRS server. If the connection can be established, it will make something like svn diff of message properties files on both local and master servers. After creating the diff, local server will respond this diff in user-friendly format to client (callouts 2 and 3 on mockup below this paragraph). Client may review it, correct any conflicts and approve commit operation. In fact, local server will send approved diff to master server, which will try to apply received changeset. In case of succeed, master sends corresponding aknowledge to local server and person, who made these translations, will be notified with success message.

Please configure the Balsamiq Wireframes macro and select the wireframe to show. Learn more

The conception of translations commitiing, saving and synchronizing will be reviewed in corresponding wiki pages here.

  • No labels


  1. The committing functionality can come later. Focus on just getting those written to the for that new locale and then people can submit that locale as a patch file on a ticket.

    Can the popup show tabs so that the user can see the other languages as well as the key code that is in the properties file?

    1. Thanks, Ben, for this comment. I'm completely agreed with you about doing committing functionality later, because it can be not so easy. The major point is to make base version of localization tool and then sequentially add pieces of functionality.

      As for showing popup dialog with tabs for other languages, I think, it's also possible, and even more, it will be so convenient to have such functionality, because it will allow persons to make translations into different languages, and possibly will greatly simplify our work on coding. 

  2. Will there be permissions about being able to 1) add new translations or 2) edit an existing one? Should this permission be locale-specific (allowed to edit French only, for example)?

    How can you prevent local changes from being overwritten during an update? Will the diff files be stored separately and reapplied with each update?

    Is seeing the text in context with different languages sufficient to properly translate the message? Developers have access to the code and know what the command is supposed to to. Users do not. Should there be a separate data field for definition or explanation or help text, for example, similar to what we do for concept translations? At the very least the hover help should be translated and viewable.

    As an FYI, the TSB shows the languages all on one screen so that it is easy to 1) see if its not translated and 2) see the commonality among similar languages. Clicking between the different tab controls to see this seems unnecessary.

    1. Thanks a lot, Andrew, for all these questions and suggestions! Will try to answer on them one by one.

      As for questions about permissions. Yes, I think, we should have certain privileges for adding and editing translations within OpenMRS access control system. We can have them in terms of existing as following:

      • Manage translations - Required to add new translations
      • Edit translations -  Required to allow a user to change existing translations.

      Should this permission be locale-specific? I think that no they should not. Even Amanuens translation system does not grant any locale-specific privileges to translators, may be this is because it's not so easy to implement such access control. And in the most common case it can be considered as overhead.

      As for next question about preventing of overwriting of local changes. If you meant an SVN update, then I guess, we should not worry about that, because all changes will be being done in execution environment within message properties files on local server not in development environment.  But if you meant physical re-deploy of application on server, then, as initial solution in this case we can keep separate diff files for each user in OpenMRS data directory and then apply them everytime when doing redeploy.

      As for question about showing explanations of certain text message meaning. Basically, most of the times, the meaning of message can be get from context. But yes, there can be few cases, when we can not catch the meaning from context. So, if such situation heppens, then we can have optional description property in openmrs:message jsp tag. And developer, who initially adds this message, can put short explanation into this property.

  3. FYI: PIH just presented one of their modules, "custommessages" on a recent developer's forum: Check back on that page for the recording link to see what they have done with it. They are storing the messages in the db, I believe. The main difference is the lack of in-line editing. The work you have shown here could bolt on top of that module to save you some coding time.

    1. Thanks, Ben, for this info. I've already looked through their presentation and made some investigations into module source code. So, at the first glance I can say that this module has all necessary things to build basic version of in-page localization tool on. Basically, we can use its CustomMessageController for getting, saving and exporting messages. And this is very convenient.

      But from the other hand we should answer to the next question: where do we want to have functionality of in-page localization tool - within core or within separate module?
      If within separate module - then, the custommessage module is the right place, for doing in-line localalization tool development.

      1. If its possible I'd love for it to all be in a module. There might need to be some core changes (to the taglibs) in order for it to work though, so perhaps some core changes to enable it but then the bulk of it actually in a module?

        1. Yes it is, I'm completely agreed with you, Ben. I'm considering that, technically, In-page localization tool is not a part of core, it's related to translation service, so it should be done within module.

          Also, I would not mind to do preparatory work on custommessage module - move it onto maven platform, because it's bit inconvenient to build it via ant and use openmrs-1.6.x project as libraries source for build.

  4. Mykola, here's another strategy to consider...

    1. Simply focus on making messages on a page inline-editable (e.g., text & button labels).
      • Someone with Translate Messages privilege sees a small "translate" button as you have proposed in the footer.  Clicking the button toggles translation mode on/off.
      • In translate mode, any messages on the screen (including text & button labels) can be edited inline; when toggle off, the web application works as normal.
      • This step is completed when a user with Translate Messages privilege can see a translate button, use it to toggle into "translate" mode, and, when in translate mode, edit any messages on the screen, including button labels.  No persistence.  All editing inline (no multilingual popups, etc.).  This should be doable via a module without the need for any browser-specific component (bookmarklet or browser extension).
      • Extra credit: add a cross-browser, cross-platform shortcut key for toggling the translate button.
    2. Persist edits done in translate mode.
      • This step is completed when inline edits performed by a user in "translate" mode are persisted back into the appropriate message bundle (i.e., the message bundle for whichever locale is active).  The user should be able to switch locales (using the existing footer links) and edit messages within that locale.  You've just created a novel way for people to manage their messages in vivo (within the running application).  In addition, if I switch to a locale without any messages, then I will see the default locale (e.g., English) messages in the web application and can proceed to go page-by-page, toggling into translate mode and editing each message into the new language.

    I would leave further enhancements (seeing multiple languages at once, submitting changes to a central server, etc.) off the table until you have gotten the above working.  If you can make a module that does these two things, it will be immediately helpful for managing messages (not just translation).  In fact, you might find that the first enhancement you want to do (before the ones you've listed) is to make the above work easily for modules – i.e., modules that follow specific conventions can join the party and have their messages edited inline as well.  Then module authors could get the basic functionality working and use your module to come along later and fine tune their messages and/or create translations for their module.

    1. Thanks, Burke, for this suggestion!

      I like this strategy and completely agree with fact that we can leave further enhancements. As I've said before, the major point is to make base version of in place localization tool and then sequentially add pieces of functionality.

      So, as I understood from description given above, the first thing, that I need to do, is to make all text messages to be translatable (I believe that it can be done by slightly changing OpenmrsMessageTag to produce inline editable messages). Then, in translate mode any message can be edited in place by user with Translate Messages privilige (without any popups, simply just like a Jeditable Jquery plugin does it, for instance). Translate mode is activated/deactivated by toggling button in page footer. All edits, which are being done in translate mode, persisted back into message source bundle when user toggles off translate mode.

      May you confirm me that I understood you right?

    2. Burke, I think it is pretty important to be able to see other languages when you are doing translations. Translation is a tricky process and we should not underestimate the amount of learning that has already gone on about this. That is why we work with Univ. of Cambridge on linguistic issues. It is still necessary to have better definitions of what the text really means as context is NOT sufficient to understand what the function is. It is helpful, and is better than NOT having the context, but it is not clear what the menu item is really doing. I also worry about people changing languages they are not proficient in, or changing it from something that was correct to something they thought was correct (hence the need to have permissions per language). I do like the idea of storing this in the database rather than properties, as it makes it easier to work with. 

      I don't really remember what the local server versus the master server refers to here (probably did at the time), but at some point would like to reapproach this.


      1. Andy, the first pass is just to enable in-page translation – i.e., to get it working.  See this example.

        Once we have in-page translation working, it will be a fairly straightforward step to expose the messages from all available languages to the user when editing a message.  For example, when you click on a message to edit it, a popup (maybe automatically or via a hotkey) displays all existing translations of that message for you as a reference.

        I believe that supporting simultaneous multiple language translation (i.e, editing the message in multiple languages) within a single widget is overkill, adds more complexity than value, and will make it more complicated to impose language-specific translation permissions.

        The master server thing is no longer part of our design plan; rather, you will be able to export your translation edits as message bundle(s).