Search code examples
grailsinternationalizationhttp-accept-language

Grails i18n: Setting Accept-Language header


According to Grails' internationalization doc, i18n is accomplished by either:

  • Setting an Accept-Language header in the request; or
  • Tacking on a lang query string param

I'm opting for the former, because its more HTTP compliant and, frankly, I just don't like adding it as a query param.

But how would I set Accept-Language in the first place?!?

I want my app's locale to be determined by the TLD requested. So, a request for http://myapp.example.com would return the en_US version of my app, because *.com is traditionally associated with English/US. If http://myapp.example.fr was requested, then Grails should serve back the fr_FR version of my app. Etc.

So my real question is:

How can I map the requested URL/TLD to a variable that Grails can set on the server, and then inject into GSPs, such that client-side requests always have a matching Accept-Language header for the given URL/TLD?


Update

I want to confirm browser/Grails behavior here: is it safe to assume that when a user configures their browser, that the browser adjusts the Accept-Language header accordingly? If so, can I also assume that if Accept-Language is not sent, and lang is not specified as a query param, that Grails uses en_US by default?


Solution

  • You are making things more difficult for yourself than you need to be. Trying to set the locale on the server, inject into GSPs and deal with forcing client-side requests to modify their request headers (which is a horrible idea considering that header is intended for the user's browser to control, and not your applications) is over complicated.

    The simpler, and correct, approach would be to implement your own custom logic inside a new localeResolver bean inside your Grails application.

    This bean could first check your own custom lookup based on the request.getRequestURI() and decide what the locale should resolve to. You could even have it fall back to the default behavior there afterwards as well.

    The key to implementing this, again, is to understand the existing localeResolver and understanding how to replace it. You will have to dig into the internals of Grails (and Spring) to discover this.

    To replace the default implementation you just need to redefine the bean within your resources.groovy. The re-implementation is entirely up to you.

    Update

    Some additional information to get you headed in the right direction.

    By default, your resources.groovy file won't contain this bean definition for your project. It's up to you to create a new entry there that will replace the one created by the framework.

    To understand what kind of bean you are to be implementing you should take a look at the LocaleResolver interface. Depending on how you approach this problem you will either be implementing this interface or extending the Grails implementation.

    The Grails implementation of the i8n plugin on Github and how it setups the locale resolver. You will notice the default implementation is the SessionLocaleResolver provided by Spring.