How can I force Grails to use only one language? - grails

I want to make my Grails application support only one language, that I can define somewhere, completely ignoring the client's headers or the "lang" parameter. Is there any way I can do so? Thanks.

Define a LocaleResolver bean in your config/spring/resources.groovy to set the default locale.
beans = {
localeResolver(org.springframework.web.servlet.i18n.SessionLocaleResolver) {
defaultLocale = new Locale("de","DE")
java.util.Locale.setDefault(defaultLocale)
}
}
This is useful if you don't have to deal with the lang parameter - otherwise it would get overridden. To even ignore the lang parameter value you can set the locale in a Filter upon each request:
import org.springframework.web.servlet.support.RequestContextUtils as RCU
...
def filters = {
all(controller:'*', action:'*') {
before = {
def locale = new Locale("sv","SV")
RCU.getLocaleResolver(request).setLocale(request, response, locale)
}
}
}
This approach seems a bit repetitive as Locale is re-set on every request. It would be more elegant to disable the browsers locale detection via an config option.

The default LocaleResolver of Grails is SessionLocaleResolver. If you want to always use de_DE you can change this to FixedLocaleResolver.
beans {
localeResolver(FixedLocaleResolver) {
locale = new Locale("de", "DE")
}
}
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.

remove all messages_xx.properties files and keep only the messages.properties files.
This is the default message bundle to which the system will always fall back if it can't find the right message bundle.
This way you can still use messages (and thus keep the option to nationalize your app) but users will get always the same language.

This worked for me in order to override the default localResolver bean
beans = {
localeResolver(org.springframework.web.servlet.i18n.FixedLocaleResolver) {
setLocale(Locale.US)
}
}

Related

Change Grails REST format /controller/<id>/<action>

