atom feed4 messages in net.java.dev.webwork.usersReplacing MessageFormat by OGNL. Is i...
FromSent OnAttachments
VladDec 20, 2006 2:01 am 
Philip LuppensDec 20, 2006 2:10 am 
VladDec 20, 2006 3:40 am 
VladDec 21, 2006 6:12 am 
Subject:Replacing MessageFormat by OGNL. Is it a good idea?
From:Vlad (webw@opensymphony.com)
Date:Dec 20, 2006 2:01:46 am
List:net.java.dev.webwork.users

Hi,

I am developing a web site on WebWork. The site will be running in several
countries, so it must be localized.

WebWork allows localizing a lot (if not everything), but I have noticed that now
I am mixing texts containing placeholders in OGNL format and in Java
MessageFormat.

For example the following message is for validator: OGNL: errors.user.age.invalid = Your age must be within ${minAge} and ${maxAge}
years. And this message is for <ww:text> tag: MessageFormat: auth.login.message = You are logged in as {0}.

I think that it will be difficult for translators to care about two possible
formats, as well as it will make translation tool logic more complicated. My
thought is to avoid using MessageFormat class / style completely. For the places
where OgnlValueStack is not available, I would create a helper class with a
method like: [code] public static String translateOgnl(String message, Map<Object, Object> args) { OgnlValueStack stack = new OgnlValueStack(); stack.push(args); return TextParseUtil.translateVariables(message, stack); } [/code]

In my opinion messages with OGNL placeholders are more "translator-friendly"
than MessafeFormat style: OGNL: "Hello ${name}! It's your day. Bye..." MessageFormat: "Hello {0}! It''s your day. Bye..." as place holders have meaningful names and single quote has no special meaning
outside of OGNL expression.

I had concerns about performance, but after I have written the following test
class it appeares the both approaches perform equally: [code] public class TestOgnlValueStack {

public static String translateOgnl(String message, Map<Object, Object> args) { OgnlValueStack stack = new OgnlValueStack(); stack.push(args); return TextParseUtil.translateVariables(message, stack); }

public static String translateMessageFormat(String message, Object[] args) { return MessageFormat.format(message, args); }

public static void main(String[] args) {

// preload classes and print translated messages String ognlMessage = "Hello ${name}! It's your day. Your value is ${value}.
Bye..."; Map<Object, Object> map = new HashMap<Object, Object>(2); map.put("name", "Vlad"); map.put("value", Integer.MAX_VALUE); System.out.println("ognl result: " + translateOgnl(ognlMessage, map));

String mfMessage = "Hello {0}! It''s your day. Your value is {1}. Bye..."; Object[] array = new Object[] {"Vlad", Integer.MAX_VALUE}; System.out.println("MessageFormat result: " +
translateMessageFormat(mfMessage, array));

final int iterations = 100000;

long start = System.currentTimeMillis(); for (int i=0; i<iterations; i++) { map = new HashMap<Object, Object>(2); map.put("name", "Vlad"); map.put("value", Integer.MAX_VALUE); translateOgnl(ognlMessage, map); } long duration = System.currentTimeMillis() - start; System.out.println("ognl duration in ms (total): " + duration); System.out.println("ognl duration in ms (for one iteration): " +
(double)duration/iterations);

start = System.currentTimeMillis(); for (int i=0; i<iterations; i++) { array = new Object[] {"Vlad", Integer.MAX_VALUE}; translateMessageFormat(mfMessage, array); } duration = System.currentTimeMillis() - start; System.out.println("MessageFormat duration in ms (total): " + duration); System.out.println("MessageFormat duration in ms (for one iteration): " +
(double)duration/iterations);

}

} [/code]

The class produces the following output: [code] ognl result: Hello Vlad! It's your day. Your value is 2147483647. Bye... MessageFormat result: Hello Vlad! It's your day. Your value is 2.147.483.647.
Bye... ognl duration in ms (total): 2766 ognl duration in ms (for one iteration): 0.02766 MessageFormat duration in ms (total): 2610 MessageFormat duration in ms (for one iteration): 0.0261 [/code]

I will have to write own implementation for TextProvider interface and replace
<ww:text> tag implementation. Unfortunatly TextProvider interface has methods
which, like MessageFormat, allow passing unnamed arguments. Implementation for
those methods will just silently skip arguments like List or String[]. But it is
my application and not a public framework.

The question is it a good idea to replace MessageFormat by OGNL? or am I doing
something wrong? Do I oversee any major efforts that will need to be done in order to implement
the replacement?

Many thanks in advance!

--------------------------------------------------------------------- Posted via Jive Forums http://forums.opensymphony.com/thread.jspa?threadID=54464&messageID=109075#109075