LocaleChangeInterceptor - internationalization

In the previous sections, we saw how to create an interceptor (ProcessingTimeLogInterceptor) and configure it in our web application context. Spring provides some pre-built interceptors that we can configure in our application context as and when needed. One such pre-built interceptor is LocaleChangeInterceptor, which allows us to change the current locale on every request and configures LocaleResolver to support internationalization.

Internationalization means adapting computer software to different languages and regional differences. For example, if you are developing a web application for a Dutch-based company, they may expect all the web page text to be displayed in the Dutch language, use the Euro for currency calculations, expect a space as a thousand separator when displaying numbers, and use a "," (comma) as a decimal point. On the other hand, when the same Dutch company wants to open a market in America, they expect the same web application to be adapted for American locales; for example, the web pages should be displayed in English, dollars should be used for currency calculations, numbers should be formatted with "," (comma) as the thousand separator, a "." (dot) acts as a decimal point, and so on.

The technique for designing a web application that can automatically adapt to different regions and countries without needing to be re-engineered is called internationalization, sometimes shortened to i18n (i-eighteen letters-n).

In Spring MVC, we can achieve internationalization through LocaleChangeInterceptor (org.springframework.web.servlet.i18n.LocaleChangeInterceptor). The LocaleChangeInterceptor allows us to change the current locale for every web request via a configurable request parameter.

In Chapter 4, Working with Spring Tag Libraries, we have seen how to externalize text messages in the add products page; now we are going to add internationalization support for the same add products page (addProducts.jsp), because in Spring MVC, prior to internationalizing a label, we must externalize that label first. Since we already externalized all the label messages in the add products page (addProducts.jsp), we can proceed to internationalize the add products page.

Time for action - adding internationalization

Technically we can add support for as many languages as we want with internationalization, but for demonstration purposes I am going to show you how to make our add products page with Dutch language support:

  1. Create a file called messages_nl.properties under /src/main/resources in your project, add the following lines in it, and save the file:
          addProduct.form.productId.label = Nieuw product ID 
          addProduct.form.name.label = Naam 
          addProduct.form.unitPrice.label = prijs per eenheid 
          addProduct.form.manufacturer.label = fabrikant 
          addProduct.form.category.label = categorie 
          addProduct.form.unitsInStock.label = Aantal op voorraad 
          addProduct.form.description.label = Beschrijving 
          addProduct.form.condition.label = Product Staat 
          addProduct.form.productImage.label = product afbeelding 
    
  2. Open our addProduct.jsp and add the following set of tags right after the <body> tag:
          <section> 
             <div class="pull-right" style="padding-right:50px"> 
                <a href="?language=en" >English</a>|<a href="?
                language=nl" >Dutch</a>                
             </div> 
          </section> 
    
  3. Now open our web application context configuration file, WebApplicationContextConfig.java, and add one more bean definition for the locale resolver as follows:
          @Bean 
          public LocaleResolver localeResolver(){ 
             SessionLocaleResolver resolver = new 
             SessionLocaleResolver(); 
             resolver.setDefaultLocale(new Locale("en")); 
        
             return resolver; 
          } 
    
  4. Now change our addInterceptors method to configure one more interceptor in our InterceptorRegistry as follows:
          @Override 
          public void addInterceptors(InterceptorRegistry registry) { 
             registry.addInterceptor(new 
             ProcessingTimeLogInterceptor()); 
        
             LocaleChangeInterceptor localeChangeInterceptor = new
          LocaleChangeInterceptor();
       
          localeChangeInterceptor.setParamName("language");
             
          registry.addInterceptor(localeChangeInterceptor); 
          } 
    
  5. Now run our application and enter the http://localhost:8080/webstore/market/products/add URL; you will be able to see our regular add products page with two extra links in the top-right corner to choose the language:
    Time for action - adding internationalization

    The add products page showing internationalization support to choose languages

  6. Now click on the Dutch link; you will see the product ID label transformed into the Dutch caption Nieuw product ID.
  7. Since our configured LocaleChangeInterceptor will add a request parameter called language to the web request, we need to add this language request parameter to our whitelisting set in our ProductController. Open our ProductController and, within the initialiseBinder method, add the language request parameter to the whitelisting set as follows:
          binder.setAllowedFields("productId", 
                      "name", 
                      "unitPrice", 
                      "description", 
                      "manufacturer", 
                      "category", 
                      "unitsInStock", 
                      "condition", 
                      "productImage", 
                      "language"); 
    