I messed around with this a bit yesterday and failed miserably. I want to convert:
"/$controller/$action?/$id?"
To
#in psudo
"/$controller/$id?/$action?"
#ideal regex
"\/(\w+)(\/\d+)?(\/\w+)?"
The most obvious way failed "/$controller/$action?/$id?"
I can write the regex's to do it, but I am having trouble finding a way to using true regexs (I found RegexUrlMapping but could not find out how to use it), and also can't find documentation on how to assign a group to a variable.
My question is 2 parts:
How to I define a URL Resource with a true regex.
How to I bind a "group" to a variable. In other words if I define a regex, how do I bind it to a variable like $controller, $id, $action
I would also like to be able to support the .json notation /user/id.json
Other things I have tried, which I thought would work:
"/$controller$id?$action?"{
constraints {
controller(matches:/\w+/)
id(matches:/\/\d+/)
action(matches:/\/\w+/)
}
}
also tried:
"/$controller/$id?/$action?"{
constraints {
controller(matches:/\w+/)
id(matches:/\d+/)
action(matches:/\w+/)
}
}
The grails way to deal with this is to set
grails.mime.file.extensions = true
in Config.groovy. This will cause Grails to strip off the file extension before applying the URL mappings, but make it available for use by withFormat
def someAction() {
withFormat {
json {
render ([message:"hello"] as JSON)
}
xml {
render(contentType:'text/xml') {
//...
}
}
}
For this you'd just need a URL mapping of "$controller/$id?/$action?"
I'm not aware of any way to use regular expressions in the way you want in the URL mappings, but you could get a forward mapping working using the fact that you can specify closures for parameter values that get evaluated at runtime with access to the other params:
"$controller/$a?/$b?" {
action = { params.b ?: params.a }
id = { params.b ? params.a : null }
}
which says "if b is set then use that as the action and a as the id, otherwise use a as the action and set id to null". But this wouldn't give you a nice reverse mapping, i.e. createLink(controller:'foo', action:'bar', id:1) wouldn't generate anything sensible, you'd have to use createLink(controller:'foo', params:[a:1, b:'bar'])
Edit
A third possibility you could try is to combine the
"/$controller/$id/$action"{
constraints {
controller(matches:/\w+/)
id(matches:/\d+/)
action(matches:/\w+/)
}
}
mapping with a complementary
"/$controller/$action?"{
constraints {
controller(matches:/\w+/)
action(matches:/(?!\d+$)\w+/)
}
}
using negative lookahead to ensure the two mappings are disjoint.

Set value in message.properties file from grails service

I want to set values to message.properties file.
I have already done it in java like the following:
Properties emailErrorMsgProp = new Properties();
emailErrorMsgProp.load(new FileInputStream("grails-app/i18n/messages.properties"));
emailErrorMsgProp.setProperty("ma_email_error",result.callStatusMsg.toString());
emailErrorMsgProp.store(new FileOutputStream("grails-app/i18n/messages.properties"), null);
I also want to make it language specific.i have language specific properties files.
I would like to do the same thing in grails Service, but how would I go about it?
Try this:
def writeToProps(key, value) {
new File("grails-app/i18n/messages.properties").withWriterAppend { out ->
out.writeLine "\n${key}=${value}"
}
}
You should take a look at ReloadableResourceBundleMessageSource.

Store and use application configuration settings in database for a Grails application?

we currently use configuration files to store application settings. I was wondering if it is possible to store these settings inside the database and if so how to achieve this?
Greetings
You can store whatever you want in the database and read it out using a Domain class. This is especially useful if you want to be able to make changes to things without having to redeploy new code. But realize that you will incur a database hit every time the property is accessed.
You can set up a ConfigurationService with:
ConfigurationService {
static def configurationValues
def getConfigurationValues() {
if(configurationValues == null) {
refreshConfigurationValues()
}
configurationValues
}
def refreshConfigurationValues() {
configurationValues = //go get the values out of the database
}
}
Then you can add a Controller/Action to force the refresh when necessary
ConfigurationController {
def configurationService
def refreshConfiguration = {
configurationService.refreshConfigurationValues()
render "Ahhh... That's refreshing :)"
}
}
Now you can refresh your config values by invoking: "http://yoururl/appName/configuration/refreshConfiguration"
This is can be done with BootStrap.groovy. So following Jarred's answer, create a domain class of the configuration data you would like to store and then inside the BootStrap.groovy file, put these values. What this does is if the configuration values does not exists, it will create it, if it exists will not do anything.
Then you can access your configuration values using the domain class. I'm assuming you want to do this because grailsApplication.config... can sometimes become unruly.
Domain-Class MyConfig.groovy:
class MyConfig {
String type
String name
String value
}
BootStrap.groovy:
def myConfig = MyConfig.findByName("path") ?: new MyConfig(
type: "Path"
name: "path"
value: "/var/tmp"
).save(failOnError: true)

Grails i18n from property files backed up by a DB?

i am trying to get a situation where i can use i18n property files which are backed up with a database?
So for some standard stuff i would like to use the property files, but some fields must be editable by the end-user so i was planning to use i18n in the database for that. So a real combination would be great. If the i18n code cannot be found in the property files then do a lookup in the DB.
Any idea how i can tackle this? I have seen the post Grails i18n From Database but Default Back To File
But there is no real answer to the problem, any other suggestions on how to tackle this?
Put a new domain class into your project:
class Message {
String code
Locale locale
String text
}
Add the following lines to your resources.groovy:
// Place your Spring DSL code here
beans = {
messageSource(DatabaseMessageSource) {
messageBundleMessageSource = ref("messageBundleMessageSource")
}
messageBundleMessageSource(org.codehaus.groovy.grails.context.support.PluginAwareResourceBundleMessageSource) {
basenames = "WEB-INF/grails-app/i18n/messages"
}
}
And add the following class to your src/groovy folder:
class DatabaseMessageSource extends AbstractMessageSource {
def messageBundleMessageSource
protected MessageFormat resolveCode(String code, Locale locale) {
Message msg = messageBundleMessageSource.resolveCode(code, locale)
def format
if(msg) {
format = new MessageFormat(msg.text, msg.locale)
}
else {
format = Message.findByCodeAndLocale(code, locale)
}
return format;
}
}
Now grails will try to resolve the message from the message bundle. If it is not available, it will look it up from database. You could add some error-handling, but this version works, if all messages are available at least in one place.
See http://graemerocher.blogspot.com/2010/04/reading-i18n-messages-from-database.html for some more details.
Some details on the changes done in resources.groovy:
In this file you can define injectable groovy classes, which can be included by just defining a variable having the same name as defined in the resources.groovy. E.g. in this file, there are messageSource and messageBundleMessageSource, which you can be include in any controller or service files. If this variable is defined, an instance of the class in the brackets is created.
In this case, we overwrite the general messageSource to use our custom implementation DatabaseMessageSource. So the I18n function message will now use our custom implementation.
Since our custom implementation requires to check the message.properties-files we keep the original message source in the second bean. By defining this instance in our custom implementation, we can still use the old implementation (and therefore looking up messages the usual way).
I'm not sure I know what you mean by
i18n property files which are backed up with a database
But if you simply mean that you want the message keys to be resolved using a database table (instead of a .properties file), then you can do this by writing your own implementation of the MessageSource interface
class DBMessageSource implements MessageSource {
String getMessage(MessageSourceResolvable resolvable, Locale locale) {
// IMPLEMENT ME
}
String getMessage(String code, Object[] args, Locale locale) {
// IMPLEMENT ME
}
String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
// IMPLEMENT ME
}
}
Then simply replace the default implementation of the messageSource bean with your implementation by adding the following to resources.groovy
messageSource(DBMessageSource)
In followup of the answer of #crudolf i implemented the following method to achieve my goal.
class DatabaseMessageSource extends AbstractMessageSource {
// the message bundle resource that holds all of the messages
def messageBundleMessageSource
// the default locale used when there is no correct results found
// if a visitor (x) comes along with an unknown locale in the DB
// then this locale will be used as fallback!
Locale fallbackLocale = new Locale("nl", "NL")
protected MessageFormat resolveCode(String code, Locale locale) {
// first try to find the message in the messagebundles
MessageFormat messageFormat = messageBundleMessageSource.resolveCode(code, locale)
if(!messageFormat) {
// no message found so lets find one in the database
def message = Message.findByCodeAndLocale(code, locale) ?: Message.findByCodeAndLocale(code, fallbackLocale)
if (message) {
// found one create a message format!
messageFormat = new MessageFormat(message.text, message.locale)
} else {
// not found! create a standard message format
messageFormat = new MessageFormat(code, locale)
}
}
return messageFormat
}
}
Take a look at https://github.com/goeh/grails-i18n-db and https://github.com/halfbaked/grails-localizations. Both offer also a gui to manage localizations.

