Spring MVC — локализация (выбор языка)
Internationalization (i18n). — включение в приложении поддержки разных языков (закладывается при проектировании). Кстати цифра в (i18n) означает количество символов между буквами I и n
Localization (l10n) — реализация в коде.
Для начала нужно создать файлы .properties где будут находится «ключ»-«значение» на разных языках. Как создать файлы локализации на разных языках в Intelij IDEA?
Для того чтобы создать в Intellij IDEA Resource Bundle с несколькими файлами на разных языках, нужно в директории (например, ‘locale’) нажать правой кнопкой>new>file. Далее создать первый файл — «имя.properties» и второй «имя_ru.properties» («имя_en.properties» и т.д.). После чего все файлы объединятся в специальную «Resource Bundle ‘имяФайла’ « папку. Чтобы добавлять значения было удобнее, можно нажать на папку правой кнопкой и выбрать «Jump to Source». Создав property вы увидите несколько полей для добавления значений на разных языках.
Здесь созданы два набора локалей — один для смены текста на страницах, а второй для отображения ошибок при валидации (например при вводе пустого пароля).
Далее необходимо прописать бины в нашем dispatcher-servlet.xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<mvc:interceptors> <mvc:interceptor> <mvc:mapping path="/*" /> <ref bean="localeChangeInterceptor" /> </mvc:interceptor> </mvc:interceptors> //далее используется в @Autowired в контроллере <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basename" value="/WEB-INF/locales/messages" /> <property name="defaultEncoding" value="UTF-8" /> </bean> <bean id="localeChangeInterceptor" class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor"> <property name="paramName" value="lang" /> </bean> <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver"> <property name="defaultLocale" value="ru" /> </bean> |
Объявляем перехватчика "localeChangeInterceptor" (Он задан дальше в бине). А так же бин localeResolver, который указывает на класс SessionLocaleResolver. (локаль определяет не только язык, но и другие параметры, например как отображается дата в разных странах и этот класс помогает избавиться от многих хлопот).
После этого можем перейти к реализации контроллера.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.MessageSource; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.ModelAndView; import ru.javastudy.springmvc.objects.User; import javax.validation.Valid; import java.util.Locale; @Controller public class MainController { @Autowired private MessageSource messageSource; @RequestMapping(value = "/*", method = RequestMethod.GET) public String main(@ModelAttribute User user, Locale locale) { //ниже строчки для понимания что выводится в консоль и как работает смена локали. /* System.out.println(locale.getDisplayLanguage()); System.out.println(messageSource.getMessage("locale", new String[]{locale.getDisplayName(locale)}, locale)); user.setName("Nikolay"); //заполняет поле имя "name" в index.jsp */ return "index"; } @RequestMapping(value = "/check-user*", method = RequestMethod.POST) public ModelAndView checkUser(Locale locale, @Valid @ModelAttribute("user") User user, BindingResult bindingResult) {// !!!BindingResult должен быть следующим после проверяемого значения!! ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("locale", messageSource.getMessage("locale", new String[]{locale.getDisplayName(locale)}, locale)); //если не проходит валидацию @Valid. if (bindingResult.hasErrors()) { modelAndView.setViewName("index"); } else { modelAndView.setViewName("main"); } return modelAndView; } } |
Листинг класса User. Ещё раз обратите внимание, что при проверке @Size в сообщение используется уже другой набор из ValidationMessages.properties (см. скришот выше)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
import javax.validation.constraints.Size; public class User { public User() { // TODO Auto-generated constructor stub } public User(String name) { super(); this.name = name; } @Size(min = 6, message = "{name.size.error}") //Отдельный bundle ValidationMessages.properties! // Имя должно быть больше 6 знаков private String name; @Size(min = 5, max = 10, message = "{password.size.error}") private String password; private boolean admin; public boolean isAdmin() { return admin; } public void setAdmin(boolean admin) { this.admin = admin; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } |
Так выглядит тестовая форма.
Созданы два поля и кнопка. form:input path="name", "password" связаны с User.class. При нажатии на кнопку выполняется action="check-user" и направляется в контроллер, где дальше идет проверка какую страницу вызвать index.jsp или main.jsp.
И теперь два представления .jsp:
«index.jsp»
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<body> <form:form method="POST" modelAttribute="user" action="check-user" class="box login"> <fieldset class="boxBody"> <span style="float: right"> <a href="?lang=en">en</a> <a href="?lang=ru">ru</a> </span> <form:label path="name"> <spring:message code="username" /> </form:label> <form:input path="name" /> <form:errors path="name" cssClass="error" /> <form:label path="password"> <spring:message code="password" /> </form:label> <form:password path="password" /> <form:errors path="password" cssClass="error" /> </fieldset> <footer> <input type="submit" class="btnLogin" value="<spring:message code="login"/>"> </footer> </form:form> </body> |
и «main.jsp»
1 2 3 4 5 6 |
<body> <p>Hello ${user.name}!</p> <p>Your password is ${user.password}!</p> <p>Admin ${user.admin}!</p> <p>Locale ${locale}!</p> //берется из метода checkUser() в контроллере </body> |
Может быть интересно
На сайте добавлена еще одна статья по интернационализации — Локализация Java Spring MVC приложения. Настройка поддержки нескольких языков.
Исходные коды Spring MVC localization example:
SpringMVC_localization — javastudy.ru
11