Dataverse: Internationalization - alert messages is not toggling with language selection

Created on 16 Oct 2018  路  18Comments  路  Source: IQSS/dataverse

The alert info/warning/success messages remains English , and doesn't toggle with Language selection .

image

Internationalization

All 18 comments

I just saw "please review the code" at https://github.com/IQSS/dataverse/pull/5299#issuecomment-440353165

There is a lot of discussion about the specifics of this issue in the pull request #5299.

I have just created a new branch 5202-edit-dataverse-info-msg off of the original branch @JayanthyChengan created, in order to fix the display of the info msg on the Edit Dataverse pg.

screen shot 2018-11-28 at 10 53 30 am

Will put more detail and feedback into the pull request, to keep the conversation going there.

@mheppler @JayanthyChengan Why when I look at this PR is there a ton of changes not specifically related to the title of this ticket? It makes it less clear what the scope is. The PR title is more accurate, more broad. Just trying to understand what these changes mean.

@kcondon According to the commit log for this PR, it includes the changes from the date format PR a653bccfef55862ab87414571045c2d3e9d82713.

The changes in that PR are mostly applied to the Java manage beans. The rest of the changes for this PR are applied to the DataverseLocaleBean.java manage bean and each of the main app xhtml pgs that you can navigate to in the browsers. This allows for blue info alert msgs on each edit or manage pg to be translated. The changes were applied to all pages, even those without these info msgs, for consistency's sake.

Those main pages are as listed here:

  • 403.xhtml
  • 404.xhtml
  • 500.xhtml
  • ThemeAndWidgets.xhtml
  • confirmemail.xhtml
  • dashboard-users.xhtml
  • dashboard.xhtml
  • dataset-widgets.xhtml
  • dataset.xhtml
  • dataverse.xhtml
  • dataverse_template.xhtml (main template for entire app)
  • dataverseuser.xhtml
  • editdatafiles.xhtml
  • file.xhtml
  • guestbook-responses.xhtml
  • guestbook.xhtml
  • harvestclients.xhtml
  • harvestsets.xhtml
  • iframe.xhtml
  • loginpage.xhtml
  • manage-groups.xhtml
  • manage-guestbooks.xhtml
  • manage-templates.xhtml
  • oauth2/callback.xhtml
  • oauth2/convert.xhtml
  • oauth2/firstLogin.xhtml
  • passwordreset.xhtml
  • permissions-manage-files.xhtml
  • permissions-manage.xhtml
  • privateurl.xhtml
  • role_permission_helper.xhtml (to soon be removed)
  • search/advanced.xhtml
  • shib.xhtml
  • template.xhtml

I'll be happy to provide more detail or answer any more questions if that doesn't clear up enough of what's covered in this PR.

OK, I'll take a look. Might have misunderstood the essence of the ticket and the conversation moved to PR.

@kcondon please let me know, if I can answer any of your questions. Thanks

Unfortunately, the solution of using f:view on each page had other conflicting issues (see #5400). So we had to revert that back.

The plan is to go back to solving this a different way. It seems to be the issue is that the DataverseLocaleBean, which is a container managed bean is being used in a non managed way by the BundleUtil. So we'd like to try and see if we can make sure that BundleUtil does that, likely by also making it managed (possibly renaming it with the convention we've used for other such classes - BundleWrapper). The thought is by doing this, it wouldn't be creating a new LocaleBean and would use the one from the session which definitely knows the correct Locale.

Confirmed with @djbrooke that we will pick this up first thing after the holiday break. This was the plan as discussed with @scolapasta and @matthew-a-dunlap when reviewing the issues discovered in #5400. With the work @JayanthyChengan delivered thus far, the IQSS dev team will pick up this issue with a fresh set eyes in the new year and get it across the finish line.

We will iterate on the DataverseLocaleBean as mentioned above, to solve the language toggle problems with the composite components in messages.xhtml which deliver alert messages to the UI via the custom iqbs component in dataverse_header.xhtml.

@mheppler - I tried the option of what Gustavo suggested( maybe not in proper way ), but the issue still remains the same. Thanks for taking this issue first thing after the holiday break, that's greatly appreciated.

@JayanthyChengan Happy to collaborate on this. You've done great work in this feature thus far, and hopefully in the process to improve it, we can all learn a little bit more about the JSF template feature and how language works.

Some comments on the state of things w/ this. There were multiple issues and some confusion (so, a bit of a longread).

First of all, yes, the way BundleUtil and LocalBundle were calling the locale bean was wrong. You cannot just instantiate a bean that's supposed to be session scoped from a static, non-EJB context. So that had to be changed.

Note however, that this was not in any way unique to the info message in the example above. It was affecting all the calls to the BundleUtil from all the Java beans; and note that the way it was written, it was actually working properly for most of the BundleUtil strings. For example, on the HarvestingClients page, in the example above, that top message was the only one left un-translated; all the other messages (errors when creating clients, etc.) coming from the backing bean were in French. That's because every time BundleUtil was instantiating a new DataverseLocaleBean, as it was, it was getting the proper locale code from the FacesContext.ViewRoot.Locale. So we can simply continue doing just that - bypassing trying to talk to the locale bean. (with some fallback code for when FacesContext is unavailable; similarly to how it was being done before) In other words, we don't need an EJB service bean wrapper for the BundleUtil, because we don't need EJB there at all. This is what I'm doing in the solution I checked in. (but let's review and see if this solution is missing something somehow).

Now, as for the reason the info message in the example above was left untranslated. It definitely doesn't have anything to do with the custom component we are using for info messages. It doesn't matter how custom it is; the localization DOES NOT happen there - the page gets the string from the bundle and passes it to the message component as text:

FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, BundleUtil.getStringFromBundle("harvestclients.title"), BundleUtil.getStringFromBundle("harvestclients.toptip")));

