Goals
- Uniformity: The i18n storage and editing process for GWT and non-GWT (i.e. template-contained) should be the same, or at least seamless to the user.
- Instant Availability: Changed messages should not require a recompilation of the whole project to be displayed, enabling on-line editing of messages (possibly even in the place they're displayed at).
- Minimal Code Load: When dealing with GWT, we don't know at run-time which messages will be displayed, requiring either all messages to be preloaded in the browser (expensive) or compile-time analysis of the code for used messages. Since we want to reduce the code load in the browser, the latter is preferable, but it poses problems of its own.
- Message Comments: When editing messages, comments can often be very helpful. Accordingly, each message should have an associated comment field.
Technical Issues
GWT provides two i18n solutions, a static solution with which messages are wired into the code at compile-time and a dynamic solution which reads message strings from an external source on the host page. While the latter allows for more flexibility, like changing message strings on the fly, only the former enables message selection based on code analysis, reducing the amount of unnecessarily loaded content. Assuming that some applications built on Continuity contain large amounts of text, and that applications use more than one module (and the module's messages are not all the same), pushing all messages to the client with every module seems very impractical.
Spring, and therefore also the Velocity templates employed in Continuity, reads messages from properties files using a cache and in general is flexible enough for most of the above goals. However, while Spring has no issue with comments in properties files, they cannot be accessed natively, nor are they preserved in write operations to the files.
Solutions
These solutions aim at the problems with getting messages in GWT to the client in a small load, with a fast user interface and in a dynamic fashion. The classification of the solutions (simple, medium, hard) refers to the amount of work required to implement them.
Simple Solution: Throw dynamic change overboard
An easy way to fix the incompatibilities of the goals is to get rid of the requirement for dynamic changes. If all changes to messages are done in the original underlying properties files, both the comments are preserved in Spring and static string binding can be used by GWT. This solution still requires the application to be recompiled after a change has been made, but changes can be compiled in a batch. A downside of the compilation requirement is the necessity to keep all the client side source code at hand - it would be much easier to just push changes down to the client without recompilation. This solution has the advantage that it is very simple to implement, but it requires the editing of messages in properties files, which can be an issue when done by users.
Simple Solution: Provide all messages
Although nothing I'd advocate, another simple solution is to just use dynamic message resolving in GWT. This can have two flavours. Since we have the control over the message source in the client, the source can either be a list of all messages in the program (fast user interface, big initial load) or a dynamic message request to the server (sluggish user interface, no initial load). Both solutions have disadvantages that are to big to be practical. A compromise could be that the developer specifies which messages are used in a module and those are pre-fetched. This becomes impractical with large modules though. The advantage of this approach is the full support for dynamic messages, but the disadvantages speak against it.
Medium Solution: Some dynamic change
This is an extension of the first solution introduced above, which used only back-end message editing, to enable some dynamic change of messages. The goal is to provide an editor in the front end, which writes to properties files on the server. These files are then again used to compile the front end once editing is finished. This results in some problems however: if both messages from GWT and the templates are changed (or if one message is employed in both areas), its change will appear right away in the templates, but only after explicit manual recompile in the GWT part of the application. This can be fixed by only resetting the cache manually. Another downside that's not as easy to fix is the requirement for recompilation, which has the same issues as described in the original solution without dynamic change. In difference to the original solution, this method also doesn't preserve or provide any comments (as every solution that writes/reads properties files through Spring).
Hard Solution: Adapting GWT Compiler
As mentioned in the second simple solution, having all messages available dynamically would be very useful. The problem is, however, that finding a list of all required messages for a module can only be done through code analysis (or through human labour in the code, which is not advisable), and this is complicated to implement. An ideal solution would marry both methods offered by GWT: In this case, the GWT code would include message function calls as used by the static method in GWT, but instead of replacing these method calls with literals, they are changed into calls to a cache. In addition, a list of the required messages is provided to the cache, which can then pre-fetch all those messages. Once a message is changed dynamically, the change is simply written through the cache, thus fulfilling both the requirement for dynamic message editing and keeping the code load to a minimum. This solution also has the advantage of keeping the message content separate from the client code, rendering recompilations in production obsolete.
Comment Solution:
Whenever we are talking about dynamic editing of properties files, the problem remains that writing and reading comments in properties files is not supported by the Spring mechanisms. One solution is to write a new properties accessor which gives access to comments in properties files. However, it is also possible to save messages and their comments in an entirely different format, e.g. in a database, and then compile them into the necessary properties files when they've been changed. This would probably be appropriate when using one of the methods above requiring recompilation of client code.
Conclusion
All in all it seems to me that for the beginning the first solution is best, being simple and fast to implement. It can later be extended by the adaption of the GWT compiler, allowing for dynamic change while preserving the reduced code load.
No comments:
Post a Comment