Link to home
Start Free TrialLog in
Avatar of rospcc
rospcc

asked on

Multiple Language Support Dilemma

I am trying to develop a new application which supports multiple languages by just a click of a button. Starting from scratch seems really easy and fun. After all, it is a new application and you get to decide how to go about doing it.

Now the problem arise because I have an existing application, and it is very huge in size (about 200 JSP forms and 100 JAVA files), which needs to implement this multiple languages feature as well.

Say I have a screen which shows a list of animal names in English and when the user clicks on Dutch, the list will be presented in Dutch accordingly.

Assuming I have a function called “getAnimalNames()” which previously does not require any parameter. In order to implement the multi language feature I need to know what language does the user wants it to appear as. Probably I should change it to “getAnimalNames(LanguageType)”.

What would be the easiest way to implement this without having to run through 200 pages of JSPs and 100 JAVA one by one just to introduce an extra parameter to each and every of the functions/methods?
Avatar of bloodredsun
bloodredsun
Flag of Australia image

The best way would be to implement the fmt library from JSTL which allows both internationalization (i18n) and localization (l10n). This would require recoding your jsps to some small extent but it would be very simple as it uses properties file and resource bundles which would mena leaving your java classes alone.

This is a classic link that should show you how it is done http://www.onjava.com/pub/a/onjava/2002/09/11/jstl2.html 

This was the approach I used for a site that had to deal with both English and Chinese customers.
Hi,

I totally agree with bloodredsun in this but I think that you need to change your 200 JSPs as well as modify your 100 Java files. I know that it may be tedious but it would be the best bet for the long run. If the contents are too much, you can consider it to store in DB, you can customize fmt to get the data from DB instead of properties file.

David
Avatar of rospcc
rospcc

ASKER

Hi bloodredsun,

It seems like even with the internationalization, I still need to modify all the 200 JSPs and 100 Java files. Please correct me if I am wrong.

Let's say if previously I have a function like this:

public void insertData (int value)
{
      String sql = "INSERT INTO table1 (Age) VALUES ("+value+");
}

And because I need to support multiple language I have to modify it to this:

public void insertData (int value, int Language)
{
      String sql = "INSERT INTO table1 (Age, LangVer) VALUES ("+value+", "+Language+");
}

So the way I call this function from JSP has to be changed from:
FUNC.insertData(iValue);
to
FUNC.insertData(iValue, iLang);

Is there any way to implement without modifying all the JSP pages? I know that I have to change my JAVA files for sure and that's not a concern.
>>I still need to modify all the 200 JSPs and 100 Java files

No. Using the fmt libs you would need to modify the JSPs not the java files. The resource bundles work by using a key, which is normally the value in your default language.

e.g.
-- In your JSP
<fmt:message key="welcome" />

--in the default resource bundle test.properties
welcome=Welcome

--in the french resource bundle test_fr.properties
welcome=Bonjour

This is just one approach, the benefits being the once you have done this you can easily extend your supported languages by adding a new resource bundle.


Avatar of rospcc

ASKER

Hi bloodresun,

Could you please explain how do I implement that in my example above? I still do not get it how will you implement this without changing the JAVA.
because the key remains the same, i.e. the java class outputs the same value, the fmt tags then do the job of translating this value.
Avatar of rospcc

ASKER

Hi bloodredsun,

I do not want just to display in different languages. My application involves saving text in different languages as well.

For example you have a list of animal names in this manner:

----------------------------
            Animal            |
----------------------------
     ENG     |    INA        |
----------------------------
 DRAGON   |                |
----------------------------

I do not want the application to just translate DRAGON to another language. I will need the user to be able to insert a new value for the INA part. Do you get what I am trying to say?
Ah, apologies fror that.

In this case, you will have to handle the internationalization yourself. This shiouldn't be to hard however. You are right in that you will need to modify your java classes to accept a language parameter as your database tables will need to associate the language with the word.

How you do this depends on what you are gouing to do with this data but I would recommend that you move the language into it's own table so that you reference it separately.

----------------------------
            Language        |
----------------------------
     ENG     |    INA        |
----------------------------
      1        |       2        |
----------------------------

----------------------------
            Animal            |
----------------------------
     1         |       2        |
----------------------------
 DRAGON   |     foo       |
----------------------------


And that you use PreparedStatements rather than plain SQL statements for your database insertions and queries.

I can't really give you any more advice thatn this as I don't know the structure of your webapp - model 1 (pure jsps with helper classes), model 2(jsp with controller servlets) or MVC (Struts or JSF). Which one you have determines what you will need to do but it appears that you have the right idea in that you will need to pass a variable around, either in each request or in the session that will allow you to detect whuich language is being used.
Avatar of rospcc

ASKER

The webapps I am working on is based on model 1.

The suggestion that you gave above was what I originally thought of. However, I felt that it is not good enough because you have to do 1 more sql transaction before every sql transaction (that is to get the language "key"). (Method 1)

