views:

231

answers:

4

In GWT one typically loads i18n strings using a interface like this:

public interface StatusMessage extends Messages {
   String error(String username);
   :
}

which then loads the actual strings from a StatusMessage.property file:

error=User: {0} does not have access to resource

This is a great solution, however my client is unbendable in his demand for putting the i18n strings in a database so they can be changed at runtime (though its not a requirement that they be changed realtime).

One solution is to create a async service which takes a message ID and user locale and returns a string. I have implemented this and find it terribly ugly (it introduces a huge amount of extra communication with the server, plus it makes property placeholder replacement rather complicated).

So my question is this, can I in some nice way implement a custom message provider that loads the messages from the backend in one big swoop (for the current user session). If it can also hook into the default GWT message mechanism, then I would be completely happy (i.e. so I can create a interface like above and keep using the the nice {0}, {1}... property replacement format).

Other suggestions for clean database driven messages in GWT are also welcome.

+1  A: 

Let's say your application has 500 messages per locale at an average of 60 chars per message. I wouldn't think twice about loading all of these when the user logs in or selects his language: it's <50k of data and should not be an issue if you can assume broadband connectivity being available...your "one swoop" suggestion. I already do that in one GWT application, although it's not messages, but properties that are read from the database.

Tomislav Nakic-Alfirevic
Broadband connectivity is not a problem and the DB is fast. Do you just load all the messages into a singleton right after onModuleLoad ? (when locale is available). I have thousands of messages, so some form of aggregation would be needed to keep the message classes from exploding in size (fx. a class with messages specific for each view)
Lars Tackmann
Well, the event is different in my case (user login triggers property loading in my case). However, given that you have quite a large number of messages to retrieve, doing the retrieval for individual views might make sense, as you said. When the user accesses a view, you lazy-load the messages in a static list or map an not have to reload it on each page access for a certain user. If your views extend a common parent class (as is the case in the app I'm working on), you can probably get away with adding a class in between and contain all the logic and data structures there.
Tomislav Nakic-Alfirevic
+2  A: 

GWT's in-built Dictionary class is the best way to move forward. Here's the official documentation on how to use it.

sri
+1 This is a pretty good idea. The idea is that you would print out a JSON map like `var dict = {'key':'value'}` into the host page's HTML, then in your GWT code, call `Dictionary dict = Dictionary.getDictionary("dict");` to get the map-like object in your GWT code.
Jason Hall
The way the application I'm currently working on is set up, this would be similar in behaviour to the "one swoop" approach Lars mentioned as there is one host page so all of the messages (thousands, in Lars' case) would be stored and retrieved together within a single file.
Tomislav Nakic-Alfirevic
+1  A: 

i think you might find this article useful: http://googlewebtoolkit.blogspot.com/2010/02/putting-test-data-in-its-place.html?utm_source=feedburner&amp;utm_medium=feed&amp;utm_campaign=Feed:+blogspot/NWLT+(Google+Web+Toolkit+Blog)&amp;utm_content=Google+Reader

What you could do is set up a TextResource and then, you could just change the text at runtime. I haven't tried this but I am very confident that this would work.

markovuksanovic
This is not a bad idea, I will try implementing a resource that loads the messages in JSON format from the server via a REST api.
Lars Tackmann
A: 

Hi Lars

Did you solve this? I'm facing the exact same scenario. I want my serviceImpl to return a value that I can build my Dictionary object from, but I dont know how to construct the javascript array correctly from the values I have. I currently have HashMap in the server part.

Andreas Blomqvist