Make writing a habit together! This is the 10th day of my participation in the “Gold Digging Day New Plan · April More text Challenge”. Click here for more details.

First, SpringMVC uses internationalization based on annotations

In our daily work, if our website needs to be viewed by people in different language regions, we need to use the basic operation of internationalization, which is easier for SpringMVC. Let’s start by creating a simple page for internationalization operations

1-1. Create the login page

First, we need to build a Framework for SpringMVC. If you have any questions about the framework, please read the previous article.

<%@ page contentType="text/html; charset=UTF-8" language="java" %> <% request.setAttribute("basePath",request.getContextPath()); %> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton, And Bootstrap polymorphism "> <meta name="generator" content="Hugo 0.88.1"> <title> internationalization -- I18N </title> <link Rel = "canonical" href = "https://getbootstrap.com/docs/5.1/examples/sign-in/" > <! -- Bootstrap core CSS --> <link href="${basePath}/assets/dist/css/bootstrap.min.css" rel="stylesheet"> <style> The bd - placeholder - img {the font - size: 1.125 rem; text-anchor: middle; -webkit-user-select: none; -moz-user-select: none; user-select: none; } @media (min-width: 768px) {. Bd-placeholder -img-lg {font-size: 3.5rem; } } </style> <! -- Custom styles for this template --> <link href="${basePath}/assets/dist/css/signin.css" rel="stylesheet"> </head> <body class="text-center"> <main class="form-signin"> <form> <img class="mb-4" src="${basePath}/assets/brand/bootstrap-logo.svg" alt="" width="72" height="57"> <h1 class="h3 mb-3 fw-normal">Please sign in</h1> <div class="form-floating"> <input type="email" class="form-control" id="floatingInput" placeholder="[email protected]"> <label for="floatingInput">Email address</label> </div> <div class="form-floating"> <input type="password" class="form-control" id="floatingPassword" placeholder="Password"> <label for="floatingPassword">Password</label> </div> <div class="checkbox mb-3"> <label> <input type="checkbox" value="remember-me"> Remember me </label> </div> <button class="w-100 btn btn-lg btn-primary" type="submit">Sign in</button> <p class="mt-5 mb-3 text-muted">&copy; </p> </form> </main> </body> </ HTML >Copy the code

Visit the following page:

1-2. How to achieve internationalization

Think about it, how can we achieve international? Generally, internationalization requires compatibility with two or more languages. In this case, we have two ways to achieve this:

Create N sets of view pages for different languages. 2. Create a page and load different language packages according to the browser language

The first option is generally not used unless different language pages have different requirements for customization. The second option is therefore commonly used for internationalization.

1-3. Internationalize by setting the language in the browser

1-3-1. Create a language pack

1. Create a language package to put all the text in the view page in the same file, such as en_us.properties/zn_ch.properties, so that there are two language packages. 2. Create different language packages for different views, such as login/ login_en_us.properties. The login/login_zn_CH properties.

These two schemes can be selected according to the actual situation of the project. The second scheme is used in this paper.

To facilitate the operation of the internationalized language pack, we need to install a plug-in “Resource Bunlder Editor” for IDEA.

The resulting language package is as follows:

Chinese and English language packs are created. For later maintenance and convenience, we need to name our files in accordance with i18N. For details, you can search the i18N comparison table.

1-3-2. Create a language

Click + ok, add a TXT text key, this key can be written casually, but for semantic suggestions or write English meaning.

Then each language package creates the corresponding text message

1-3-3. Configure in the Spring-MVC file

<! -- Set internationalization support, Internationalization attribute resource configuration file -- > < bean class = "org. Springframework. Context. Support. ResourceBundleMessageSource" id = "messageSource" > <property name="basenames"> <array> <value>i18N.login</value> </array> </property> </bean>Copy the code

If there are many resource files, you can add them to array.

1-3-4, the view layer is internationalized

In springMVC, the view layer can be internationalized in two ways: JSTL tags and spring tag libraries

The 1-3-4-1 JSLT tag is internationalized

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>.... <body> <! -- < FMT :setLocale value="${param.setLocale}"/> The value of the locale is obtained from the parameter passed --> < FMT :setLocale value="en_US"/> <! < FMT: basename="login"> <! Basename = basename = login; <table> <tr> < TD >< FMT :message key="email"/></ TD ><input type="text" name="email"></ TD >  </tr> </table> </center> </fmt:bundle> </body>Copy the code

1-3-4-2. Use the Spring tag library

1. You need to import the spring tag library first

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
Copy the code

2. Replace the text with the Spring: Message tag

<spring:message code="txt_password">
Copy the code

3. After the final replacement, our login.jsp page is:

<%@ page contentType="text/html; charset=UTF-8" language="java" %> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <% request.setAttribute("basePath",request.getContextPath()); %> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content=""> <meta name="author" content="Mark Otto, Jacob Thornton, And Bootstrap polymorphism "> <meta name="generator" content="Hugo 0.88.1"> <title> internationalization -- I18N </title> <link Rel = "canonical" href = "https://getbootstrap.com/docs/5.1/examples/sign-in/" > <! -- Bootstrap core CSS --> <link href="${basePath}/assets/dist/css/bootstrap.min.css" rel="stylesheet"> <style> The bd - placeholder - img {the font - size: 1.125 rem; text-anchor: middle; -webkit-user-select: none; -moz-user-select: none; user-select: none; } @media (min-width: 768px) {. Bd-placeholder -img-lg {font-size: 3.5rem; } } </style> <! -- Custom styles for this template --> <link href="${basePath}/assets/dist/css/signin.css" rel="stylesheet"> </head> <body class="text-center"> <main class="form-signin"> <form> <img class="mb-4" src="${basePath}/assets/brand/bootstrap-logo.svg" alt="" width="72" height="57"> <h1 class="h3 mb-3 fw-normal"><spring:message code="txt_plase_login"/></h1> <div class="form-floating"> <input type="email" class="form-control" id="floatingInput" placeholder="[email protected]"> <label for="floatingInput"><spring:message code="txt_email"></label> </div> <div class="form-floating"> <input type="password" class="form-control" id="floatingPassword" placeholder="Password"> <label for="floatingPassword"><spring:message code="txt_password"></label>  </div> <div class="checkbox mb-3"> <label> <input type="checkbox" value="remember-me"> <spring:message code="txt_remember_me"> </label> </div> <button class="w-100 btn btn-lg btn-primary" type="submit"><spring:message code="txt_login"></button> <p class="mt-5 mb-3 text-muted">&copy; </p> </form> </main> </body> </ HTML >Copy the code

The 1-3-4-3, test

Finally, the access controller found this error and found that the key was not found. Finally, it found that there was no real-time compilation after the resource file was added using IDEA. The historical compilation file was deleted, and the access was recompiled

This time, there is the problem of Chinese garbled code, and then deal with it as follows

Restart the service and access it again

Set the browser language to English and visit again as follows:

1-3-5, the realization principle

In fact, internationalization in SpringMVC is handled very simply based on the language information brought by the browser. By default, SpringMVC determines the client’s localization type based on the accept-language parameter.

When a request is received, SpringMVC looks in the context – a localization resolver (LocalResolver) that it finds and uses to get information about the localization type of the request: Locale Locale = request.getlocale (); // Get the browser area information

1-4. Set internationalization with a custom parser

Above case mainly by modifying the browser’s language, and then at the time of the request, through the request in the request header with language setting, allow for springmvc by using AcceptHandlerLocaleResolver to parse.

Our own implementation is also covered by actual AcceptHandlerLocaleResolver, then carry language mark in the request

1-4-1. Inject SessionLocaleResolver into Spring

The purpose of this is to save the language to SessionLocaleResolver while the page is switching, so that subsequent pages can be displayed in the same language when they are accessed again

<! -- Use SessionLocaleResolver to keep Local Will save session to obtain Local object - > < bean class = "org. Springframework. Web. Servlet. I18n. SessionLocaleResolver" id="localeResolver"></bean>Copy the code

1-4-2. Write a controller to save the language Settings

@param localeResolver inserts SessionLocaleResolver into the method * @param request * @param response * @return */ @RequestMapping("/i18n/{local}") public String changeLocal(@PathVariable String local, @Autowired SessionLocaleResolver localeResolver, HttpServletRequest request, HttpServletResponse response){ Locale locale=new Locale(local.split("_")[0],local.split("_")[1]); localeResolver.setLocale(request,response,locale); return "login"; }Copy the code

1-4-3. Modify the Login page to switch between Chinese and English

< div class = "row" > < a class = "col - 6" href = "${basePath} / i18n/zh_CN" > English < / a > < a class = "col - 6" href="${basePath}/i18n/en_US">Englis h</a> </div>Copy the code