So, I came up with another idea which is to store this "key" in a JSP session instead. That way I can avoid having to open 1 more connection. (Method 2)

Of course there are pros and cons for both methods. For method 1, the one that you suggested above, the apps will be able to remember the last user's language preference setting.

For method 2, everytime user logs in we will assign a default key (say English) and he/she has to click on the respective language he/she wants to view the webapps in.

I guess there's no way out but to tamper with the JSP and JAVA files individually. *sigh*
>>I guess there's no way out but to tamper with the JSP and JAVA files individually. *sigh*

This is one of the problems with model 1 based webapps, there is no clean separation of application logic from presentation logic so changes to one means changes to both your JSPs and java classes.

You don't need to do another sql select but only need to store the language selection in the session, and persist this in a cookie if required. This is pretty much the only correct usage of cookies that I would use.
Avatar of rospcc

ASKER

If I were to store the language variable in cookies, will I be able to retrieve that value directly from JAVA or do I have to go through JSP first?
>>If I were to store the language variable in cookies, will I be able to retrieve that value directly from JAVA or do I have to go through JSP first?

As JSP is Java Server Pages, you will have to use Java either way! I guess you are talking about Java versus JavaScript. You can easily access Cookies in Java/JSP using this code

Cookie[] cookies = request.getCookies() ;

You can then iterate over the array of cookies and get the correct one using the method getName() like this

<%
//Get cookie array
  Cookie[] myCookies = request.getCookies();
  //If array is not null then display cookies
  if(myCookies!=null) {
    for (int n=0; n < myCookies.length; n++){
%>
        <TR>
          <TD><%= myCookies[n].getName() %></TD>
          <TD bgcolor=""><%= myCookies[n].getValue() %></TD>
        </TR>
<%
    }
  }
%>
Avatar of rospcc

ASKER

I am talking about Java and not JavaScript. From the code you provided above, it seems like I have to get the value from the cookies through JavaScript/JSP, am I right?

If it is alright with you, could you also provide me codes or links on how to set the cookies?

A bunch of thanx bloodredsun.
>>it seems like I have to get the value from the cookies through JavaScript/JSP, am I right?

No, it can all be done in JSP and done more easily too. JavaScript handling of cookies is pretty rubbish

Here are two JSPs I made earlier (very Blue Peter!) that show you how to do exactly this :-)
--------------------------
getCookie.jsp
-------------------------
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html lang="en-uk">
<head>
<title>Cookies</title>
<link REL=stylesheet HREF="../css/styles.css" TYPE="text/css" />
</head>

<body style="margin: 10px;">
<H2>Cookie Analysis</H2>
<P>The following cookies have been registered on the client by this web application.</P>
<TABLE>
  <TR>
    <TH>Cookie Name</TH>
    <TH>Color</TH>
  </TR>
<%
//Get cookie array
  Cookie[] myCookies = request.getCookies();
  //If array is not null then display cookies
  if(myCookies!=null) {
    for (int n=0; n < myCookies.length; n++){
%>
        <TR>
          <TD><%= myCookies[n].getName() %></TD>
          <TD bgcolor=""><%= myCookies[n].getValue() %></TD>
        </TR>
<%
    }
  }
%>
</TABLE>


<H2>Cookie Cutter</H2>
<P>The following form allows you to specify a name and a value of a cookie that
you want to create. The JSP that receives this data 'makeCookie.jsp' contains
code that creates the cookie.</P>

<FORM name="frm" method="post" action="makeCookie.jsp">
<TABLE>
  <TR>
    <TD>Cookie Name</TD>
    <TD><INPUT type="text" name="CookieName"></TD>
  </TR>
  <TR>
    <TD>Value</TD>
    <TD>
    <INPUT type="radio" name="BackColor" value="green">green<BR>
     <INPUT type="radio" name="BackColor" value="black">black<BR>
     <INPUT type="radio" name="BackColor" value="red">red<BR>
    <INPUT type="radio" name="BackColor" value="blue">blue<BR>
  </TR>
  <TR>
    <TD align=left><INPUT type="reset" value="Reset" name="Reset"></TD>
    <TD align=right><INPUT type="submit" value="Submit" name="Submit"></TD>
  </TR>
</TABLE>
</FORM>

</BODY>
</HTML>
-------------------------
makeCookie.jsp
------------------------
<%
  String strMsg = "" ;
  String strCookieName = request.getParameter("CookieName");
  String strBackColor = request.getParameter("BackColor");

  if((strCookieName!=null)&&(!strCookieName.equals("")))  {
    if((strBackColor!=null)&&(!strBackColor.equals("")))    {
      Cookie c = new Cookie(strCookieName, strBackColor);
      response.addCookie(c);
      strMsg = "Cookie successfully created.";
    } else  {
      strMsg = "Must provide a Background Color.";
    }
  } else {
    strMsg = "Must provide a cookie name.";
  }
%>

