Replacing MessageFormat by OGNL. Is it a good idea?

Vlad <[email protected]> Wed, 20 Dec 2006 04:02:09 CST
Newsgroups gmane.comp.java.open-symphony.webwork
Message-ID <19067509.1166609015472.JavaMail.os-j2ee@opensymphony01.managed.contegix.com>
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!

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

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]