docs/Spring全家桶/SpringMVC/SpringMVC中的国际化功能.md
ڿӦóʱֶ֧Եֶ֧ԵĹ֮ܳΪʻӢinternationalizationдΪi18nΪĸiĩĸnм18ĸ
ضıػܣӢlocalizationдΪL10nػָݵڵʾȡ
ҲаߺϳΪȫӢglobalizationдΪg11n
JavaУֶ֧ԺͱػͨMessageFormat``Localeʵֵģ
WebӦóҪʵֹʻܣҪȾViewʱҪѸԵԴļͬûͬһҳʱʾԾDzͬġ
Spring MVCӦóʵֹʻ
ʵֹʻĵһǻȡûLocaleWebӦóУHTTP淶涨ЯAccept-Languageͷָʾû趨˳磺
Accept-Language: zh-CN,zh;q=0.8,en;q=0.2
HTTPͷʾѡģѡģѡӢġqʾȨأǿɻһȼбתΪJavaLocaleûLocaleֻͨȨߵLocale
Spring MVCͨLocaleResolverԶHttpServletRequestлȡLocaleжLocaleResolverʵ࣬õCookieLocaleResolver
@Primary
@Bean
LocaleResolver createLocaleResolver() {
var clr = new CookieLocaleResolver(); clr.setDefaultLocale(Locale.ENGLISH); clr.setDefaultTimeZone(TimeZone.getDefault()); return clr;}
CookieLocaleResolver``HttpServletRequestлȡLocaleʱȸһضCookieжǷָLocaleûУʹHTTPͷȡûУͷĬϵLocale
ûһηվʱCookieLocaleResolverֻܴHTTPͷȡLocaleʹĬԡͨվҲûԼѡԣʱCookieLocaleResolverͻûѡԴŵCookieУһηʱͻ᷵ûϴѡԶĬԡ
ڶǰдģеַԴļķʽ洢ⲿڶԣļΪmessagesôԴļ밴·ʽclasspathУ
messages.propertieszh_CNļΪmessages_zh_CN.propertiesja_JPļΪmessages_ja_JP.propertiesÿԴļͬkey磬ĬӢģļmessages.properties£
language.select=Language
home=Home
signin=Sign In
copyright=Copyright?{0,number,#}
ļmessages_zh_CN.properties£
language.select=
home=ҳ
signin=¼
copyright=Ȩ?{0,number,#}
ǴһSpringṩMessageSourceʵԶȡе.propertiesļṩһͳһӿʵ֡롱
// code, arguments, locale:
String text = messageSource.getMessage("signin", null, locale);
Уsignin``.propertiesļжkeyڶObject[]ΪʽʱIJһǻȡûLocaleʵ
MessageSource£
@Bean("i18n")
MessageSource createMessageSource() {
var messageSource = new ResourceBundleMessageSource(); // ָļUTF-8:
messageSource.setDefaultEncoding("UTF-8"); // ָļ:
messageSource.setBasename("messages"); return messageSource;}
עResourceBundleMessageSourceԶļԶԵԴļ
עSpringᴴֻһMessageSourceʵԼMessageSourceרŸҳʻʹõģΪi18n``MessageSourceʵͻ
ҪViewʹMessageSource``LocaleԣͨдһMvcInterceptorԴע뵽ModelAndViewУ
@Component
public class MvcInterceptor implements HandlerInterceptor {
@Autowired LocaleResolver localeResolver;
// עעMessageSourcei18n:
@Autowired @Qualifier("i18n") MessageSource messageSource;
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { if (modelAndView != null) { // ûLocale:
Locale locale = localeResolver.resolveLocale(request); // Model:
modelAndView.addObject("__messageSource__", messageSource); modelAndView.addObject("__locale__", locale); } }}
ҪWebMvcConfigurerעMvcInterceptorڣͿViewеMessageSource.getMessage()ʵֶԣ
{{ __messageSource__.getMessage('signin', null, __locale__) }}
дȻУʽ̫ˡʹViewʱҪÿضView涨ƹʻPebbleУǿԷװһʻƾ»_һ´ViewResolverĴ룺
@Bean
ViewResolver createViewResolver(@Autowired ServletContext servletContext, @Autowired @Qualifier("i18n") MessageSource messageSource) {
var engine = new PebbleEngine.Builder() .autoEscaping(true) .cacheActive(false) .loader(new Servlet5Loader(servletContext)) // չ:
.extension(createExtension(messageSource)) .build(); var viewResolver = new PebbleViewResolver(); viewResolver.setPrefix("/WEB-INF/templates/"); viewResolver.setSuffix(""); viewResolver.setPebbleEngine(engine); return viewResolver;}
private Extension createExtension(MessageSource messageSource) {
return new AbstractExtension() { @Override public Map<String, Function> getFunctions() { return Map.of("_", new Function() { public Object execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) { String key = (String) args.get("0"); List<Object> arguments = this.extractArguments(args); Locale locale = (Locale) context.getVariable("__locale__"); return messageSource.getMessage(key, arguments.toArray(), "???" + key + "???", locale); } private List<Object> extractArguments(Map<String, Object> args) { int i = 1; List<Object> arguments = new ArrayList<>(); while (args.containsKey(String.valueOf(i))) { Object param = args.get(String.valueOf(i)); arguments.add(param); i++; } return arguments; } public List<String> getArgumentNames() { return null; } }); } };}
ǿѶҳдΪ
{{ _('signin') }}
ǴĶԣҪѲȥ
<h5>{{ _('copyright', 2020) }}</h5>
ʹViewʱҲӦӿʵָ
ҪûֶлLocaleдһLocaleControllerʵָùܣ
@Controller
public class LocaleController {
final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired LocaleResolver localeResolver;
@GetMapping("/locale/{lo}") public String setLocale(@PathVariable("lo") String lo, HttpServletRequest request, HttpServletResponse response) { // ݴloLocaleʵ:
Locale locale = null; int pos = lo.indexOf('_'); if (pos > 0) { String lang = lo.substring(0, pos); String country = lo.substring(pos + 1); locale = new Locale(lang, country); } else { locale = new Locale(lo); } // 趨Locale:
localeResolver.setLocale(request, response, locale); logger.info("locale is set to {}.", locale); // ˢҳ:
String referer = request.getHeader("Referer"); return "redirect:" + (referer == null ? "/" : referer); }}
ҳУͨϽǸûṩһѡбЧ
лģ
֧ҪHTTPнûLocaleȻԲͬLocaleʾͬԣ
Spring MVCӦóͨMessageSource``LocaleResolverViewʵֹʻ