<HTML>
<HEAD>
<TITLE>Make a Cookie</TITLE>
<LINK rel="stylesheet" type="text/css" href="../styles.css">
</HEAD>

<BODY>
<P><%= strMsg %></P>
<P>Click <a href="getCookie.jsp">here</a> to go back to the cookie page</P>
<HR>

</BODY>
</HTML>
Avatar of rospcc

ASKER

Say I have created a java file called "Animal.java" and there is a method "getAnimalNames(String category, int LangSet)". LangSet is supposed to get the value from the cookies.

Apart from passing it from the JSP like this:

<jsp:useBean id="A" class="Classes.Animal" scope="session"/>

A.getAnimalNames("Bird", myCookies[n].getName());

Can I directly retrieve the value from Java side?
>>Can I directly retrieve the value from Java side?

Yes, but not like that! You seem to have misunderstood the java in the for loop.

You would need to do this

<jsp:useBean id="A" class="Classes.Animal" scope="session"/>
<%
Cookie[] myCookies = request.getCookies();
String myCookieValue = "" ;
for (int n=0; n < myCookies.length; n++){
  if("NameOfCookie".equals( myCookies[n].getName() )) {
         myCookieValue  = myCookies[n].getValue() ;
  }
}
A.getAnimalNames("Bird", myCookieValue );
%>

You have to do this as a single request can have many cookies assocaited with it (the session cookie that keeps track of your session id is one of them) so you need to iterate over the array of Cookies to find the one with the name that you specified. More detail on the inner working of cookies can be found in that link I sent you.
Avatar of rospcc

ASKER

bloodredsun, you misunderstood me again.

The example that I gave above is just an example. I know that I have to include those in the for loop for it to work. The example that you just showed me is still processing in the JSP side. What I want to know is how can I retrieve this value from JAVA side.

Say in the Animal.java I have this:

public class void getAnimalNames(String sName)
{
    // I want to retrieve the value of the cookies here
    int iLangVer = <cookies value>;

    // So that I can use it in the SQL statement
    String sSQL = "Select * from tblAnimal WHERE Category = '"+sName+"' AND LangVer = "+<cookies value>+";

    // proceed to open connection and execute bla bla bla...
}

I hope you understand better what my requirement is and still: Can I do that?
>>The example that I gave above is just an example

Okay, but it was a fairly bad one in that it was not valid code.I don't know your level of knowledge so when you make an error I don't know whether it's because it's a typo or that you don't understand so it's best if I at least mention it, no ;-)

>>What I want to know is how can I retrieve this value from JAVA side.

It all boils down to scope. If the <cookies value> variable is an instance variable rather than a local one, then it will be available to all the methods in that class without needing to pass it in as a method parameter.

I'm guessing that the above example is also incorrect in that you have decribed a malformed inner class (!) rather than a method as you had the "class" keyword in the modifiers of the method/constructor.

public class Animal{
    //method
    public void getAnimalNames(String sName){
    ....}
    //inner class
    public class getAnimalNames(String sName){
    ....}

Assuming that you want a method you could do this with your Animal class. This would allow you to set the value when you instanciate the Animal class and then not bother about it again.

public class Animal{

    private int iLangVer;

    public void setILangVer(int pInt ){
         this.iLangVer = pInt ;
    }

    public int getILangVer(){
        return this.iLangVer;
    }

    //method
    public void getAnimalNames(String sName){
        // So that I can use it in the SQL statement
        String sSQL = "Select * from tblAnimal WHERE Category = '"+sName+"' AND LangVer = "+ iLangVer  +";
        // proceed to open connection and execute bla bla bla...
}

See here for more details http://java.sun.com/docs/books/tutorial/java/javaOO/classvars.html regarding class/instance variable/members.
Avatar of rospcc

ASKER

I have actually tried your proposed solution above however it only works if there is a "communication" between 1 JSP and 1 JAVA. Because there are certain java files which will call methods/functions from other java files you see. What I mean is this:

Say I have 3 files (1 JSP & 2 JAVAs), test.jsp, test1.java, test2.java. Assuming that test1.java has the method you created above.

// In test.jsp
<jsp:useBean id="T" class="Classes.test1" scope="session"/>

T.setILangVer(2); // Instantiate value of iLangVer = 2
========================================
// In test1.java

public class test1
{
    test2 t2 = new test2();
    public int iLangVer;

    public void setILangVer(int pInt ){
         this.iLangVer = pInt ;
    }

    public int getILangVer(){
        return this.iLangVer;
    }

    public void sortAnimal(String sName)
    {
         // ***************************************************
         // Trying to pass iLangVer (which is supposed to be 2) but it got reset to 0
         String sCat = t2.getAnimalCategory(iLangVer);
    }

}
========================================
// In test2.java

public class test2
{
     public String getAnimalCategory(int iLangVer)
     {
           // do something here
      }
}

Please refer to the asteriks for my question/comment. Thank you for reading!
ASKER CERTIFIED SOLUTION
Avatar of bloodredsun
bloodredsun
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial