Créer une application Web multilingue avec Spring MVC

View more Tutorials:

See more:

1- L'objectif de ce document

Il est préférable de créer un site multilingue parce qu'il aide votre site Web à accéder à plus d'utilisateurs. Le Website est connu sous le nom d' internationalization (i18n) qui s'oppose à la Localization (localisation) (L10n).
Le site web ( o7planning.org) que vous visitez est un site internationalisateur. Le site Web est maintenant disponible en 2 langues, dont l'anglais, le vietnamien, le français, l'allemand et le russe.
Remarque: Internationalization est un mot comprenant 18 caractères, le premier caractère est i et le dernier est n, donc il est généralement abrégé en​​​​​​​ i18n.
Spring fournit un soutien étendu pour l'internationalisation (Internationalization) (i18n) grâce à l'utilisation de  Spring Interceptor, Locale Resolvers et  Resource Bundles pour différents sites régionaux.
Dans cette publication, je vous guiderai pour créer un simple site multilingue utilisant ​​​​​​​ Spring MVC.
Vous pouvez prévisualiser l'exemple ci-dessous:
Dans l'exemple, l'information locale ( Locale) se trouve sur le paramètre de l' URL. Les informations locales seront stockées dans Cookie et l'utilisateur ne doivent pas sélectionner de nouveau la langue dans les pages suivantes.
  • http://localhost:8080/SpringMVCInternationalization/login1?lang=vi
  • http://localhost:8080/SpringMVCInternationalization/login1?lang=fr
Un autre exemple de l'information Locale située sur l' URL:
  • http://localhost:8080/SpringMVCInternationalization/vi/login2
  • http://localhost:8080/SpringMVCInternationalization/en/login2

2- Créer le projet Maven

  • File/New/Other..
  • Group Id: org.o7planning
  • Artifact Id: SpringMVCInternationalization
  • Package: org.o7planning.springmvcinternationalization
Le projet est créé:
Assurez- vous que votre projet utilise Java >= 6.
Project Properties:

3- Message Resources

Ici, je crée trois fichiers  properties pour des langues:  y compris: anglais, français et vietnamien. Ces fichiers seront chargés (load) et gérés par  messageResource Bean.
i18n/messages_en.properties
#Generated by Eclipse Messages Editor (Eclipse Babel)

label.password = Password
label.submit   = Login
label.title    = Login Page
label.userName = User Name

 
i18n/messages_fr.properties
#Generated by Eclipse Messages Editor (Eclipse Babel)

label.password = Mot de passe
label.submit   = Connexion
label.title    = Connectez-vous page
label.userName = Nom d'utilisateur

 
i18n/messages_vi.properties
#Generated by Eclipse Messages Editor (Eclipse Babel)

label.password = M\u1EADt kh\u1EA9u
label.submit   = \u0110\u0103ng nh\u1EADp
label.title    = Trang \u0111\u0103ng nh\u1EADp
label.userName = T\u00EAn ng\u01B0\u1EDDi d\u00F9ng
 
Eclipse vous fournit d'éditer l'information de fichier en utilisant  "Message Editor".

4- La configuration Spring MVC

Si vous créez un site multilingue, vous devez utiliser l'encodage  UTF-8.
SpringWebAppInitializer.java
package org.o7planning.springmvcinternationalization.config;

import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;

public class SpringWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(ApplicationContextConfig.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDispatcher",
                new DispatcherServlet(appContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");

        // UtF8 Charactor Filter.
        FilterRegistration.Dynamic fr = servletContext.addFilter("encodingFilter", CharacterEncodingFilter.class);

        fr.setInitParameter("encoding", "UTF-8");
        fr.setInitParameter("forceEncoding", "true");
        fr.addMappingForUrlPatterns(null, true, "/*");
    }

}
Si vous devez déclarer 2 chaines  Spring BEAN y compris localeResolver et  messageResource.

localeResolver - Spécifie comment obtenir des informations locales (Locale) que l'utilisateur utilisera. CookieLocaleResolver lira les informations locales de Cookie afin de trouver quelle langue que l'utilisateur a utilisé.

messageResource - Va prendre en charge le contenu des fichiers  properties.
ApplicationContextConfig.java
package org.o7planning.springmvcinternationalization.config;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration

@ComponentScan("org.o7planning.springmvcinternationalization.*")
public class ApplicationContextConfig {

   @Bean(name = "viewResolver")
   public InternalResourceViewResolver getViewResolver() {
       InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

       viewResolver.setPrefix("/WEB-INF/pages/");
       viewResolver.setSuffix(".jsp");

       return viewResolver;
   }
   