This completes the language switch

1-5. Set up internationalization using the SpringMVC interceptor

1-5-1. Add interceptors in Spring-MVC

<! Use the interceptor provided by SpringMVC to accept locale arguments, Set to session - > < MVC: interceptors > < bean class = "org. Springframework. Web. Servlet. I18n. LocaleChangeInterceptor" > < / bean > </mvc:interceptors>Copy the code

Check the LocaleChangeinterceptor source code for the preHandle method:

You can see that the first step passeslocaleGet the parameters passed to the page and set them to LocaleResolver. The actual processing method is basically the same as above.

1-5-2, login.jsp modify internationalization support

<div class="row"> use the interceptor to set locale<p></p> <a class="col-6" href="? Locale =zh_CN"> </a> <a class="col-6" href="? locale=en_US">English</a> </div>Copy the code

Second, the summary

2-1. Internationalization of language switch based on browser Settings

1. Create login.properties login_en_US. Properties login_zh_CN. Configure SpringMVC to inject internationalization resource files into SpringMVC

<bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource">
        <property name="basenames">
             <array>
                 <value>i18n/login</value>
             </array>
         </property>

</bean>
Copy the code

3. Call the properties resource file on the page

< spring:message> </spring:message>

2-2. Switch languages using hyperlinks

1. Change the default localization language parser LocaleResolver to SessionLocaleResolver

Method 1: Create a request method and receive local parameters (en_US and zh_CN) to set the session to be removed. Method 2: Use the interceptor provided by SpringMVC to receive local parameters (en_US and zh_CN) to set the session to be removedCopy the code

Third, Java error message internationalization processing.

3-1. The Spring Form tag returns an error message using JSR303

3-1-1. Modify the controller method for the login page

Using the Spring Formb tag to display error messages, you must jump from the controller because you need to add a Model. The User is added to the Model automatically, mainly to assign values to The modelAttribute in the JSP page form tag.This is a necessary step

3-1-2. Modify the login page

1. Add the Spring Form tag

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
Copy the code

Change the form tag to modelAttribute=”user” in the code below the Spring Form tag, which is the variable name in the jump page controller above

<form:form action="${basePath}/login" method="post" modelAttribute="user">
Copy the code

The error message also uses the Spring Form tag. The value of path must be consistent with the property in the User bean.

<form:errors path="email"></form:errors>
Copy the code
<form:errors path="password"></form:errors>
Copy the code

Use Maven to add validator packages

<dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-validator</artifactId> < version > 5.1.3. Final < / version > < / dependency >Copy the code

Add User Bean and set JSR303 annotation

Set authentication annotations for email and password respectively

Add the login submission method

With JSR303, be sure to add BindingResult to the method parameters

In the 3-2-6 s, test,

So the error message is displayed, but if the page switches to English, the error message is still in Chinese, which is a problem. Therefore, we also need to internationalize the background information.

3-2. Internationalize the content in your code

3-2-1. Set up internationalization using MessageSource

3-2-1-1. Inject MessageSource in controller

Use MessageSource to get the value of the property key, since the language of internationalization has been set through the filter /SessionLocaleResolver, so MessageSource. GetMessage (), You can automatically obtain the information configured in the resource file by passing in the corresponding error key and Locale.You can see that the second argument in the getMessage method is currently passed null, in this case an object[] can be passed related parameters, such as when we modify the resource file login_err:

Then modify the controller as follows:

The tests are as follows:

The 3-2-2-2, test

As you can see below, the email or password error is displayed in English

The following is in Chinese

3-3, internationalization JSR303 annotation error message

3-3-1, methodInvocation: Error that occurs when Spring MVC invocation handles methods

JSR303 error messages are in the following format when configuring resource files: The key prefix is: Comments. Object. Property. For example, notempty.user. email= The mailbox cannot be empty

3-3-1-1. Processing validation annotation information in user

The authentication information can be removed from the user

3-3-1-2. Test verification

3-3-2, typeMismatch: data typeMismatch occurs during data binding

This is a datatype check as we have a birthday format

Key prefix: typeMismatch. Object. Attribute typeMismatch. User. Birthday = birthday date format error

3-3-2-1. Add attribute error message

3-3-2-2. Modify the JSP page

3-3-2-3, test verification

Internationalization processing is complete here!