views:

2265

answers:

3

I have a web-app that I would like to extend to support multiple languages with new URLs. For example, www.example.com/home.do stays English, but www.example.com/es/home.do is Spanish. My first thought was to create a Filter which rewrites incoming urls like /es/home.do to /home.do (and sets the Locale in the Request); this works fine. The Filter wraps the ServletRequest with an HttpServletRequestWrapper which overrides getContextPath() to return the language:

class FakeContextRequest extends HttpServletRequestWrapper {

  private String context = "";
  FakeContextRequest(HttpServletRequest request, String context) {
    super(request);
    // snip some validation code
    this.context = request.getContextPath() + context;
  }
  @Override
  public String getContextPath() {
    return this.context;
  }
}

My Filter forwards to the appropriate request as follows:

FakeContextRequest fr = new FakeContextRequest(request, lang);
fr.getRequestDispatcher(newResourceName).forward(fr, response);

My problem is that the next servlet doesn't forward properly. The next servlet (typically a Struts ActionServlet) forwards to a JSP (often using Struts Tiles); when I get to the JSP the HttpServletRequest has been wrapped several times and the object in question reports the context to be empty (the root context, which is where the application is actually deployed).

I want the context to be re-written so that all my context-aware code that already exists can automatically insert the language into the URLs that are written. Is this possible?

Edit: I solved my problem by using a wrapped HttpServletResponse instead of a wrapped HttpServletRequest; I rewrite the URL in the response.encodeURL() method.

+1  A: 

As far as I know, the conventional way to do this is with the accept-language HTTP header. The presentation language is a presentation detail, which shouldn't be represented by the set of URLs to navigate through the application.

David M. Karr
The accept-language header won't work, because it's not compatible with search engines. Search engines need unique links in order to spider the content in different languages.
Mr. Shiny and New
+1  A: 

I'm not sure that overriding getContextPath() is enough to solve your problem. What if Struts is calling ServletContext.getContextPath() under the covers, or uses getRequestURI(), etc?

matt b
Good point. I will have to find another approach, it seems.
Mr. Shiny and New
A: 

I solved my problem by doing URL Rewriting in response.encodeURL() and friends. The request object gets wrapped and replaced throughout the request chain but the response object seems to make through unmolested. This works very reliably.

Mr. Shiny and New
I think this is the method used in the UrlRewriterFilter project http://tuckey.org/urlrewrite/
Brian Clozel