Spring permission: messages in javascript for i18n internationalization

I am trying to internationalize part of our code. I have a page in JSPX that uses the <spring:message> to resolve lines from message.properties file. This works great for the HTML and CSS that are on the JSPX page, but there is a javascript file there, and replacing the <spring:message> with a line there simply means that it prints verbatim.

My JSPX creates javascript like this:

 <spring:theme code="jsFile" var="js" /> <script type="text/javascript" src="${js}" /> 

JS where I am looking for a string replacement is below:

 buildList('settings', [{ name: '<spring:message code="proj.settings.toggle" javaScriptEscape="true" />', id:"setting1", description: '<spring:message code="proj.settings.toggle.description" javaScriptEscape="true" />', installed: true }]); 

And finally, message.properties looks something like this:

 proj.settings.toggle=Click here to toggle proj.settings.toggle.description=This toggles between on and off 

So I wonder if this work should? It seems to me that this is necessary, from what I have gathered in different forums, but I canโ€™t understand where I am mistaken. Is there a better way to do this?

I should also note that these files are outside the WEB-INF folder, but by placing the ReloadableResourceBundleMessageSource file in the root file applicationContext.xml, spring tags are selected.

Thanks for any help!

+22
javascript spring spring-mvc internationalization dojo
Jun 02 '11 at 18:51
source share
3 answers

It seems to me that you want to process a JS file, such as a JSP file, and allow its contents using the spring: tag. I would not do that.

Typically, the JS i18n runs in one of two ways:

  • Writing an Array of Translated Strings from a JSP Page
  • By creating a translation filter and providing a previously translated JS file to the requesting client

Both work best if you create one central location for your client-side translation strings.
In your context, I would recommend the first method (much simpler). That is, if your project is quite large and you have many translatable strings on the client side. Thus, the modification will look like this:

 <script type="text/javascript"> var strings = new Array(); strings['settings.toogle'] = "<spring:message code='proj.settings.toggle' javaScriptEscape='true' />"; strings['settings.toogle.description'] = "<spring:message code='proj.settings.toggle.description' javaScriptEscape='true' />"; </script> <spring:theme code="jsFile" var="js" /> <script type="text/javascript" src="${js}" /> 

And in your JS file:

 buildList('settings', [{ name: strings['settings.toggle'], id:"setting1", description: strings['settings.toggle.description'], installed: true }]); 

Keep in mind that I used double quotes to write translated strings. This is due to some words in French or Italian that may contain an apostrophe.

Edit: auxiliary input

We provide translations to JS files for this reason. Usually the reason is because we want to dynamically create part of the user interface. There are also cases where we need to localize some third-party component, my answer above concerns them pretty well.
For cases where we want to dynamically create user interface elements, it actually makes sense to use templates, rather than concatenating HTML tags in JavaScript. I decided to write this because it makes a much cleaner (and possibly reusable) solution.
Therefore, instead of transferring translations to JavaScript, you can create a template and put it on the page (my example will use Handlebars.js , but I believe that you can use any other engine):

 <script id="article" type="text/x-handlebars-template"> <div class="head"> <p> <span> <spring:message code="article.subject.header" text="Subject: " /> </span>{{subject}}</p> </div> <div class="body"> {{{body}}} </div> </script> 

On the client side (i.e. in JavaScript), all you have to do is access the template (the example below explicitly uses jQuery) and compile:

 var template = Handlebars.compile($("#article").html()); var html = template({subject: "It is really clean", body: "<p>Don't you agree?</p><p>It looks much better than usual spaghetti with JavaScript variables.</p>" }); $("#someDOMReference").html(html); 

A few things to note here:

  • Tags
  • <spring:message /> by default excludes both HTML and JS, we do not need to specify the javaScriptEscape attribute
  • It makes sense to provide the text attribute for the <spring:message /> , since it can be used as a recession (if there is no translation for this language), as well as a comment (which means this element). You can even create a tool to scan files for <spring:message /> tags and automatically create property files
  • To prevent Handlebars from escaping HTML content, I used triple {{{curly braces}}}

This is basically it. I recommend using templates if possible.

+36
Jun 05 '11 at 12:17
source share

Thanks for your reply. Here is a more general solution.

The idea is to provide a dynamic javascript file called "string.js" containing an associative array of messages registered in the java resource bundle using the current user language.

1) Create a method in Spring Controller to load all resource keys from the resource set and return the view "spring.jsp"

 @RequestMapping(value="strings.js") public ModelAndView strings(HttpServletRequest request) { // Retrieve the locale of the User Locale locale = RequestContextUtils.getLocale(request); // Use the path to your bundle ResourceBundle bundle = ResourceBundle.getBundle("WEB-INF.i18n.messages", locale); // Call the string.jsp view return new ModelAndView("strings.jsp", "keys", bundle.getKeys()); } 

2) Implement View "strings.jsp"

 <%@page contentType="text/javascript" pageEncoding="UTF-8" %><%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><%@taglib prefix="spring" uri="http://www.springframework.org/tags" %>var messages = new Array(); <c:forEach var="key" items="${keys}">messages["<spring:message text='${key}' javaScriptEscape='true'/>"] = "<spring:message code='${key}' javaScriptEscape='true' />"; </c:forEach> 

3) Import "spring.js" into the HTML source code. The message array is accessible and loaded in the correct language.

Possible problem . If the user changes his language, "w761> .js" should be restarted by the navigator, but it will be cached. Clearing the cache is necessary when the user changes his language (or another trick to reload the file).

+17
Aug 14 '12 at 18:48
source share

In addition to @Toilal's answer, you can add a helper function for strings.jsp to make better use of the translation array:

 <%@page contentType="text/javascript" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> <%@taglib prefix="spring" uri="http://www.springframework.org/tags"%> var messages = new Array(); <c:forEach var="key" items="${keys}">messages["<spring:message text='${key}' javaScriptEscape='true'/>"] = "<spring:message code='${key}' javaScriptEscape='true' />"; </c:forEach> /** * Tranlate a String by her key, if key is not defined return the key. * * @author Pedro Pelรกez <aaaaa976 at gmail dot com>, Drupal/Wordpress authors, and others * @param {String} key * @returns {String} */ function t(key) { if (messages[key]) { return messages[key]; } return key; } 

Then if necessary just use:

 alert(t("menu.section.main")); 
+1
Apr 12 '17 at 13:38 on
source share



All Articles