国际化也称作i18n,其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数。由于软件面向的是全球不同国家的各个用户,所以软件是否可以显示不同的语言,就变得非常重要。而软件显示不同的语言的过程,就成为国际化。(我们浏览的网页一般都会有多个语言版本,如下图:)
通常来讲:软件的国际化是通过配置文件来实现的。
那我们就可以将国际化分为以下三步:
在resource文件夹下创建i18n文件夹,在i18n文件夹下创建相关的配置文件。
注意配置文件的命名规范,一定要以basename_language_country.properties
的格式,java才会识别。
其中,basename是必须的,语言和国家是可选的。这里存在一个优先级概念,如果同时提供了messages.properties和messages_zh_CN.propertes两个配置文件,如果提供的locale符合en_CN,那么优先查找messages_en_CN.propertes配置文件,如果没查找到,再查找messages.properties配置文件。最后,提示下,所有的配置文件必须放在classpath中,一般放在resource目录下。
一种语言对应一个配置文件,下图所示是IDEA的可视化方式。对应的配置文件:
login.btn=登录
login.password=密码
login.remember=记住密码
login.tip=请登录
login.username=用户名
spring提供了ResourceBundleCondition这个类来确定配置文件的位置
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
String basename = context.getEnvironment().getProperty("spring.messages.basename", "messages");
ConditionOutcome outcome = (ConditionOutcome)cache.get(basename);
if (outcome == null) {
outcome = this.getMatchOutcomeForBasename(context, basename);
cache.put(basename, outcome);
}
return outcome;
}
可以看出要想指定配置文件的位置,只需要将spring.messages.basename
的值覆盖即可。
所以在application.properties
配置文件中添加spring.messages.basename=i18n.login
就可查找到配置文件。
spring中org.springframework.web.servlet.LocaleResolver
接口用于实现国际化。
public interface LocaleResolver {
Locale resolveLocale(HttpServletRequest var1);
void setLocale(HttpServletRequest var1, @Nullable HttpServletResponse var2, @Nullable Locale var3);
}
那我们可以定义自己的类,重写resolveLocale
方法,spring也有自己默认的处理方法。在org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver
中。
public Locale resolveLocale(HttpServletRequest request) {
Locale defaultLocale = this.getDefaultLocale();
if (defaultLocale != null && request.getHeader("Accept-Language") == null) {
return defaultLocale;
} else {
Locale requestLocale = request.getLocale();
List<Locale> supportedLocales = this.getSupportedLocales();
if (!supportedLocales.isEmpty() && !supportedLocales.contains(requestLocale)) {
Locale supportedLocale = this.findSupportedLocale(request, supportedLocales);
if (supportedLocale != null) {
return supportedLocale;
} else {
return defaultLocale != null ? defaultLocale : requestLocale;
}
} else {
return requestLocale;
}
}
}
我们可以仿照spring给定的i18n写自己的国际化方法。
public class MyLocaleResolver implements LocaleResolver {
@Override
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
// 获取请求域中的语言参数
String lanuage = httpServletRequest.getParameter("l");
// 获取默认的语言参数
Locale locale = Locale.getDefault();
if(!StringUtils.isEmpty(lanuage)){ //如果请求域从的语言参数不为空
// zh_CN
String []split = lanuage.split("_");
locale = new Locale(split[0],split[1]);
}
return locale;
}
再通过前端发送请求。
<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>
<input type="text" class="form-control" th:placeholder="#{login.username}" required="" autofocus="">
<input type="password" class="form-control" th:placeholder="#{login.password}" required="">
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> [[ #{login.remember} ]]
</label>
</div>
<button class="btn btn-lg btn-primary btn-block" type="submit">[[ #{login.btn} ]]
<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
<a class="btn btn-sm" th:href="@{/index.html(l='zh_CN')}">中文</a>
<a class="btn btn-sm" th:href="@{/index.html(l='en_US')}">English</a>
</form>
</body>
将自己的MyLocaleResolver组件添加到spring容器中。
@Bean
public LocaleResolver localeResolver(){
return new MyLocaleResolver();
}