anonymous wrote : The least intrusive change would be to update the Logger 
factory to use the message as a key with the resource bundles located in the 
classpath say under conf/logging-i18n

I was thinking we pass in an I18N class as the first arg. to log() and the 
Logger would handle it normally (that is, just call toString() on it like it 
would do for any Object it gets passed).  The I18N would then, in its 
toString() lookup the message in the bundle.  This would allow the resource 
bundle lookup to only occur when it needs to (that is, if the message actually 
needs to get logged, not if the log level isn't enabled, for example).  I18N 
would provide a varargs type of functionality (to support < JDK 1.5, we'd have 
to have just a series of constructors) to allow for placeholder replacement 
values.  This is how we can support dynamic messages with runtime info.

The question is, how do you tell the I18N object what resource bundle to look 
in?  We could add a factory method to Logger to create an I18N object that has 
the same category as the Logger and we use that as the name (or part of the 
name) of the resource bundle:

private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);
  | ...
  | LOG.debug(LOG.createI18N("file.not.found", myFile));

Or we provide a public method I18N.setBundleName() that the Logger would have 
to call, but that would break the abstraction in which the Logger doesn't know 
its a special I18N object - it would be ideal for it to just call toString() 
and have it magically work without the Logger doing anything special (like "if 
(msg instanceof I18N) msg.setBundleName(...)).

I've also seen I18N logging work where each class with I18N messages would 
create a sister object to the public static final Logger and provides I18N 
factory building:

private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);
  | private static final I18N MSG = LOG.getI18NFactory();
  | ...
  | LOG.debug(I18N.msg("file.not.found", myfile));
  | 

Using the message key string passed to log() as the resource bundle key would 
be a way to capture the messages that don't have dynamic info - but that would 
mean

A) the resource bundle lookup would be performed on every log, even if the 
message isn't in a resource bundle yet - not sure how that exception condition 
would affect logging performance

B) the resource bundle key would be really long in some cases (not sure if this 
is a problem, unless there turns out to be invalid .properties file characters 
in there like '=')

C) depending on the ratio of static messages to messages with dynamic content, 
it may not prove to be valuable enough to offset the performance hit

anonymous wrote : It should emit a default resource bundle for the messages 
that don't have a matching key to dynamically build the keys which can be 
localized. This will allow one to gradually localize output as needed.

That's a good idea - we could spit out classname, line number type info with it 
- then you just perform a logging run to capture messages.  Obviously, as you 
said, this would be a gradual process and wouldn't help with the dynamic log 
messages in which an I18N encapsulation object would have to be used.

Then the question comes up with, how do you encapsulate the key string as a 
constant (to avoid typos in logging like "file.not.fond") and how do you 
auto-create the resource bundles to free the developer from having to do it?  
We can introduce an XDoclet tag that would define the english version of the 
message and the message key:

/**
  |  * This class does something.  Blah. Blah.
  |  * @author Joe Bling
  |  *
  |  * @msg FILE_NOT_FOUND File named {0} was not found
  |  */

We just run this through a special xdoclet ant task to extract all the message 
keys, and create an interface that contains the message key (constant name and 
message key are the same name).  Then it would create a resource bundle file 
with the english version of the message.  We then hand off the resource bundles 
to translators to translate to different languages.  This XDoclet approach 
gives the added benefit of allowing the developer to see the actual error 
message at the top of the .java file in the @msg tag. (conceivably, we could 
allow @msg anywhere - in methods for example - to allow for more localized 
definitions of @msg's.  That is define @msg on the method in which it is used).

An example interface would be:


  | package where.my.class.is;
  | 
  | public interface I18NMessages
  | {
  |    /** File named {0} was not found */
  |    String FILE_NOT_FOUND = "FILE_NOT_FOUND";
  | }
  | 

Note that generating code like this with the javadoc command containing the 
actual message has an added benefit - tools like Eclipse that provide hover 
help will show you the actual message when you hover over the constant (nice 
for developers to make sure they know what placeholders are in the message 
right there while writing the log call).

The resource bundle:

FILE_NOT_FOUND=File named {0} was not found

View the original post : 
http://www.jboss.org/index.html?module=bb&op=viewtopic&p=3860580#3860580

Reply to the post : 
http://www.jboss.org/index.html?module=bb&op=posting&mode=reply&p=3860580


-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
_______________________________________________
JBoss-Development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to