Spring REST Change Roulette Language

I am trying to handle a locale change in a Spring 3 REST application.

But the locale does not change to fr.

The console log displays: 2014-05-19 14: 29: 46.214 DEBUG [AbstractExceptionHandler] =========== β†’ locale: ru

Here is my configuration:

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasenames("classpath:messages/messages", "classpath:messages/validation");
        // If true, the key of the message will be displayed if the key is not found, instead of throwing an exception
        messageSource.setUseCodeAsDefaultMessage(true);
        messageSource.setDefaultEncoding("UTF-8");
        // The value 0 means always reload the messages to be developer friendly
        messageSource.setCacheSeconds(0);
        return messageSource;
    }

    // The locale interceptor provides a way to switch the language in any page just by passing the lang=’en’, lang=’fr’, and so on to the url
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
        localeChangeInterceptor.setParamName("lang");
        registry.addInterceptor(localeChangeInterceptor);
    }

    @Bean
    public LocaleResolver localeResolver() {
//      AcceptHeaderLocaleResolver localeResolver = new AcceptHeaderLocaleResolver();
        CookieLocaleResolver localeResolver = new CookieLocaleResolver();
        localeResolver.setDefaultLocale(new Locale("en"));
//        SessionLocaleResolver localeResolver = new SessionLocaleResolver();
//        localeResolver.setDefaultLocale(StringUtils.parseLocaleString("en"));
        return localeResolver;
    }

Here is my exception handler:

@ControllerAdvice
public class AdminExceptionHandler extends AbstractExceptionHandler {

    @ExceptionHandler(NullPointerException.class)
    @ResponseBody
    public ResponseEntity<ErrorInfo> nullPointerException(HttpServletRequest request, NullPointerException e) {
        String url = request.getRequestURL().toString();
        String errorMessage = localizeErrorMessage("error.npe", new Object[] { e.getMessage() });
        return new ResponseEntity<ErrorInfo>(new ErrorInfo(url, errorMessage), HttpStatus.INTERNAL_SERVER_ERROR);
    }

}

public class AbstractExceptionHandler {

    private static Logger logger = LoggerFactory.getLogger(AbstractExceptionHandler.class);

    @Autowired
    private MessageSource messageSource;

    protected String localizeErrorMessage(String errorCode, Object args[]) {
        Locale locale = LocaleContextHolder.getLocale();
        logger.debug("===========>> locale: " + locale);
        return messageSource.getMessage(errorCode, args, locale);
    }

    protected String localizeErrorMessage(String errorCode) {
        return localizeErrorMessage(errorCode, null);
    }

    protected String extractAdminIdFromUrl(String url) {
        String adminId = null;
        try {
            URI uri = new URI(url);
            String path = uri.getPath();
            adminId = path.substring(path.lastIndexOf('/') + 1);
        } catch (URISyntaxException e1) {
            e1.printStackTrace();
        }
        return adminId;
    }

}

And here is my test:

@Test
public void testExceptionLocalizedMessage() throws Exception {
    HttpHeaders httpHeaders = Common.createAuthenticationHeaders("stephane" + ":" + PASSWORD);

    MvcResult resultGet = this.mockMvc.perform(
            get("/error/npe").headers(httpHeaders)
            .param("lang", "fr")
            .accept(MediaType.APPLICATION_JSON)
        )
        .andExpect(status().isInternalServerError())
        .andExpect(jsonPath("$.message").value("Une erreur inconnue s'est produite. Veuillez nous excuser."))
        .andReturn();

    httpHeaders.add("Accept-Language", "fr");
    resultGet = this.mockMvc.perform(
            get("/error/npe").headers(httpHeaders)
            .accept(MediaType.APPLICATION_JSON)
        )
        .andExpect(status().isInternalServerError())
        .andExpect(jsonPath("$.message").value("Une erreur inconnue s'est produite. Veuillez nous excuser."))
        .andReturn();
}

I would like to process the locale argument in url, as in? lang = en and the Accept-Language header as a rollback.

As a REST application, I thought about using the AcceptHeaderLocaleResolver class, but it does not support setting the language using the url parameter.

I considered using the SessionLocaleResolver class to make little sense in a REST application.

This leaves my CookieLocaleResolver class, which I am not particularly convinced of, which should be used in a REST application.

, en fr, .

EDIT:

, :

httpHeaders.add("Accept-Language", Locale.FRENCH.getLanguage());

. locale() . :

this.mockMvc.perform(
        get("/error/npe").headers(httpHeaders).locale(Locale.FRENCH)
        .accept(MediaType.APPLICATION_JSON))
        .andDo(print()
    )
    .andExpect(status().isInternalServerError())
    .andExpect(jsonPath("$.message").value(localizeErrorMessage("error.npe", Locale.FRENCH)))
    .andReturn();
+4
1

. Accept-Language cookie.

public class WebConfiguration extends WebMvcConfigurerAdapter {

    @Bean
    public LocaleResolver localeResolver() {
        return new SmartLocaleResolver();
    }

}

public class SmartLocaleResolver extends CookieLocaleResolver {

    @Override
    public Locale resolveLocale(HttpServletRequest request) {
        String acceptLanguage = request.getHeader("Accept-Language");
        if (acceptLanguage == null || acceptLanguage.trim().isEmpty()) {
            return super.determineDefaultLocale(request);
        }
        return request.getLocale();
    }

}

UPDATE: Thor, , cookie, :

@Override
public Locale resolveLocale(HttpServletRequest request) {
    Locale locale = super.determineDefaultLocale(request);
    if (null == locale) {
        String acceptLanguage = request.getHeader("Accept-Language");
        if (acceptLanguage != null && !acceptLanguage.trim().isEmpty()) {
            locale = request.getLocale();
        }
    }
    return locale;
}

( ):

private AcceptHeaderLocaleResolver acceptHeaderLocaleResolver = new AcceptHeaderLocaleResolver();

@Override
public Locale resolveLocale(HttpServletRequest request) {
    Locale locale = super.determineDefaultLocale(request);
    if (null == locale) {
        locale = acceptHeaderLocaleResolver.resolveLocale(request);
    }
    return locale;
}

UPDATE: .

:

httpHeaders.add(HttpHeaders.ACCEPT_LANGUAGE, "fr_FR");

:

@Override
public Locale resolveLocale(HttpServletRequest request) {
    for (String httpHeaderName : Collections.list(request.getHeaderNames())) {
        logger.debug("===========>> Header name: " + httpHeaderName);
    }
    String acceptLanguage = request.getHeader(HttpHeaders.ACCEPT_LANGUAGE);
    logger.debug("===========>> acceptLanguage: " + acceptLanguage);
    Locale locale = super.resolveLocale(request);
    logger.debug("===========>> acceptLanguage locale: " + locale.getDisplayCountry());
    if (null == locale) {
        locale = getDefaultLocale();
        logger.debug("===========>> Default locale: " + locale.getDisplayCountry());
    }
    return locale;
}

===========>> Header name Accept-Language, logger acceptLanguage .

+5

Source: https://habr.com/ru/post/1541122/


All Articles