   @Bean(name = "messageSource")
   public MessageSource getMessageResource()  {
       ReloadableResourceBundleMessageSource messageResource= new ReloadableResourceBundleMessageSource();
       
       // Read i18n/messages_xxx.properties file.
       // For example: i18n/messages_en.properties

       messageResource.setBasename("classpath:i18n/messages");
       messageResource.setDefaultEncoding("UTF-8");
       return messageResource;
   }
   
   @Bean(name = "localeResolver")
   public LocaleResolver getLocaleResolver()  {
       CookieLocaleResolver resolver= new CookieLocaleResolver();
       resolver.setCookieDomain("myAppLocaleCookie");
       // 60 minutes
    
       resolver.setCookieMaxAge(60*60);
       return resolver;
   }
   

}
Avant que la commande ne soit traitée par Controller, elle doit passer par les Interceptors où vous devez enregistrer LocaleChangeInterceptor, Interceptor traite les changements Locale de l'utilisateur.
WebMvcConfig.java
package org.o7planning.springmvcinternationalization.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

   // Static Resource Config
   @Override
   public void addResourceHandlers(ResourceHandlerRegistry registry) {

       // Default..
   }

   @Override
   public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
       configurer.enable();
   }

   @Override
   public void addInterceptors(InterceptorRegistry registry) {
       LocaleChangeInterceptor localeInterceptor = new LocaleChangeInterceptor();
       localeInterceptor.setParamName("lang");
     
     
       registry.addInterceptor(localeInterceptor).addPathPatterns("/*");
   }
 
}

5- Controller & Views

MainController.java
package org.o7planning.springmvcinternationalization.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MainController {

   @RequestMapping(value = "/login1")
   public String login1(Model model) {
       return "login1";
   }
 
}
login1.jsp
<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ page session="false"%>


<!DOCTYPE html>

<html>
<head>

<meta charset="UTF-8">

<title><spring:message code="label.title" /></title>
</head>
<body>

    <div style="text-align: right;padding:5px;margin:5px 0px;background:#ccc;">
       <a href="${pageContext.request.contextPath}/login1?lang=en">Login (English)</a>
       &nbsp;&nbsp;
       <a href="${pageContext.request.contextPath}/login1?lang=fr">Login (French)</a>
       &nbsp;&nbsp;
       <a href="${pageContext.request.contextPath}/login1?lang=vi">Login (Vietnamese)</a>
    </div>
 
    <form method="post" action="">
        <table>
            <tr>
                <td>
                 <strong>
                <spring:message    code="label.userName" />
                </strong>
                </td>
                <td><input name="userName" /></td>
            </tr>
            <tr>
                <td>
                 <strong>
                <spring:message    code="label.password" />
                </strong>
                </td>
                <td><input name="password" /></td>
            </tr>
            <tr>
                <td colspan="2">
                <spring:message code="label.submit" var="labelSubmit"></spring:message>
                <input type="submit" value="${labelSubmit}" />
                </td>
            </tr>
        </table>
    </form>
</body>
</html>

 

6- Configurer et exécuter de l'application

Test URL:

7- L'information Locale sur URL

Dans le cas où vous souhaitez créer un site Web multilingue, l'information Locale se trouve sur l' URL. Vous devez modifier certaines configurations:
  • http://localhost:8080/SpringMVCInternationalization/vi/login2
  • http://localhost:8080/SpringMVCInternationalization/en/login2
Créez deux classes  UrlLocaleInterceptor et  UrlLocaleResolver.
UrlLocaleInterceptor.java
package org.o7planning.springmvcinternationalization.interceptor;

import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import org.springframework.web.servlet.support.RequestContextUtils;

public class UrlLocaleInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {

        LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);

        if (localeResolver == null) {
            throw new IllegalStateException("No LocaleResolver found: not in a DispatcherServlet request?");
        }
        // Get locale from LocaleResolver.
   
        Locale locale = localeResolver.resolveLocale(request);

        localeResolver.setLocale(request, response, locale);

        return true;
    }

}

 
UrlLocaleResolver.java
package org.o7planning.springmvcinternationalization.resolver;

import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.LocaleResolver;

public class UrlLocaleResolver implements LocaleResolver {

    private static final String URL_LOCALE_ATTRIBUTE_NAME = "URL_LOCALE_ATTRIBUTE_NAME";

    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        // ==> /SpringMVCInternationalization/en/...
        // ==> /SpringMVCInternationalization/fr/...
        // ==> /SpringMVCInternationalization/WEB-INF/pages/...
        String uri = request.getRequestURI();

        System.out.println("URI=" + uri);

        String prefixEn = request.getServletContext().getContextPath() + "/en/";
        String prefixFr = request.getServletContext().getContextPath() + "/fr/";
        String prefixVi = request.getServletContext().getContextPath() + "/vi/";