override grails g:link tag

I am trying to override the g:link tag so that I can prefix an extra string. Here is my code:
import org.codehaus.groovy.grails.plugins.web.taglib.*
class ApplicationTagLib {
static namespace = "g"
def link = { attrs, body ->
if("es".equalsIgnoreCase(request.stLocale.language)) {
attrs['controller'] = "es/" + attrs['controller']
}
def applicationTagLib = grailsApplication.mainContext.getBean('org.codehaus.groovy.grails.plugins.web.taglib.ApplicationTagLib')
applicationTagLib.link.call(attrs, body)
}
}
This works fine except for when I add "es/" the resulting path gets translated into es%2F instead of es/ which causes the link to not work.
Is there a way to prevent this from automatically encoding the new slash or a better way to prefix this string to the controller path?
You should be aware that in Grails the controller package (thus it's location in the project's structure path) does not correlate with the default URL mapping - the structure is flattened.
The slash you add to the controller name is thus encoded as it would otherwise form a part of the URL (and thus not map to a controller).
Perhaps the logic for handling different locale be better placed in a controller anyway.
You can add this '/es' prefix in all links generated by grails tags by configuring your UrlMappings.groovy. If you're using the default one, generated by grails create-app command, you can add '/es' in your URL's like this:
class UrlMappings {
static mappings = {
"/es/$controller/$action?/$id?" { // <---------- added '/es' prefix
constraints {
// apply constraints here
}
}
"/"(view: "/index")
"500"(view: '/error')
}
}
To learn more about URL Mappings, see the Grails guide.
Regards

Resources