Localization support

A discussion on the slf4j-dev mailing list spawned an open-source project called CAL10N or Compiler Assisted Localization. As its name indicates, CAL10N focuses on the issue of localization/internationalization in Java applications.

The org.slf4j.cal10n package which ships with slf4j-ext-${project.version}.jar adds an extremely thin layer on top of CALI0N to offer localized logging.

Once you have a handle on an IMessageConveyor instance, you can create a LocLoggerFactory, which in turn can create LocLogger instances capable of doing localized logging.

Let us assume that you have defined localized message in your application. In accordance with the CAL10N's philosophy, you have the declared the keys for those messages in the enum type Production.

import ch.qos.cal10n.LocaleData;
import ch.qos.cal10n.Locale;
import ch.qos.cal10n.BaseName;

@BaseName("production")
@LocaleData( { @Locale("en_UK"), @Locale("ja_JP") })
public enum Production  {
  APPLICATION_STARTED,
  APPLICATION_STOPPED,
  ...
  DB_CONNECTION,
  DB_CONNECTION_FAILURE;
}

It is assumed that you have created appropriate bundle file for the various locales "en_UK" and "ja_JP" as appropriate. Here is a sample bundle for the "en_UK" locale.

APPLICATION_STARTED=Application {0} has started.
APPLICATION_STOPPED=Application {0} has stopped.
... 

Then, you can instantiate a IMessageConveyor, inject it into a LogLoggerFactory, retrieve multiple LogLogger instances by name and log away, as the next sample code illustrates.

import java.util.Locale;

import org.slf4j.cal10n.LocLogger;
import org.slf4j.cal10n.LocLoggerFactory;

import ch.qos.cal10n.IMessageConveyor;
import ch.qos.cal10n.MessageConveyor;

public class MyApplication {

  // create a message conveyor for a given locale 
  IMessageConveyor  messageConveyor = new MessageConveyor(Locale.UK);
  
  // create the LogLoggerFactory
  LocLoggerFactory llFactory_uk = new LocLoggerFactory(messageConveyor);
  
  // create a locLogger
  LocLogger locLogger = llFactory_uk.getLocLogger(this.getClass());
  

  public void applicationStart() {
    locLogger.info(Production.APPLICATION_STARTED, "fooApp");
    // ..
  }
  
  public void applicationStop() {
    locLogger.info(Production.APPLICATION_STOPPED, "fooApp");
    // ...
  }
}

Assuming the resource bundle production_en_UK.properties exists, and the underlying logging framework is enabled for the info level, log messages will be output in UK English.

Note that a LogLogger is a regular SLF4J logger with additional methods supporting localization. For those additional methods which take an enum as first parameter, LogLogger follows the standard Java convention for parameter substitution as defined by the java.text.MessageFormat class. For non-localized logs, which take a String as first parameter, LogLogger follows the {} convention, as customary for all org.slf4j.Logger implementations.

Here is an example illustrating the difference.

import ...;
public class MyApplication {

  IMessageConveyor  messageConveyor = new MessageConveyor(Locale.UK);
  LocLoggerFactory llFactory_uk = new LocLoggerFactory(messageConveyor);
  LocLogger locLogger = llFactory_uk.getLocLogger(this.getClass());

  public void someMethod() {
    // follows the MessageFormat convention
    locLogger.info(Production.APPLICATION_STARTED, "fooApp");

   // follows the {} convention
   logLogger.info("Hello {}", name);
   ...  
  }  
}