What just happened?

In step 1, we just created a property file called messages_nl.properties. This file acts as a Dutch-based message source for all our externalized label messages in the addProducts.jsp file. In order to display the externalized label messages, we used the <spring:message > tag in our addProducts.jsp file.

But by default, the <spring:message > tag will read messages from the messages.properties file only; we need to make a provision for our end user to switch to the Dutch locale when they view the webpage, so that the label messages can come from the messages_nl.properties file. We provided such a provision through a locale-choosing link in addProducts.jsp, as mentioned in step 2:

<a href="?language=en" >English</a>|<a href="?language=nl"       >Dutch</a> 

In step 2, we created two links, one each to choose English or Dutch as the preferred locale. When the user clicks on one of these links, it will add a request parameter called language to the URL with the corresponding locale value. For example, when we click on the English link on the add products page at runtime, it will change the request URL to http://localhost:8080/webstore/products/add?language=en ; similarly if you click on the Dutch link, it will change the request URL to http://localhost:8080/webstore/products/add?language=nl .

In step 3, we created a SessionLocaleResolver bean in our web application context as follows:

@Bean 
public LocaleResolver localeResolver(){ 
   SessionLocaleResolver resolver = new SessionLocaleResolver(); 
   resolver.setDefaultLocale(new Locale("en")); 
    
   return resolver; 
} 

SessionLocaleResolver is the one that sets the locale attribute in the user's session. One important property of SessionLocaleResolver is defaultLocale. We assigned en as the value for the default locale, which indicates that by default our page should use English as its default locale.

In step 4, we created a LocaleChangeInterceptor bean and configured it in the existing interceptor list:

@Override 
public void addInterceptors(InterceptorRegistry registry) { 
   registry.addInterceptor(new ProcessingTimeLogInterceptor()); 
    
   LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); 
   localeChangeInterceptor.setParamName("language"); 
   registry.addInterceptor(localeChangeInterceptor); 
} 

We assigned the string language as the value for the paramName property in LocaleChangeInterceptor. There is a reason for this because, if you notice, in step 2 when we created the locale choosing link in add products page (addProduct.jsp), we used the same parameter name as the request parameter within the <a> tag:

<a href="?language=en" >English</a>|<a href="?language=nl" >Dutch</a> 

This way we can give a hint to LocaleChangeInterceptor to choose the correct user-preferred locale. So whatever parameter name you plan to use in your URL, use the same name as the value for the paramName property in LocaleChangeInterceptor. One more thing: whatever value you have given to the language request parameter in the link should match the translation message source file suffix. For example, in our case we have created a Dutch translation message source file, messages_nl.properties; here the suffix is nl and messages.properties without any suffix is considered the default for the en suffix. That's why in step 2 we have given nl and en as the values for the language parameters for Dutch and English, respectively:

<a href="?language=en" >English</a>|<a href="?language=nl" >Dutch</a> 

So finally, when we run our application and enter the http://localhost:8080/webstore/market/products/add URL, you will see our regular add products page with two extra links in the top-right corner to choose the language.

Clicking on Dutch changes the request URL to http://localhost:8080/webstore/market/products/add?language=nl, which brings up the LocaleChangeInterceptor and reads the Dutch-based label messages from messages_nl.properties.

Note that, if we do not give a language parameter in our URL, Spring will use the default message source file (messages.properties) for translation; if we give a language parameter, Spring will use that parameter value as the suffix to identify the correct language message source file (messages_nl.properties).

Have a go hero - fully internationalize the product details page

As I already mentioned just for demonstration purposes, I have internationalized a single web page (addProducts.jsp). I encourage you to internationalize the product detail web page (product.jsp) in our project. You can use the Google translate service (https://translate.google.com/) to find out the Dutch translation for labels. Along with this, try to add language support for one more language of your choice.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.252.87