I am using Grails 2.0.3 in my project. I would like to implement internationalization to my application. As far as I read from this documentation I understand Grails have an out box support for internationalization. However I would like to override browsers Accept-Header setting and would like to set users language preference.
First I've created a filter in order to catch requests and check the language preferences. But it did not help. In filter I can get localized messages but when page is rendered I am getting English page. Here is the code that I use for setting locale.
def locale = new Locale("es", "ES")
java.util.Locale.setDefault(locale)
Then I've created custom LocaleResolver and injected that in spring configuration as localeResolver. Again in filter I can see localized messages however in pages still no luck?
Is there a way to override or bypass browsers setting in Grails i18n support?
The default LocaleResolver of Grails is SessionLocaleResolver. If you want to always use es_ES you can change this to FixedLocaleResolver.
beans {
localeResolver(FixedLocaleResolver) {
locale = new Locale("es", "ES")
}
}
If you want to restrict to a set of locales, then you will need a filter, and use the SessionLocaleResolver#setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) method.
Related
Working in ZF: Is it possible to change the base or root url on the www.example.com to www.example.com/$language/home, thus depending on the (browser) locale of the users browser?
Example; If a guest manually types www.example.com I would like to change the url automatically to a url with locale: www.example.com/en/home for guests in en_GB region or www.example.fr/home for guests in fr_FR region.
From the root-url I have all the menu-urls and content locale aware. Clicking a link to a menu item in the url the lang is automatically added after the root. The content on the root url is locale aware too using translate, so english for en_GB en french for fr_FR, etc.
Still missing though I would like to have the root url change to locale aware right from the start of the visit to the application if only the root is entered.
I guess something like
root :to => redirect("/prepayments")
in Rails 3 from what I understand from this Q&A on this forum
I have tried and implemented controller action helpers, redirects, etc. etc. for as far as I could find on this forum, but they all don't offer the solution.
A redirect in htaccess is not possible I think since I first need to get the locale from the browser. Since I don't know this the redirect is dynamic and I cannot set a redirect in htaccess.
I woud appreciate any suggestions?
Since I don't know what version of Zend you're using I am posting this for Zend 1.1x. One thing you could do is "catch" the request before it is dispatched, get the Accept-Language header and based on the user's preferences there set the locale or redirect the user to a URL you like. One way to do this is in the FrontController's preDispatch() method.
Keep in mind that:
You will need to check if all browsers send this through
This header string must be parsed careful
Because of the way it is defined:
Accept-Language en,bg;q=0.7,en-us;q=0.3
Also users may and often do set language preferences to a foreign language so this header on its own may not be enough.
The best way to do this in a OOP way is to wrap this functionality in a ZendPlugin.
Attach it in your bootstrap:
protected function _initLocaleHandlerControllerPlugin() {
$frontController = Zend_Controller_Front::getInstance();
$plugin = new App_Controller_Plugin_LocaleHandler();
$frontController->registerPlugin($plugin);
}
Now in this plugin redefine the preDispatch() callback:
public function preDispatch(Zend_Controller_Request_Http $request) {
$acceptLang = $request->getHeader('Accept-Language');
//Parse string and get language
//After parsing set the appropriate locale in `Zend_Locale`
//redirect the user/dispatch the request?
//THIS IS JUST AN EXAMPLE:
$request->setModuleName('home')
->setControllerName('registration')
->setDispatched(true);
}
Zend 1.x doesn't seem to have a built in class for this, Zend 2 does have the "Zend\Http\Header\AcceptLanguage" class.
I finally found the next solution on my question with a little help from Florent in Zend Framework: Redirect from action helper:
In my Language Plugin I added
public function routeShutdown(Zend_Controller_Request_Abstract $request)
{...some code handling translate...
$url = $request->getRequestUri();
if ($url === '/') {
$redirector = Zend_Controller_Action_HelperBroker::getStaticHelper('Redirector');
$redirector->gotoUrl($lang.'/home');
}
The routes I have them in a routes.ini so $lang.'/home' is routed to the indexController and indexAction of the Default module.
I have a Grails web application running on a german localized machine.
How does Grails determine the language to use? From the webbrowser? From the systems setting? Is this changeable with altering the language used for the ui (eg with this one: http://grails.org/plugin/lang-selector)? If not, how is it changeable?
Reason is that (seldom) i have users that access the webapp via (english) terminalserver. And there is some strange behaviour with number input (comma, dot, ...)
From http://grails.org/doc/latest/guide/i18n.html
By default the user locale is detected from the incoming
Accept-Language header. However, you can provide users the capability
to switch locales by simply passing a parameter called lang to Grails
as a request parameter:
/book/list?lang=es
Grails will automatically switch the user's locale and store it in a
cookie so subsequent requests will have the new header.
Also you can configure the default locale as follows. Place
beans = {
localeResolver(SessionLocaleResolver) {
defaultLocale = new Locale("ru", "RU")
java.util.Locale.setDefault(defaultLocale)
}
}
in the resources.groovvy file
We know that passing the lang parameter in the URL changes the locale of the grails application
/url?lang=de
In the code I can get the locale by RequestContextUtils.getLocale(request), which returns the locale set in the ParamsAwareLocaleChangeInterceptor (part of grails source), using the lang parameter.
If a script or corrupted string is passed as value to the lang parameter, then the same crap gets set as locale.
/url?lang=>"'><script>alert(167) </script>&=>"'><script>alert(167)</script>
with this request, the Content-language in the http header is set to the script= value of lang parameter. After this RCU.getLocale() returns this malicious script which messes up the content of my site, as a lot of content is decided based on locale. Is the a way to get around this problem (sanitize the lang before setting the locale) or is this a grails bug?
Also, can I restrict what is being passed in lang? For ex: if only 'en' and 'de' are supported on the site, the passing /url?lang=es messes up the content. is there a way I can restrict the value of lang parameter to only 'en' and 'de', may be in a filter or something, before the change of locale happens in the grails interceptor?
I can think of 3 possible options.
1) To restrict the lang you could set the locale in a Filter upon each request. But this you are resetting every time on a reload.
def filters = {
before = {
def locale = new Locale("sv","SV")
RCU.getLocaleResolver(request).setLocale(request, response, locale)
}
}
2) You could delete all message properties files leaving only the messages.properties files. So the system will always default to this property file.
3) you could setup a LocaleResolver in your config/spring/resources.groovy to set the default locale.
I am using shiro to protect my grails application, using the default setup as with
grails shiro-quick-start
and a custom user. So far, all controller actions are protected, but if I put in the URL to a GSP-File (say, index.gsp), I do not get a login prompt.
The default filter I use is
def filters = {
all(uri: "/**") {
before = {
accessControl()
}
}
}
but seemingly GSP-Files do not match this URI-Filter. What URI-Filter do I have to use? I am using grails 1.3.7 and shiro plugin 1.1.3
very interesting, but seems to be a grails problem, not a shiro one.
I didn't manage to secure /object/view.gsp pages through the filters mechanism - it seems to be based on controller/action and since there is no controller involved...
But I did find another solution. Add the following line to your UrlMappings.groovy file
"/$folder/${view}.gsp"(controller:'auth', action:'login')
this will send your .gsp files through a controller.
How can I change the current locale ?
I tried to put controller/action?lang=de but my locale is still en_US
I tried to override the value using this piece of code:
def key = "org.springframework.web.servlet.DispatcherServlet.LOCALE_RESOLVER"
def localeResolver = request.getAttribute(key)
localeResolver.setLocale(request, response, new Locale("de","DE"))
Nothing changed.
I tried to override the value using this piece of code:
import org.springframework.web.servlet.support.RequestContextUtils as RCU;
RCU.getLocaleResolver(request).setLocale(request, response, new Locale("de","DE"))
And... nothing happened. i still got my locale set to en_US.
Any idea to change the locale ?
According to the chapter 10. Internationalization of the Grails documentation, Grails supports i18n out of the box and you should indeed be able to change the locale using the lang parameter:
By default the user locale is detected
from the incoming Accept-Language
header. However, you can provide users
the capability to switch locales by
simply passing a parameter called lang
to Grails as a request parameter:
/book/list?lang=de
Grails will automatically switch the
user locale and store it in a cookie
so subsequent requests will have the
new header.
But sometimes you may want to preset the default language because not all your applications will be in english. To do this, all you have to do is to set your localeResolver in your resources.groovy spring configuration file as shown below:
beans = {
localeResolver(org.springframework.web.servlet.i18n.SessionLocaleResolver) {
defaultLocale = new Locale("de","DE")
java.util.Locale.setDefault(defaultLocale)
}
}
Now, without more details, I can't say why using the lang parameter isn't working in your case. Just in case, how do you know that the locale is still en_US?.
As far as I understand the way you are checking the locale "request.locale" is wrong, it gives the locale of browser, not the locale of grails applciation.
You should use "LocaleContextHolder.locale".
In 2.0.3 it changes the locale by simply passing parameter lang=someLocale.
Do you try to change locale in application root url (eg. http://localhost:8080/myapp/?lang=de)?
In Grails basic setup trying to change locale in application root url does not work. Grails change locale in localChangeInterceptor which is called before all controllers are called. When you access application root url, no controller is called as can be seen in default UrlMappings.
That's why changing locale in application root url does not work. If you try to change url in some controller, it works.
Current locale is stored under key org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME in http session. You can check it there.
Correct solution is to map root url to some controller in UrlMappings.
This is problably way too late but for reference, I do this in my index page controller:
session['org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE'] = new Locale("es", "PR")
I had a similar issue, and it was because a space. I had:
[space]messages_de.properties instead messages_de.properties
I had a problem with this awhile back when proxy-ing through an older version of Apache2.2 and using the grails (2.3.9) war file. I've had better luck using mod_proxy_html (3.1) / Apache 2.4. Maybe more advanced versions of grails fix this.