Tech and Media Labs
This site uses cookies to improve the user experience.




Localization and Internationalization

Jakob Jenkov
Last update: 2016-05-20

If your application is to be ported to different languages you will need to be able to localize the components in your application. Butterfly Container can help you do that.


Instantiation and Execution Time Localization

When localizing a component you basically have two options:

  1. Instantiation Time Localization
  2. Execution Time Localization

Instantiation Time Localization

Instantiation time localization means that you inject localized dependencies (texts, paths, number and date formatters etc.) into the component when it is instantiated. The component doesn't have to know anything about Locale or the localization mechanism used. Furthermore, since resources are injected it is visible from the interface of the component what resources it needs. This makes instantiation time localization a nice and clean localization method.

In order for instantiation time localization to work the Locale (language) to localize to must be known when the component is instantiated. This is not always the case.


Execution Time Localization

Execution time localization means that the component obtains the localized dependencies when it executes. For this to work the Locale does not have to be known until execution time. This is often the case for singletons that need to produce localized output in different languages during the same runtime session. For instance, for a singleton component in a web application, the language to localize to depends on the language chosen by the current user. The singleton may serve requests for several users at the same time, each with a different language selected.


Instantiation or Execution Time Localization?

Instantiation time localization is the cleanest way to localize your components, but execution time localization is the most flexible way, meaning it works for all situations. Of course you can use both methods in your application depending on the situation, but you risk that maintenance developers get confused about how a given component is localized.

Furthermore, instantiation time localization can lead to more messy configurations and code. If a component needs a lot of localized resources (texts and paths for instance), the configuration of that component factory in the container script grows quite large. In addition the component needs members (field + perhaps getters/setters) for those resources, so the component code may grow unnecessarily too.

Here is an instantiation time localization example:

//instantiation time localization example
public class MyComponent{
  String localText1 = null;
  String localText2 = null;

  public void setLocalText1(String text){ this.localText1 = text; }
  public void setLocalText2(String text){ this.localText2 = text; }

  public void execute(...){
    //output the localized texts, localText1 and localText2
    System.out.print(localText1);
    System.out.print(localText2);
  }
}

Here is the butterfly container script for the MyComponent configuration:

myComponent = * com.myapp.MyComponent().setLocalText1(...)
                                       .setLocalText2(...);

As you can imagine, the more resources the MyComponent needs, the larger both the class and the configuration grows. The advantage is that you can see from the configuration exactly what dependencies the MyComponent has.

Here is the same example using execution time localization:

public class MyComponent{
 Resources resources = null;

 public MyComponent(Resources resources){
   this.resources = resources;
 }

 public void execute(...){
   Locale locale = ... //obtain locale for this request

   System.out.println(resources.get("localText1").get(locale));
   System.out.println(resources.get("localText2").get(locale));
 }
}

And here is the butterfly container script configuration for it:

myComponent = * com.myapp.MyComponent(resources);

As you can imagine, only the execute() method will grow as the number of localized dependencies grow. All localized dependencies are obtained from the Resources object. This makes execution time localization a less verbose localization method. The downside is that it leads to hidden dependencies. You can no longer see from the interface or configuration of MyComponent exactly what localized resources it needs.

Note, that this Resources object still needs to be configured somehow, but this configuration is left out of the example.

Which of the two methods you choose is up to you. Personally I think execution time localization is the simplest mechanism to use, and being the most flexible, working for singletons, flyweights, cached objects etc, it can be applied across all components in your application.

Jakob Jenkov




Copyright  Jenkov Aps
Close TOC