Page internationalization
Sometimes, our website will involve Chinese and English or even multi-language switch, this time we need to learn internationalization!
1. Preparation
First set the coding problem of properties in IDEA.Write an internationalization profile to extract the internationalization page messages that the page needs to display. We can go to the login page and see what configuration we need to write for internationalization!
2. Write configuration files
1. Create an i18N directory under resources to store the internationalization configuration files
What is I18n?
- Similarly, the K8S
Create a login.properties file and a login_zh_CN. Properties file.
Three new configuration files are created to configure the language:
-
Login. properties: takes effect when no language is configured
-
Login_en_us. properties: Valid in English
-
Login_zh_CN. Properties: Valid in Chinese
The names are combinations of underscores: filename _ language _ country. Properties;
We find that IDEA automatically recognizes that we need to do international operations; The folder has changed!
After binding together, we want to add more over the language configuration, just in the large resource packRight-click to add to the binding configuration fileCan beThe following page pops up: Let’s add another English one;At this time only need to enter the name of the region can be created successfully, such as enter en_US, it will be automatically recognized, so much faster!
Then open the English or Chinese language configuration file and click on the Resource Bundle to enter the visual editing pageAfter entering the visual editing page, click the plus sign to add attributes. First, create a login.tip to represent the prompt on the home pageThen do the language configuration for the prompt in three cases respectively, and enter the corresponding input boxes (note: IDEA2020.1 may not save, it is recommended to write in the configuration file directly).Double-clicking opens atlogin.tip
We can find visual configuration is very convenient, you can configure 3 at once
Next, configure all the variables for the language to be converted (note: IDEA2020.1 may not save, it is recommended to write directly in the configuration file)Then open the three configuration files to check the text content, you can see that all the configuration is done
Then go to our configuration file;
The login. The properties: the default
Password = password login.remember= remember me login.tip= please login login.username= usernameCopy the code
English:
login.btn=Sign in
login.password=Password
login.remember=Remember me
login.tip=Please sign in
login.username=Username
Copy the code
English:
Password = password login.remember= remember me login.tip= please login login.username= usernameCopy the code
OK, configuration file step done!
3. Check whether the configuration file takes effect
In the Spring in the program, the internationalization mainly through ResourceBundleMessageSource this class
Spring Boot by MessageSourceAutoConfiguration as we automatic configuration management component of internationalized resource file
In our IDEA, we view the following MessageSourceAutoConfiguration class
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingBean(name = AbstractApplicationContext.MESSAGE_SOURCE_BEAN_NAME, search = SearchStrategy.CURRENT)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@Conditional(ResourceBundleCondition.class)
@EnableConfigurationProperties
public class MessageSourceAutoConfiguration {
private static final Resource[] NO_RESOURCES = {};
@Bean
@ConfigurationProperties(prefix = "spring.messages")
public MessageSourceProperties messageSourceProperties(a) {
return new MessageSourceProperties();
}
@Bean
public MessageSource messageSource(MessageSourceProperties properties) {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
if (StringUtils.hasText(properties.getBasename())) {
// He can set our Basenames basic name
messageSource.setBasenames(StringUtils
// Then he will look for it from properties.getBasename(), our config file
.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(properties.getBasename())));
}
if(properties.getEncoding() ! =null) {
messageSource.setDefaultEncoding(properties.getEncoding().name());
}
messageSource.setFallbackToSystemLocale(properties.isFallbackToSystemLocale());
Duration cacheDuration = properties.getCacheDuration();
if(cacheDuration ! =null) {
messageSource.setCacheMillis(cacheDuration.toMillis());
}
messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat());
messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage());
return messageSource;
}
/ /...
}
Copy the code
MessageSource ()
public MessageSource messageSource(MessageSourceProperties properties);
Copy the code
As you can see, it takes the MessageSourceProperties object, so let’s look at this class
public class MessageSourceProperties {
/** * Comma-separated list of basenames (essentially a fully-qualified classpath * location), each following the ResourceBundle convention with relaxed support for * slash based locations. If it doesn't contain a package qualifier (such as * "org.mypackage"), it will be resolved from the classpath root. */
private String basename = "messages";
/** * Message bundles encoding. */
private Charset encoding = StandardCharsets.UTF_8;
Copy the code
The class first declares a property basename, which defaults to messages;
We translate the notes:
/** * Comma-separated list of basenames (essentially a fully-qualified classpath * location), each following the ResourceBundle convention with relaxed support for * slash based locations. If it doesn't contain a package qualifier (such as * "org.mypackage"), it will be resolved from the classpath root. */
Copy the code
-
Comma-separated list of base names (essentially fully qualified classpath locations)
-
Each follows the ResourceBundle convention and is easily supported at the location of the slash
-
If the package qualifier is not included (for example, “org.mypackage”), it will be resolved from the classpath root
It means:
-
If you do not specify in the SpringBoot configuration file. Separate the name of the internationalized resource file
-
By default, it goes to the classpath to find messages.properties as the internationalization resource file
Here we have customized the internationalization resource file, so we need to specify the name of our configuration file by adding the following configuration to the SpringBoot configuration file application.properties
# The real location of our configuration file
spring.messages.basename=i18n.login
Copy the code
I18n is the name of the folder where the resource is stored, and login is the basic name of the resource file.
4. Obtain the displayed internationalized value on the home page
Go to the page to obtain the value of internationalization, check the documentation of Thymeleaf, find the value of message: #{… }. Let’s go to the page to test:
IDEA and hints, very intelligent!
Use # {… } message expression, go to the home index. HTML to get the internationalized value, not in <>, use #[[#{}]]
<! DOCTYPEhtml>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>The login page</title>
<! -- Bootstrap core CSS -->
<link th:href="@{/css/bootstrap.min.css}" rel="stylesheet">
<! -- Custom styles for this template -->
<link th:href="@{/css/signin.css}" rel="stylesheet">
</head>
<body class="text-center">
<form class="form-signin" action="dashboard.html">
<img class="mb-4" th:src="@{/img/bootstrap-solid.svg}" alt="" width="72" height="72">
<h1 class="h3 mb-3 font-weight-normal" th:text="#{login.tip}">Please sign in</h1>
<label class="sr-only">Username</label>
<input type="text" class="form-control" th:text="#{login.username}" placeholder="Username..." required="" autofocus="">
<label class="sr-only">Password</label>
<input type="password" class="form-control" th:text="#{login.password}" placeholder="Password..." required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me" th:text="#{login.remember}"> Remeember me
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit" th:text="#{login.btn}">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2020-2021</p>
<a class="btn btn-sm">Chinese</a>
<a class="btn btn-sm">English</a>
</form>
</body>
</html>
Copy the code
Restart the project, visit the home page, found that it has been automatically identified as Chinese!But we want better! Can automatically switch between Chinese and English according to the button!
5. Configure internationalization parsing to switch between Chinese and English
There is an internationalized Locale in Spring; There’s a parser in there called LocaleResolver (Get locale information object)!
Think: what does HTML lang=”en” or HTML lang=” en-us “mean
The HTML lang attribute is used to declare the language type,,,,,
<html lang="en"></html>/ / English<html lang="zh-CN"></html>/ / Chinese<html lang="ja"></html>/ / Japanese<html lang="en-US"></html>// American English<div lang="en">this is English .</div>/ / EnglishCopy the code
The lang attribute, written in the HTML tag, declares the language type of the current page, which is instructive for search engines, web page translation, and screen reading browsers.
1. Add a link to switch labels in Both Chinese and English
The login page is displayed in Chinese, and we can see two tags in the index.html page
<a class="btn btn-sm">Chinese</a>
<a class="btn btn-sm">English</a>
Copy the code
That corresponds to the viewSo how do we switch between Chinese and English through these two tags?
First add jump links and parameters to the two tags
<! Don't use the passed parameter here? Use the key = value -- -- >
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">Chinese</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
Copy the code
2. Customize the locale parser component
How to implement our custom locale parser? Let’s start by analyzing a wave of source code
There are two classes for internationalization in Spring:
- Locale: indicates the region, each one
Locale
Objects represent a particular geographic, political, and cultural region - LocaleResolver: the locale parser
Start by searching WebMvcAutoConfiguration, where you can find localeResolver() about a method
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
public LocaleResolver localeResolver(a) {
// If the user is configured, the user is used
if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.mvcProperties.getLocale());
}
// If the user is not configured, use the default
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
return localeResolver;
}
Copy the code
This method is to get the LocaleResolver locale object parser:
- If the user is configured, the user configured locale parser is used.
- If not configured by the user, the default locale parser is used
We can see that the default locale parser isAcceptHeaderLocaleResolver
Object, we click into the class to view the sourceYou can see that it inherits the LocaleResolver interface and implements locale resolution
Therefore, to implement the above custom internationalization resources, we simply need to write our own locale parser, inherit the LocaleResolver interface, and override its methods.
We created MyLocaleResolver under the Config package as our internationalization locale parser
We wrote the corresponding request jump in index.html
-
If you click the Chinese button, you go to the /index.html(l=’zh_CN’) page
-
If you click the English button, you go to the /index.html(l=’en_US’) page
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}"< p style = "max-width: 100%; clear: both; min-height: 1emclass="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
Copy the code
So our custom locale parser, MyLocaleResolver, needs to handle these two link requests with parameters
package com.cy.config;
import org.springframework.web.servlet.LocaleResolver;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
public class MyLocaleResolver implements LocaleResolver {
// Parse the request
@Override
public Locale resolveLocale(HttpServletRequest request) {
// Get the internationalization parameters in the request
String language = request.getParameter("l");
// The default locale
Locale locale = Locale.getDefault();
// If the requested link parameter is not empty, it carries an internationalization parameter
if(! StringUtils.isEmpty(language)){/ / the split space
String[] split = language.split("_");
//zh_CN(language-region)
locale = new Locale(split[0], split[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {}}Copy the code
In order for our regionalization information to work, we need to configure this component again! Add beans under your MvcConofig configuration class;
// Custom internationalized components take effect
@Bean
public LocaleResolver localeResolver(a) {
return new MyLocaleResolver();
}
Copy the code
Let’s restart the project, visit, and find that clicking the button can achieve a successful switch!
Click the Chinese button to jump tohttp://localhost:8080/index.html?l=zh_CN, shown as Chinese
Click on theEnglish
Button to jump tohttp://localhost:8080/index.html?l=en_US, shows in English: