Reputation: 1773
I've already found a way to get message from i18n message properties (outside the controller)
def messageSource = Holders.grailsApplication.mainContext.getBean 'messageSource'
....
errorMessages << [field: "transactionDate", message: messageSource.getMessage("transactionDate.require.message", null ,null)]
But then while reviewing my colleauges work, I found out that they use a different way..
def g = new ApplicationTagLib()
errorMessages.add([field: "exchangeRate", message: g.message(code: "exchangeRate.max.message")])
Obviously, this a simpler version but I want to know which way is preferred (best practice) and what is the difference of the one to the other.
Upvotes: 3
Views: 2768
Reputation: 7505
Just as an addition to above answers, there could be following places where you need to implement internationalisation or fetch the message from message bundles.
Below are the elaborate usage scenarios:
Views:- we have taglib available with message tag. Use this on views.
controllers :- message method is by default available here and locale conversion is automatically handled. See this.
service: we may call taglibs inside services as below:
def myCustomTaglib = grailsApplication.mainContext.getBean('com.custom.MyCustomTagLib');
Or inject messageSource bean as
def messageSource
Filters / utility / Special files:- For these you may create something like below and then use it throughout.
String i18nMessage(def input,String defaultMessage) {
String[] languageCode = RequestContextHolder.currentRequestAttributes().request.getHeader("Accept- Language").split("-")
Locale locale = languageCode.length == 2 ? new Locale(languageCode[0], languageCode[1]) : new Locale(languageCode[0])
String message = defaultMessage
try {
message = messageSource.getMessage(input.code,input?.args?.toArray(),locale)
}catch (NoSuchMessageException nsme ){
log.info("No such error message--> ${nsme.getMessage()}")
}
return message
}
Also, if you get exception below:
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
Then, you might need to add request listener to your web.xml
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>
Note: web.xml is not available by default, you need to generate it from template.
These are the most common places you might need message bundle conversions. Solution at point 4 would work in almost all cases. If you notice locale has been handled here manually which we could pass after fetching from requestHeader or request params optionally.
Hope it helps.
Upvotes: 1
Reputation: 2188
Inside a Controller message
and g.message
are directly available from ValidationTagLib
. Your colleague is assigning an object of ApplicationTagLib
to variable g
. I suspect ApplicationTagLib
is a custom class and not provided by grails api, atleast not in 2.3.x.
If you need i18 messages anywhere except controllers in your application, then you would have to get messageSource
bean first or you can create a new instance of ValidationTagLib
and then call message()
on that instance.
Upvotes: 1