在springmvc中实现国际化的步骤
1、编写国际化配置文件,我们将要显示的内容都配置出来;
2、使用resourcebundlemessagesource来管理国际化资源文件;
3、如果是以前的jsp页面,可以使用fmt:message来取出国际化的内容;
springboot的配置
抽取页面需要显示的国际化消息;
示例:在登录页面进行国际化的配置;
login.properities
login.tip=请登录~
login.username=用户名~
login_en_US.properities
源码分析
org\springframework\boot\autoconfigure\web\servlet\WebMvcAutoConfiguration.java
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "spring.mvc", name = "locale")
public LocaleResolver localeResolver() {
if (this.mvcProperties.getLocaleResolver() == WebMvcProperties.LocaleResolver.FIXED) {
return new FixedLocaleResolver(this.mvcProperties.getLocale());
}
AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
localeResolver.setDefaultLocale(this.mvcProperties.getLocale());
return localeResolver;
}
WebMvcAutoConfiguration.java中自动装配了国际化的配置代码;它的配置是获取到springmvc中的国际化配置;
spring.messages.basename=i18n.login
org\springframework\boot\autoconfigure\context\MessageSourceAutoConfiguration.java
MessageSourceAutoConfiguration.java中配置了基础的文件名,=>login,而不是login_en_US或login_zh_CN,前边是语言,后边是国家名字;
源码如下:
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";
@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() {
return new MessageSourceProperties();
}
@Bean
public MessageSource messageSource(MessageSourceProperties properties) {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
if (StringUtils.hasText(properties.getBasename())) {
messageSource.setBasenames(StringUtils
.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;
}
这就是springboot的国际化源码;
前端页面配置
<form class="form-signin" action="dashboard.html">
<img class="mb-4" th:src="@{/asserts/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" th:text="#{login.username}">Username</label>
<input type="text" class="form-control" placeholder="Username" required="" autofocus="">
<label class="sr-only">Password</label>
<input type="password" class="form-control" placeholder="Password" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> Remember me
<!-- 行内表达式[[#{login.remember}]] -->
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
<a class="btn btn-sm" th:href="@{/index.html(l='cn_ZH')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
</form>
我们在国际化配置文件夹i18n中配置了属性文件,此时在前端页面中可以调用 th:text="#{login.username}" th:text="#{login.tip}"等;
此时国际化配置完成了一半,但是需要根据浏览器的请求头Accpet-Language的语言进行页面的回显,和我们的程序没有关系。在浏览器设置中切换需要显示的语言置顶即可。
我们下边需要手动对页面语言进行自定义切换。 th:href="@{/index.html(l='cn_ZH')}"切换为中文,
th:href="@{/index.html(l='en_US')}"切换为英文;
为了让这个链接生效;我们需要自定义一个国家化语言的解析器
package com.pshdhx.component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.LocaleResolver;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;
/**
* @Authtor pshdhx
* @Date 2020/11/2912:25
* @Version 1.0
* 根据用户点击信息进行国际化语言的切换。
*/
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
String l = httpServletRequest.getParameter("l");
Locale locale = Locale.getDefault();
if(!StringUtils.isEmpty(l)){
String[] s = l.split("_");
locale = new Locale(s[0],s[1]);
}
return locale;
}
@Override
public void setLocale(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Locale locale) {
}
}
MyMvcConfiguration.java,我们配置了国际化语言解析器,还需要让其生效,即在容器中加入@Bean即可。
package com.pshdhx.config;
import com.pshdhx.component.MyLocaleResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
/**
* @Authtor pshdhx
* @Date 2020/11/2818:48
* @Version 1.0
*/
@Configuration
//@EnableWebMvc
public class MyMvcConfiguration extends WebMvcConfigurerAdapter {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
//浏览器发送com.pshdhx请求,也来到success页面。
registry.addViewController("/pshdhx").setViewName("success");
}
/**
* 所有的webmvcadapter组件都会一起起作用,前提是springboot知道我们自定义组件的存在
*/
@Bean//将我们的组件注册到容器中
public WebMvcConfigurerAdapter webMvcConfigurerAdapter(){
return new WebMvcConfigurerAdapter(){
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("login");
registry.addViewController("/index.html").setViewName("login");
}
};
}
/**
* 添加localeResolver到容器中
*/
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}
}
重启服务器,即可进行页面语言的切换。
在此过程中遇到的问题:
进行语言切换的时候,前端页面乱码
需要在IDEA中进行如下配置
如果遇到了
Error:(1, 1) java: 非法字符: '\ufeff' 这样坑的问题,那么需要定位到java类进行
单击右键,removeBOM的操作即可。
ok,到此国际化全部结束。