I have a spring application that I want users to be able to change their preferred language. Currently, users can change the locale for the current session, but I want to be able to save the user parameter so that every time I log in, the saved locale is used if it exists. I have a mysql database that I use to maintain user locale preference. I created a custom AuthenticationSuccessHandler to handle locale changes in a saved locale that works for a user where I already saved the locale in the database. However, a bit that I do not know how to do is to save the locale when changing the parameter. The code is as follows:
@Bean public LocaleResolver localeResolver() { SessionLocaleResolver slr = new SessionLocaleResolver(); slr.setDefaultLocale(Locale.getDefault()); logger.debug("Setting locale to: " + Locale.getDefault()); return slr; } @Bean public LocaleChangeInterceptor localeChangeInterceptor() { LocaleChangeInterceptor lci = new LocaleChangeInterceptor(); lci.setParamName("lang"); logger.debug("localeChangeInterceptor called " + Locale.getDefault()); return lci; }
SecurityConfig Class:
@Configuration("SecurityConfig") @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled=true) class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired @Qualifier("CustomAuthenticationSuccessHandler") private CustomAuthenticationSuccessHandler authenticationSuccessHandler; @Override protected void configure(HttpSecurity http) throws Exception { CharacterEncodingFilter filter = new CharacterEncodingFilter(); filter.setEncoding(StandardCharsets.UTF_8.name()); filter.setForceEncoding(true); http.addFilterBefore(filter,CsrfFilter.class); // configure authentication providers http.authenticationProvider( customAuthenticationProvider() ); http.authenticationProvider( authenticationProvider() ); http.authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/?lang=**").permitAll() .antMatchers("/login**").permitAll() .antMatchers("/about**").permitAll() .antMatchers("/index.html").permitAll() .antMatchers("/css/**").permitAll() .antMatchers("/js/**").permitAll() .antMatchers("/img/**").permitAll() .antMatchers("/fonts/**").permitAll() .antMatchers("/errors/**").permitAll() .antMatchers("/error/**").permitAll() .antMatchers("/webjars/**").permitAll() .antMatchers("/static/**").permitAll() .antMatchers("/information/**").permitAll() .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')") .anyRequest().authenticated() .and() .formLogin() .loginPage("/login") .defaultSuccessUrl("/home") .failureUrl("/login?failedlogin=true") .usernameParameter("username").passwordParameter("password") .successHandler(authenticationSuccessHandler) .failureHandler(authenticationFailureHandler) .permitAll() .and() .logout() .deleteCookies("JSESSIONID") .addLogoutHandler(getCustomLogoutSuccessHandler()) .invalidateHttpSession(true) .permitAll() .and() .csrf().disable() .exceptionHandling() .and() .rememberMe().rememberMeParameter("remember-me").tokenRepository(tokenRepository) .tokenValiditySeconds(86400) ; } .... }
Authentication ClassSuccessHandler
@Component("CustomAuthenticationSuccessHandler") public class CustomAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler { private static final Logger logger = LogManager.getLogger(CustomAuthenticationSuccessHandler.class); @Autowired private LocaleResolver localeResolver; @Autowired @Qualifier("UserService") private UserService userService; @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { logger.debug("CustomAuthenticationSuccessHandler.onAuthenticationSuccess called"); setLocale(authentication, request, response); super.onAuthenticationSuccess(request, response, authentication); } protected void setLocale(Authentication authentication, HttpServletRequest request, HttpServletResponse response) { logger.debug("CustomAuthenticationSuccessHandler.setLocale called"); if (authentication != null &&authentication.getPrincipal() != null) { String username = (String) authentication.getPrincipal(); if (username != null) { String localeOption = userService.getUsersPreferedLocaleOption(username); logger.debug("localeOption " + localeOption); if (localeOption != null && !localeOption.isEmpty()) { Locale userLocale = Locale.forLanguageTag(localeOption); localeResolver.setLocale(request, response, userLocale); } } } } }
The part of the html page that shows the options for changing the language:
<form id="change-language-form" name="change-language-form" class="change-language-form ng-pristine ng-valid" method="POST"> <div class="row"> <div class="text-right col-sm-offset-8 col-sm-4"> <select id="language-selector" name="language-selector" class="language-selector"> <option value="">Language </option> <option value="?lang=en_GB">English </option> <option value="?lang=zh">中文 </option> <option value="?lang=de_DE">Deutsch </option> <option value="?lang=es_ES">Español </option> <option value="?lang=fr_FR">Français </option> </select> </div> </div> <div class="row"> <div class="spacer-sml"></div> </div> </form>
Javascript that changes the language parameter:
$('#language-selector').change(function() { var languageSelectedUrl = $(this).find("option:selected").val(); if (languageSelectedUrl) { window.location = languageSelectedUrl; } });
java spring-mvc
karen
source share