i.e. the message component doesn't even need to know what locale or what language it is; it just renders a bunch of characters.

And the only reason the page was failing to get that text from the correct bundle was, apparently, the fact that it was being done in the init() method. Somehow at the point of the init() execution, the value of the Locale in the JSF FacesContext.ViewRoot has not yet been set (it is set by the f:view locale="#{dataverseLocaleBean.localeCode}" in the dataverse template; and it is working properly throughout the rest of the page).
Other info messages, that are sent from parts of pages outside the init() methods were properly translated (meaning, even in the develop branch as it was before I did anything). For example, the info message upon creating the private url, as in the screenshot below:
screen shot 2019-01-22 at 7 14 20 pm

Why this is the case, I don't know. In the harvesting clients page, the f:viewAction that calls the init method sits OUTSIDE the ui:composition (that loads the dataverse_template, where the f:view line sets the locale...) so I thought that was the problem:

<h:body>
        <f:metadata>
            <f:viewParam name="dataverseId" value="#{dataverseServiceBean.findRootDataverse().id}"/>
            <f:viewAction action="#{dataverseLocaleBean.updateLocaleInViewRoot}"/>
            <f:viewAction action="#{harvestingClientsPage.init}"/>
            <f:viewAction action="#{dataverseHeaderFragment.initBreadcrumbs(dataverseServiceBean.findRootDataverse())}"/>
            <f:viewAction action="#{dataverseHeaderFragment.addBreadcrumb('/dashboard.xhtml?dataverseId='.concat(dataverse.id), bundle['dashboard.title'])}"/>
            <f:viewAction action="#{dataverseHeaderFragment.addBreadcrumb(bundle['harvestclients.title'])}"/>
        </f:metadata>
        <ui:composition template="/dataverse_template.xhtml">

but no; in the dataset.xhtml, the init is being called from inside the template composition - and the result was the same; any calls to bundle util inside the init() method were getting the default locale ("en").

This can be fixed by either the following Java code added to the init() method:

String localeCode = dataverseLocaleTracker.getLocaleCode();

FacesContext.getCurrentInstance().getViewRoot().setLocale(new Locale(localeCode))

or in the xhtml, by an extra f:viewAction before the f:viewAction call to init():

<f:viewAction action="#{dataverseLocaleBean.updateLocaleInViewRoot}"/>
<f:viewAction action="#{harvestingClientsPage.init}"/>

I chose the latter, at least for now. This actually sets the locale
properly for the entire page; so, strictly speaking, this makes the "f:view locale=..." line in the dataverse template unnecessary. But I chose to keep it there - because otherwise
localization isn't going to work in pages without the explicit init() method (though I'm not sure if we have any - ?).

There may be a simpler solution, that does not require modifying every xhtml page. Some way of making that viewAction call from the template - in a way that actually takes effect before the page's own init() is called. I honestly don't know.

(will add more)

harvesting clients page, with the fixes applied:
screen shot 2019-01-23 at 1 39 26 pm

@scolapasta - if you're online, please take take a look and let me know what you think...

In addition to the above, I'm wondering if we should refactor things a little; specifically, I'm not sure we even need this new dedicated DataverseLocaleBean... As it is, it does 2 things:

  • tracks the currently selected locale throughout the user's session. But does it need a bean of its own? - We already have a session-scoped bean: the actual session, DataverseSession. Any reason not to handle the locale setting there? (anything I'm missing?)

  • the other part is the methods that are not specific to any individual sessions - useLocale() that decides if we need the language dropdown (all it does, it checks if there's more than 1 language configured in the settings) and the methods that populate it if so. I feel it would make more sense to move these into the SettingsWrapper.

Let me know.

Also - probably out of scope - what about all the text messages in the API responses; are we ok with them always being in the locale that is the default for the specific Dataverse installation? (i.e., the configured locale on the server running the application).

(one alternative would be to default to that, but then also try to honor the "Accept-Language" header in the HTTP request, if possible...)

(the current solution appears to be working well; I'll sleep on it over the weekend and make a PR before next week)

The code in the PR has been refactored as outlined above: the session-scoped bean DataverseLocaleBean has been removed; its functionality split between DataverseSession and SettingsWrapper.

Assigning to @matthew-a-dunlap because of his pre-volunteering in standup this morning :)

@landreev The only thought I had for not including on every xhtml would be to have every page bean extend from a base bean that had a default init method that does this and then calls a the page specific init method (renamed to _init or something else). Would still require making lots of changes now, but would be more maintainable if we had any other such changes.

Probably not worth the effort right now, but something to consider for the future.

Was this page helpful?
0 / 5 - 0 ratings