I recently read this article on ClientBundle and under the Levers and knobs section, see these two entries:
ClientBundle.enableInlining is a deferred-binding property that can be used to disable the use of data: URLs in browsers that would otherwise support inlining resource data into the compiled JS.
ClientBundle.enableRenaming is a configuration property that will disable the use of strongly-named cache files.
I'm having a tough time visualizing these in action and understanding what they do. Where do you set these properties? Why would you set them (i.e., when would I want to "disable the use of data", or "disable the use of strongly-named cache files")? Can someone provide a real-world use case and perhaps some code snippets for me? Thanks in advance!
Where do you set these properties?
Deferred-binding properties are set in your gwt.xml with <set-property>.
See https://developers.google.com/web-toolkit/doc/latest/DevGuideCodingBasicsDeferred
Why would you set them (i.e., when would I want to "disable the use of data", or "disable the use of strongly-named cache files")?
For debugging, or if the performance boost they're supposed to bring to your app actually does more harm than good (enableInlining'), or if you need/want to share the resources with other scripts/apps (enableRenaming`).
Can someone provide a real-world use case and perhaps some code snippets for me?
You'll know it when you need them. Until then, ignore them.
In case this is still useful, I have a real-world example of needing to disable inlineing.
But first, just to clarify the code needed its simply;
<set-property name="ClientBundle.enableInlining" value="false" />
In your XML to disable the use of DataURLs and use image strips instead
I had to do this in my code, because my project requires animated images. Even a basic sprite with just a few frames has very bad performance when using DataURLs. The browsers just struggle to update and display the images at anywhere near a reasonable framerate.
By comparison, the use of image strips, vastly speeds up performance. The browser merely has to change the cropping.
In fact, given the lack-luster browser support for animated PNG's, if you need animated images, this is probably the current best way to do it.
Related
We have a rather large application, with a great deal of dynamic content. Is there anyway to force struts to use a database for the i18n lookups, instead of properties files?
I'd be open for other ways to solve this as well, if anyone has ever done i18n with dynamic content.
I don't know of an easy plug-and-play solution for this, so you will probably have to implement it yourself -- plan on spending quite a bit of time just coming to grips with how the localization features of struts 2 (and XWork) are implemented. The key will probably be to provide your own implementation of com.opensymphony.xwork2.TextProvider (and tell struts to use it by providing a <bean> tag in struts.xml). I can think of at least two ways of fitting this into the overall architecture:
Have your TextProvider implementation access the database directly. In the spirit of YAGNI, this is probably the best way to start (you can always refactor later, if necessary).
Alternatively, you could place the database code into an implementation of Java's ResourceBundle interface, which is what XWork uses internally. To me this sounds like an even more design-heavy approach, but on the plus side there are some articles around describing how to do this.
No, there is no built-in way to have Struts2 load localized content from a database. You would need to write that yourself.
What are your requirements? Do you need for users to be able to dynamically change field prompts, error messages, etc.?
You may be able to do something like that by building a custom interceptor. You could have the interceptor read all the key value pairs from your database and inject them into the value stack. The only thing I am not sure about, not really having messed with i18n with struts before, is if the i18n stuff pulls that information from the value stack. If not, I am not sure if maybe you could do something else in the interceptor to load up the information.
Building a custom interceptor is not too terribly complicated. There are plenty of tutorial sites out there, including (brace for self promotion here) my blog: http://ddubbya.blogspot.com/2011/01/creating-custom-struts2-interceptors.html.
Use properties files just for static content, like labels, messages etc.
For dynamic content start with a database table that includes a language-code-id for every language you want to use. All the dynamic content entries that are already translated go with their respective language-code-id added to their primary key. If a translation is missing, you can program your application to fall back to your default language in order to make things easier until the right translation is present.
Let your users provide their contributions in the language they like and store it with the appropriate language-id. Someone should provide the translation to the other languages in order to make the contribution complete.
...
PRIMARY KEY (`subject_id`,`language_id`),
...
As far as I can tell, there are two ways to set the IDs for web elements from within GWT. I need to perform Selenium automated testing, and would appreciate insight into the relative advantages of each technique.
Option 1: the generally accepted method
uiObject.ensureDebugId("idForMyElement");
This solution is well documented, and officially supported by google. However it comes with some disadvantages:
My team will have to add lines to every package's gwt.xml file like so:
<inherits name='com.google.gwt.user.Debug' />
Furthermore, the Debug class prepends "gwt-debug" to IDs by default. I realize I can change this behavior, but I don't like adding complexity where I can help it.
Option 2: use a generic setAttribute call
uiObject.getElement().setAttribute("id", "idForMyElement);
This seems cleaner to me- are there any downsides I might be overlooking?
Relevant resources:
How can I set id for GWT widgets in UiBinder?
https://code.google.com/p/google-web-toolkit/issues/detail?id=4176
The first option is better because you can compile out debug ids from your production code, making it smaller.
With the second option ids will be there even when you don't need them anymore.
I want to create a web site which can be viewed with two languages, one LTR and one RTL. This means that all content should be shown in either of the two languages.
My framework is Spring, and I'm using Tiles2, but I think this question is not framework specific.
The obvious solution to supporting two languages is having everything doubled (all JSP's, fragments, etc.), and you get the part of the tree which fits the language you chose. But this causes problems when changing the web site (you might forget to update the other JSP's), and is not scalable (try doing this for 5 or 10 languages).
I know I can use properties files to host strings for the different languages, but then my web site would be a huge collection of spring:message tags and will be a lot harder to maintain (what happens if I have a paragraph of 100 lines, does this all go into a single properties line?)
Is there any kind of framework, plugin, other, which solves this problem? Has anyone come across a clever solution to this problem?
I've never realized a complete project, just some tests. I think this problem is not so big as it seems if you follow some simple rules. Here is what I would try to do:
Specify direction with <body dir='ltr/rtl'>. This is preferred versus CSS direction attribute.
Avoid different left/right margins or paddings in all CSS. If you must break this rule, probably you'll need to use two different files (ltr.css and rtl.css) containing all these different elements.
Sometimes you'll need to move some elements from left to right or vice versa. For example, in LTR you want a menu on the left, but in RTL you want it on the right. You can achieve this using CSS, but this sometimes is complicated if you are not an expert and you must test it in all browsers. Another option is to use some IF depending on the case. This last option will fit very well if you use a grid based CSS library, like Bootstrap.
Choose carefully which CSS and JS libraries you'll use. Obviously, pick the ones which offer RTL/LTR support.
Don't worry too much about the images. If you must change one image depending on the language is probably because it has some text in it. So, you must use different images anyway. This is a problem related to i18n, not a text direction issue.
Don't let your customer to be too much fussy about it. I think that with these rules (and maybe some more) you can get a good result. But if your customer starts complaining about one pixel here and another one there, you'll need to complicate all this and probably is not necessary.
About your language properties file. Yes, use them. Always. This is a good practice even when you are only using one language: HTML structure is separated from content, is very easy to correct or translate, some words or sentences are in only one file...
Usually, web frameworks are used to build web applications rather than web sites, and there are quite few long static paragraphs. Most of the content is dynamic and comes from a database. But yes, the usual way of doing is to externalize everything to resource bundles, usually in the form of properties files.
Putting a long paragraph in a properties file doesn't cause much problem, because you can break long paragraphs into multiple lines by ending each line by a backslash:
home.welcomeParagraph=This is a long \
paragraph splitted into several lines \
thanks to backslashes.
RTL and LTR is one of the upper and more difficult i18n problems.
Basically its a Problem of the view-scope of the MVC-Model. This may also includes pictures and emotional differences like the color of the skin of people. In this case you better abadon to the solution HTML+CSS gives you.
In example:
<style type="text/css">
*:lang(ar) { direction:rtl }
*:lang(de) { direction:ltr }
</style>
The best practice is to ask members of the audience-group about what effect the webpages have to them.
I agree to most of solutions provided here. Your problem is more design (architecturally) oriented rather than technical. You need to choose path whether you need to keep this logic of internationalization on server (java) side or in static files.
In case you want to go for java side (preferable solution), you need to keep two properties file and use jstl tags. This minimizes your work in case you want to add another language in future. This is maintainable solution. I have seen applications supporting more than 15 languages and time zones. In fact release process gets pretty easy.
In case you want to go for keeping multiple css and other static files, you will soon find things running out of your hands pretty soon. I dont think this is a maintainable solution.
Said all this, I will leave this choice to the architect of application. He will be able to judge which way to go based upon the nature of application and constraints given to him.
You don't want to use everywhere. That's a pity because it is just the way you should do it. It is a bad practice to keep hard-coded texts in a jsp if you need internationalization.
Furthermore, Most of the modern IDE allows you to go to the variable declaration by doing ctrl+left click (or hovering the key) so that having a lot of variables in your code should not be a problem for maintenance.
First, you must distinguish, for each text element, whether it is a user interface element (e.g. button label) or redactionnal content.
user interface element labels will be stored in properties file that will have to be translated for each supported language (and provide a default value as a fall back)
redactionnal content will be stored in a content management system that you will organize in order to find easily a localized version of your content
I have a web-app in Java, Spring, Struts 2 and Hibernate, that servers multiple clients. Each client with multiple users. To create a personal feel for each client, i would like to customize the header for each client.
I'm using sitemesh as decorator, and am looking for tips or examples or someone who can point me in the right direction as to how to acomplish this in the best practice.
What would you think? Should i just code it direct in the header.jsp? Extracting the info about the logged in user and from that create a custom header by code? Or is there a more clever solution out there?
Thanks!
Update:
To further clearify what i want:
Different properties-files for each client is not an option. We are looking at potentionally hundreds of clients. It needs to be database-driven. But thats the easy part. There is no problem storing the information in db and extracting it when needed.
What im trying to figure out is if there is some sort of standard way of doing this. Some sort of filter or Action that is run before the sitemesh decorator that will provide the decorator with the correct info?
Struts2 provides application scope, for variables which are global to the application.
Load all the customer specific strings into #application scope (I would use spring to do this when the application starts up). From there referencing the strings would be pretty obvious: #application.greeting I don't like the idea of using an interceptor because there is nothing to intercept. I would say for what you are doing application scope is the perfect place. If it is a single client system I can see no reason why anything would be stored in application scope.
Aside: Tiles uses a different template paradigm than site mesh, and they have slightly different purposes. As such the two can be complimentary. Tiles relying on XML definitions can have it's definitions stored in a DB and is definitely less computationally intensive, however where there is interplay between different UI components... or disparate elements appearing on the page you need to use sitemesh. So for basic template needs tiles does everything and is quite easy to understand but say you wanted to make add a certain widget in the middle of the page which relies on JS which needs to be added to the header it would be tricky to do this in Tiles (although the obvious solution is to just roll the JS functionality into one JS file for all possible uses in a particular part of the site).
Asside 2: By using a view technology such as velocity or freemarker in conjunction with tiles it is conceivable to move the entire view layer into a database. I just thought I would mention that as for some maintenance issues that could be extremely beneficial.
Sitemesh makes it's decisions about what decoration to use based upon the requested URL string, so unless you have a reference to the client in every url - either as part of the main url string or as a known parameter, then Sitemesh out of the box is not going to help.
This leaves a few possibilities to achieve what you want;
1) Write a filter that runs before Sitemesh that adds, for example, "&clientId="xx" to every incoming request.
2) Dive into the source code for Sitemesh & look for where Sitemesh finally makes it's decision about which decorators to use and override it. I've never tried this so I don't know how practical this might be.
3) Make the style sheet definition in your jsp pages an OGNL expression and provide that information in a base action class that all your actions extend. In this way you end up with (potentially) a different CSS file for each client and you provide your customisation via CSS.
Hope that this helps.
We have a rather large application, with a great deal of dynamic content. Is there anyway to force struts to use a database for the i18n lookups, instead of properties files?
I'd be open for other ways to solve this as well, if anyone has ever done i18n with dynamic content.
I don't know of an easy plug-and-play solution for this, so you will probably have to implement it yourself -- plan on spending quite a bit of time just coming to grips with how the localization features of struts 2 (and XWork) are implemented. The key will probably be to provide your own implementation of com.opensymphony.xwork2.TextProvider (and tell struts to use it by providing a <bean> tag in struts.xml). I can think of at least two ways of fitting this into the overall architecture:
Have your TextProvider implementation access the database directly. In the spirit of YAGNI, this is probably the best way to start (you can always refactor later, if necessary).
Alternatively, you could place the database code into an implementation of Java's ResourceBundle interface, which is what XWork uses internally. To me this sounds like an even more design-heavy approach, but on the plus side there are some articles around describing how to do this.
No, there is no built-in way to have Struts2 load localized content from a database. You would need to write that yourself.
What are your requirements? Do you need for users to be able to dynamically change field prompts, error messages, etc.?
You may be able to do something like that by building a custom interceptor. You could have the interceptor read all the key value pairs from your database and inject them into the value stack. The only thing I am not sure about, not really having messed with i18n with struts before, is if the i18n stuff pulls that information from the value stack. If not, I am not sure if maybe you could do something else in the interceptor to load up the information.
Building a custom interceptor is not too terribly complicated. There are plenty of tutorial sites out there, including (brace for self promotion here) my blog: http://ddubbya.blogspot.com/2011/01/creating-custom-struts2-interceptors.html.
Use properties files just for static content, like labels, messages etc.
For dynamic content start with a database table that includes a language-code-id for every language you want to use. All the dynamic content entries that are already translated go with their respective language-code-id added to their primary key. If a translation is missing, you can program your application to fall back to your default language in order to make things easier until the right translation is present.
Let your users provide their contributions in the language they like and store it with the appropriate language-id. Someone should provide the translation to the other languages in order to make the contribution complete.
...
PRIMARY KEY (`subject_id`,`language_id`),
...