Reputation: 1122
Coming from Struts/XWorks I was able to do something like this
Messages.properties
myMessage.invalid.fieldvalue=Invalid input for $'{'getText("{0}")'}'
email.label=Email Address
Application Code
getText("myMessage.invalid.fieldvalue",new String[] {"email.label"})
Output: Invalid input for Email Address
So basically the parameter I am passing into a message is actually the code for another message and I want to render them both together.
I can't seem to find a way to do this with Grails/Spring messaging. Is this possible and if so how?
EDIT: To more clearly show one of the reason I am asking for this take this example.
Lets say I have 5 Domain classes with the property emailAddress
To validate for NULL I would have to do this
myClass1.emailAddress.nullable=Email Address cannot be NULL
myClass2.emailAddress.nullable=Email Address cannot be NULL
myClass3.emailAddress.nullable=Email Address cannot be NULL
myClass4.emailAddress.nullable=Email Address cannot be NULL
myClass5.emailAddress.nullable=Email Address cannot be NULL
What I want to be able to do is simply the messaging by overriding the default validation message as such
OLD: default.null.message=Property [{0}] of class [{1}] cannot be null
NEW: default.null.message=getMessage({0}) cannot be null
emailAddress=Email Address
So now anytime any class has a property called emailAddress
and it validates as NULL I will get the message Email Address cannot be null
. There is no need to have 5 messages that basically say the same exact thing. If I had another class with the property emailAddress
then its already handled and I dont have to copy and paste a 6th line.
Anytime I have classes with shared property names, all I have to do is add just add a single line for each property that will be applied to all classes
sharedProp1= Shared property 1
sharedProp2= Shared property 2
Upvotes: 4
Views: 346
Reputation: 1122
I was able to get this done by extending the MessageSource
and overriding the resolveArguments
method.
class CustomMessageSource extends ReloadableResourceBundleMessageSource {
@Override
protected Object[] resolveArguments(Object[] args, Locale locale) {
if (args == null) {
return new Object[0];
}
List<Object> resolvedArgs = new ArrayList<Object>(args.length);
for (Object arg : args) {
if (arg instanceof MessageSourceResolvable) {
resolvedArgs.add(getMessage((MessageSourceResolvable) arg, locale));
}
else {
//resolvedArgs.add(arg) **REPLACED THIS LINE
resolvedArgs.add(getMessage(arg, null, arg, locale));
}
}
return resolvedArgs.toArray(new Object[resolvedArgs.size()]);
}
}
I replaced a single line within the loop that evaluates your message arguments. I basically take the argument and see if its a key to another message. If yes, then replace the argument with that message, if no then continue as normal to use the argument
Make sure to map the new messageSource in your resources.groovy
file
beans = {
messageSource(groovyUtils.CustomMessageSource) {
basenames = "messages"
}
}
Upvotes: 2
Reputation: 472
When in a controller, call message
for the param you want to internationalize and store that in a local variable.
Then call message
for the full message and add your local variable, with the internationalized param value, as a param to that message.
def emailLabel = message(code: "email.label")
def fullMessage = message(code: 'myMessage.invalid.fieldvalue', args: [emailLabel])
Your messages.properties would contain something like
myMessage.invalid.fieldvalue=Invalid input for {0}
email.label=Email Address
Upvotes: 2