        Locale locale = null;
       
        // English
        if (uri.startsWith(prefixEn)) {
            locale = Locale.ENGLISH;
        }
        // French
        else if (uri.startsWith(prefixFr)) {
            locale = Locale.FRANCE;
        }
        // Vietnamese
        else if (uri.startsWith(prefixVi)) {
            locale = new Locale("vi", "VN");
        }
        if (locale != null) {
            request.getSession().setAttribute(URL_LOCALE_ATTRIBUTE_NAME, locale);
        }
        if (locale == null) {
            locale = (Locale) request.getSession().getAttribute(URL_LOCALE_ATTRIBUTE_NAME);
            if (locale == null) {
                locale = Locale.ENGLISH;
            }
        }
        return locale;
    }

    @Override
    public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
        // Nothing
    }

}

 
Éditez la classe ApplicationContextConfig:
ApplicationContextConfig.java
package org.o7planning.springmvcinternationalization.config;

import org.o7planning.springmvcinternationalization.resolver.UrlLocaleResolver;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan("org.o7planning.springmvcinternationalization.*")
public class ApplicationContextConfig {

    @Bean(name = "viewResolver")
    public InternalResourceViewResolver getViewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();

        viewResolver.setPrefix("/WEB-INF/pages/");
        viewResolver.setSuffix(".jsp");

        return viewResolver;
    }
   
    @Bean(name = "messageSource")
    public MessageSource getMessageResource()  {
        ReloadableResourceBundleMessageSource messageResource= new ReloadableResourceBundleMessageSource();
       
        // Read i18n/messages_xxx.properties file.
        // For example: i18n/messages_en.properties
     
        messageResource.setBasename("classpath:i18n/messages");
        messageResource.setDefaultEncoding("UTF-8");
        return messageResource;
    }
 
 
    // To solver URL like:
    // /SpringMVCInternationalization/en/login2
    // /SpringMVCInternationalization/vi/login2
    // /SpringMVCInternationalization/fr/login2
    @Bean(name = "localeResolver")
    public LocaleResolver getLocaleResolver()  {
        LocaleResolver resolver= new UrlLocaleResolver();
        return resolver;
    }
   
 
}
Rechangez la configuration  Interceptor dans  WebMvcConfig:
WebMvcConfig.java
package org.o7planning.springmvcinternationalization.config;

import org.o7planning.springmvcinternationalization.interceptor.UrlLocaleInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {


   @Override
   public void addResourceHandlers(ResourceHandlerRegistry registry) {

       // Default..
   }

   @Override
   public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
       configurer.enable();
   }

   @Override
   public void addInterceptors(InterceptorRegistry registry) {

       UrlLocaleInterceptor localeInterceptor = new UrlLocaleInterceptor();

       registry.addInterceptor(localeInterceptor).addPathPatterns("/en/*", "/fr/*", "/vi/*");
   }

}
Controller:
MainController.java
package org.o7planning.springmvcinternationalization.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class MainController {

    @RequestMapping(value = "/{locale:en|fr|vi}/login2")
    public String login2(Model model) {
        return "login2";
    }
   
}
login2.jsp
<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ page session="false"%>


<!DOCTYPE html>

<html>
<head>

<meta charset="UTF-8">

<title><spring:message code="label.title" /></title>
</head>
<body>

    <div style="text-align: right;padding:5px;margin:5px 0px;background:#ccc;">
       <a href="${pageContext.request.contextPath}/en/login2">Login (English)</a>
       &nbsp;&nbsp;
       <a href="${pageContext.request.contextPath}/fr/login2">Login (French)</a>
       &nbsp;&nbsp;
       <a href="${pageContext.request.contextPath}/vi/login2">Login (Vietnamese)</a>
    </div>
 
    <form method="post" action="">
        <table>
            <tr>
                <td>
                 <strong>
                <spring:message    code="label.userName" />
                </strong>
                </td>
                <td><input name="userName" /></td>
            </tr>
            <tr>
                <td>
                 <strong>
                <spring:message    code="label.password" />
                </strong>
                </td>
                <td><input name="password" /></td>
            </tr>
            <tr>
                <td colspan="2">
                <spring:message code="label.submit" var="labelSubmit"></spring:message>
                <input type="submit" value="${labelSubmit}" />
                </td>
            </tr>
        </table>
    </form>
</body>
</html>

 
L'exécution de l'application:

8- Les sites multilingues avec contenu stocké dans DB

The example of a multilingual website above is unable to satisfy you. You have the demand for a news website with multiple languages, and its content is stored in Database. A solution you can use multiple Datasources in which each datasoure is a database containing the content of a language.
Vous pouvez voir plus à

View more Tutorials: