12

I want to use JSTL's fmt tag in JavaScript to localize my alert messages. My JavaScript file is a standalone file and when I include fmt tag in js, the file browser gives JavaScript errors. Is it possible to treat .js file as .jsp files using web.xml configuration? Can anyone please suggest how can I do that?

Widor
  • 13,003
  • 7
  • 42
  • 64

7 Answers7

20

is it possible to treat .js file as .jsp file using web.xml configuration?

Yes:

<servlet>
    <servlet-name>scriptjsp</servlet-name>
    <jsp-file>/script.jsp</jsp-file> 
</servlet>
<servlet-mapping>
    <servlet-name>scriptjsp</servlet-name>
    <url-pattern>/script.js</url-pattern>
</servlet-mapping>

But, there is no actual advantage in doing this, because JavaScript files do not have to have URLs ending in ‘.js’. What determines whether a file is a JavaScript file is what MIME media type it is served as. You can set this from JSP using:

<%@ page contentType="text/javascript" %>

at the top. Then you can link directly to:

<script type="text/javascript" src="/script.jsp"></script>

(Aside: in current browsers, scripts linked to with the <script> tag will work even without having the Content-Type properly set, but that's probably not something to rely on.)

I want to use JSTL's fmt tag in javascript

This is probably not a good idea. The fmt tag deals with HTML-escaping for characters, but what you want is JavaScript string literal escaping, for example to backslash-escape quote characters. JSTL doesn't provide this capability. You'll get unexpectedly-escaped ‘&amp;’ characters showing up in your JavaScript strings, and use of apostrophe or double quote in messages will break the whole script.

Also, serving commonly-included scripts from JSP risks poor performance and cacheing.

I'd suggest an independent language lookup system in JavaScript. For example, include a per-language external script:

<script type="text/javascript" src="/script/lang/en.js"></script>

(changing 'en' to match whichever language you want), and in that file define a lookup like:

var msg= {
    messageName: 'Message in English',
    ...
};

Then look up msg.messageName for each localisable string in the script.

bobince
  • 528,062
  • 107
  • 651
  • 834
  • thanks for the explanation. It is posted while back, wonder if I can ask how to load the specific language js file in the jsp? i.e. if I get the locale and would like to only load that corresponding js in the jsp file so that the msg object could be used in other javascript file? lang_xx.js could be lang_en.js or lang_fr.js – lannyf Jan 14 '16 at 21:30
  • You mean `.js">` ? – bobince Jan 15 '16 at 11:59
  • thank you bobince. would this work: in one earlier script block do: then in following script section: .js">. I'm not sure in JSP how to refer the var defined in other script block if in some case it do need to. – lannyf Jan 15 '16 at 13:23
  • That wouldn't work because the `getParameter` output is injected into JavaScript without quoting or escaping. `<%=` without explicit escaping is an XSS security hole; never do that. If you want to get a string into a JavaScript variable you can use a library to do JavaScript string literal escaping, but it is usually simpler to inject it into HTML (with implicit HTML escaping by using eg `

    ">` and then reading `var langCode = document.body.getAttribute('data-lang-code');`.

    – bobince Jan 15 '16 at 22:01
6

If your javascript is 'inline' with the rest of your JSP page, then simply use the technique suggested by Kees de Kooter.

If your javascript needs to be in an external file (For sharing across pages, for example) then simply put it in its own JSP file.

<%@page contentType="text/javascript" %>
<fmt:message key="some.message" var="someMessage"/>"
<fmt:message key="another.message" var="anotherMessage"/>"
var someMessage = "${someMessage}"
var anotherMessage = "${anotherMessage}"/>"

And include it like this...

        <script src="yourScript.jsp" language="JavaScript" type="text/javascript"></script>

You can then refer to 'someMessage' and 'anotherMessage' from within the file that includes the JSP, or from any javascript file that is included after 'yourScript.jsp.

Note the use of the contentType attribute - 'text/javascript' prevents the JSP parser from complaining that the output isn't well formed XML - and that the tage refers to a JSP file.

A combination of this technique and that suggested by @Magner should bring you to a sensible solution.

EDIT: Changed the example to use 'text/javascript' insetad of 'text/plain' - thanks to @bobince for making me realise this error (Even though 'text/plain' works, it's more correct to use 'text/javascript'). Also, if the number of strings that need to be internationalised is small, and/or you can justify having your 'resources' in more than one place - one for the server side stuff and another for the client side stuff - @bobince's technique of using dynamic includes is a good one.

belugabob
  • 4,302
  • 22
  • 22
5

I would suggest you write a servlet that generates an array or javascript object that contains all the localized information you desire. You can use Java resource bundles which can be shared by both the client and server sides, then you don't have to intermix JSP code and Javascript code, and the servlet response will be cached by the browser.

Create a servlet, map it to a path, have it read the locale from a request parameter then generate the Javascript code.

Use a line like <script src="/mydict?lang=en"></script> then load you script afterwards <script src="/myscript.js"></script>

BeWarned
  • 2,280
  • 1
  • 15
  • 22
4

You should strive to keep your javascript code in a separate file from the jsp-code. This is to get browser caching, easier maintenance, reuse across pages, and to allow compression.

I suggest that you create a global object for text in the jsp, to be used by your javascript files. Like this:

<script>
    var text = text || {}; // play well with other jsps on the page
    text.this_page_name = {
        required_field_error: "<fmt:message key="required.field.error"/>",
        system_error: "<fmt:message key="system.error"/>"
    };
</script>

Later you use it in your javascript:

alert(text.this_page_name.required_field_error);
Magnar
  • 28,550
  • 8
  • 60
  • 65
3

You could do the following. You store the translated message in a variable that can be resolved later on in the JSP.

<fmt:message key="your.alert" var="theAlert"/>

<script type="text/javascript">
alert("${theAlert}");
</script>
Kees de Kooter
  • 7,078
  • 5
  • 38
  • 45
  • This requires that you inline all your javascript. The javascript should really be separated in its own file, for browser caching, easier maintenance, reuse across pages, and to allow compression. – Magnar Mar 11 '09 at 08:16
  • Then make the javascript file qualify as JSP by tweaking your default web.xml file. Then the JS file is both, javascript AND JSP. The file extension is simply that, an extension. Use whatever you want. Works great with CSS files as well. – Will Hartung May 05 '09 at 01:00
1

You can't use tags in JavaScript but there is a workaround: Put the tag into an hidden DIV (<div style="display: none;" id="msg"><fmt:...>

Now you can use JS to look up the DIV by its ID and get the innerHTML.

That said, fmt is just a wrapper for Java's i18n functions which you can use directly between <% %>.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
0

If you are going for only alert messages just use this tag in your javascript

Suppose you have following in your Javascript:

alert("Confirm Deletion"); 

This can be internationalized by adding bean:message tag in your javascript

alert('<bean:message key="msg.confirm"/>');

and add key value in property file

msg.delete=Confirm Deletion
Jayanth Koushik
  • 9,476
  • 1
  • 44
  • 52