ResourceBundle and Class.getResource(...) are missing from the JRE
emulation library,
which would be needed to implement i18n the usual way.
Are you planning something in this direction?
I'd like to avoid downloading resources for all supported languages to
the client.
Instead, only resources for the chosen language (or language as
indicated by the browser) should be used.
Any ideas?
Thanks,
Jochen
Listening...
Matt
Cheers,
Ludo
Here's a high-level view of how you can do it. Sorry for the lack of
specifics, but we will eventually have a sample demonstrating this
technique.
What you do is define an abstract class called something like
"Messages", with a bunch of abstract methods returning String, one
method per message you need. Then you define a bunch of concrete
implementations of the class, like "MessagesEN" which actually return
the text you need for that language in a concrete implementation.
Finally, you use deferred binding to return the correct concrete
subclass for the particular language you need. This involves using
GWT.create() at the point where you instantiate the Messages class, and
also setting up a bunch of "replace-with/when-type-assignable" rules in
your module to tell the compiler how to pick the right class.
Unfortunately, this process isn't well documented yet, so you'll have
to just look at what we're doing in UserAgent.gwt.xml and DOM.gwt.xml
and follow it. Except you'll need to get the browser's preferred
language instead of its User Agent.
This should be a lot easier when we have a good sample. We're also
looking at ways to do all this automatically from properties files.
Scott Blum
GWT Engineer
Using classes instead of resource files is certainly an elegant
solution, however, it is a little impractical to convert our 2657
properties-Files into classes.
Also, maintaining those classes is not really feasible. Once a
localized string is added or changed, this string is sent to a number
of translators who really don't know (or care) how to handle Java
classes. (We maintain our application for 6 languages)
What I want to say: We would strongly prefer to keep the localized
strings/icons within the standard properties files and find a way to
transmit them (or some intermediate form) to the client on demand.
java.util.ResourceBundle and its subclasses implement a quite generic
concept that suits desktop applications fairly well. One possible
solution could be to have an additional subclass for ResourceBundle
that deals with "remote" property bundles and include this into GWT.
Could this be a possible solution?
I'm all for referencing to i18n resource using methods or fields, but
we need a clever way to fill them using resource bundles.
Cheers,
Jochen
Currently GWT has no good solution for i18n.
We have a sample in the works that will demonstrate how to use a
Generator to automatically create the appropriate subclasses out of
java properties files. I think this will probably be a very good
solution for strings in most cases, because the compiler will inline
all the call sites and end up putting the right string literals
directly into your app. I don't have an ETA for when the sample will
be ready but supporting i18n is definitely a priority. For things
like icons, I would suggest loading them off the server.
Scott
I'd like to see how you can inline a dynamically referenced resource.
>> For things like icons, I would suggest loading them off the
>> server.
For things like localized string resources, /I/ would suggest the same
thing. Why not "generate" JS files that contain the localized strings.
Then the GWT can download the locale specific JS file for the bundle
name requested at runtime. The file will be cached by the browser, so
performance isn't an issue. Add a GWT class to wrap this into an API
that /mimics/ java.util.PropertyResourceBundle and you've not only
solved the problem, but have done so in a way that Java developers are
already comfortable with and understand.
...Impatiently waiting to be blown away by the much-anticipated i18n
sample app...
-Matt
Imho, resource bundles really aren't that great. For instance, this
line is from a Chinese locale bundle:
NumberValidator.range=${input} \u5FC5\u987B\u4ECB\u4E8E ${minimum}
\u548C ${maximum} \u4E4B\u95F4\uFF01
Isn't that great for maintenance?
Properties got much better now that they can load XML with the
declared encoding (typically UTF-8). But unfortunately, from what I
understood from it, this isn't integrated with the ResourceBundles.
So GWT might consider building something from scratch that just works
and lets it's non-ASCII users write their messages direcly in unicode.
Just my 2c
Eelco
Matt wrote:
>> I think this will probably be a very good solution for strings
>> in most cases, because the compiler will inline all the call
>> sites and end up putting the right string literals directly
>> into your app
>
> I'd like to see how you can inline a dynamically referenced resource.
To be more clear, we can't inline a dynamically referenced resource. I
was speaking of using Generators to create a concrete subclass of a
Messages-style interface class via deferred binding. The concrete type
ends up being known at compile time, so calls can be inlined. This is
the same way it works with DOMImpl subclasses, for example.
> For things like localized string resources, /I/ would suggest the same
> thing. Why not "generate" JS files that contain the localized strings.
> Then the GWT can download the locale specific JS file for the bundle
> name requested at runtime. The file will be cached by the browser, so
> performance isn't an issue. Add a GWT class to wrap this into an API
> that /mimics/ java.util.PropertyResourceBundle and you've not only
> solved the problem, but have done so in a way that Java developers are
> already comfortable with and understand.
This is another option we've talked about, pulling across a JSON
notation object that is either an array or map into the target language
strings.
> ...Impatiently waiting to be blown away by the much-anticipated i18n
> sample app...
No ETA on this.. there are a lot of ways to solve the problem and we
want to be sure we're happy with the one we stick with.
Scott
Yes, good question.
Thanks for description of currenct i18n solution.
Generator will made it much more useful.
I have one question: Who I can swith preffered browser's language via
application, whicha are based on GWT (don't use settings of browser)?
Best,
Serge
Scott Blum писал(а):
There are probably a couple of ways of doing it, but one way that
springs to mind is having your application take a query string, ala
"?lang=foo" at the end of the URL if that's appropriate for what you're
doing. You should be able to access the query param in your property
provider logic. I'd look at UserAgent.gwt.xml for an example of how
the property provider stuff works.
Scott
You can in principle do a lot of i18n stuff right now, but it requires
a lot of low-level knowledge which isn't very easy and isn't
well-documented. We're looking at how to make localization powerful
and flexible but still easy to use.
*And* we're working on updating the active issues list more often so
that you'll know that we're working on stuff like i18n :-)
In the meanwhile, know that we are reading this forum constantly. So
please keep posting your suggestions.
-- Bruce
GWT Tech Lead
Is "100% agreement" enough to /actually/ get it listed as an issue? I
don't see the GWT being used an any large enterprise applications
without a solid i18n solution.
Now that I mention it, it probably won't be used by any large
enterprise anyway, because it makes too much sense and doesn't cost
anything. <sigh>
GWT is looking good - keep up the good work!
-M
(unappreciated enterprise software consultant)
Geoff
I'd also love i18n very much
In the meantime - thanks for the greatest tool !
John
To solve the I18N issue, we decided to load from the server all the
strings a module would require as the module loads. For our app, we
are using the standard ResourceBundle setup on the server side, and as
a module loads, it requests a set of strings it's going to need. These
strings are stored away in a construct we call the GWTResourceBundle.
The GWTResourceBundle is a singleton with a private hashMap of strings
loaded by the module. It has a getString(String) method to lookup
strings by the key.
For the service side, we have a simple I18nService that can load a set
of strings from our server side resource bundle. Originally, we were
passing the entire list of keys required by the module to the service
in order to load all the required messages. However, since we're using
XLiff, we were able to extract the strings by "group" (take a look at
XLiff if that doesn't make any sense:
http://www.oasis-open.org/committees/xliff/). This allowed us to send
a single group name (or, I think we opened it up to be able to send a
list of group names) to the service, which loaded and returned all the
strings in the group(s) as a map.
The only tricky part to the GWTResourceBundle and I18nService is that
the module's loading process needs to block while the GWTResourceBundle
is retrieving the messages because the module needs to wait to show
widgets until the messages needed by those widgets are fully loaded
from the service. In order to do this, we encapsulate the module's
normal onLoad process into a GWT Command object and pass this into the
GWTResourceBundle. This Command's execute method is kicked off in the
onSuccess of the I18nService's callback.
Additionally, we're adding in an extremely simple version of the
MessageFormat class that will allow us to pass replacement arguments to
the GWTResourceBundle.getString(String) method.