JavaRush /Курсы /Модуль 5. Spring /Локализация сообщений об ошибках

Локализация сообщений об ошибках

Модуль 5. Spring
9 уровень , 8 лекция
Открыта

Локализация в IT — это как переводчик на конференции: пользователи говорят на разных языках, а система должна отвечать им понятно. Представьте, что вы разрабатываете приложение, которое выходит на мировой рынок. Для пользователей из разных стран важно, чтобы интерфейс, ошибки и уведомления были адаптированы под их язык и культурные особенности.

Что локализуем?

  1. Сообщения об ошибках: например, вместо сухого must not be null, пользователь из России должен видеть: Поле не может быть пустым.
  2. Валидационные сообщения: когда форма заполнена неверно, текст предупреждений тоже должен быть на языке пользователя.
  3. Другие уведомления: информация о некорректном вводе дат, чисел, email-ов и т.д.

Как работает локализация в Spring?

Spring предоставляет мощный инструмент для локализации — MessageSource. Это компонент, который отвечает за работу с текстами и поддерживает множественные языковые файлы.

Компоненты локализации

  1. Языковые файлы: это обычные .properties файлы с ключами и их значениями, например:
    • messages_en.properties для английского.
    • messages_ru.properties для русского.
  2. MessageSource: Bean, который ищет нужный файл в зависимости от текущей локали.
  3. LocaleResolver: определяет, какая локаль активна для текущего пользователя.

Настройка локализации в Spring-приложении

1. Подключение библиотеки

Для начала убедитесь, что у вас подключены зависимости веб и валидации в pom.xml:


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>

2. Добавляем языковые файлы

Создайте в папке src/main/resources файлы:

  • messages_en.properties:
    
    field.required=Field is required
    field.length=Field must not exceed {0} characters
    
  • messages_ru.properties:
    
    field.required=Поле обязательно для заполнения
    field.length=Поле не должно превышать {0} символов
    

Эти файлы содержат ключи и переводы. Ключи — это уникальные идентификаторы сообщений, а значения — тексты на соответствующем языке.

3. Конфигурация MessageSource

В Spring Boot MessageSource настраивается через Bean в конфигурационном классе. Добавляем следующий код:


import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;

@Configuration
public class LocalizationConfig {

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
        messageSource.setBasename("classpath:messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }
}

Это говорит Spring искать файлы messages_*.properties в папке ресурсов.

4. Настройка LocaleResolver

Добавляем LocaleResolver, чтобы определить язык пользователя. Например, можно использовать Cookie для хранения выбора языка:


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.LocaleResolver;
import org.springframework.web.servlet.i18n.CookieLocaleResolver;

import java.util.Locale;

@Configuration
public class LocaleConfig {

    @Bean
    public LocaleResolver localeResolver() {
        CookieLocaleResolver localeResolver = new CookieLocaleResolver();
        localeResolver.setDefaultLocale(Locale.ENGLISH); // Язык по умолчанию
        return localeResolver;
    }
}

5. Переключение локали через контроллер

Теперь создадим контроллер, чтобы пользователи могли менять язык. Например, через параметр lang:


import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.LocaleResolver;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Locale;

@RestController
public class LanguageController {

    private final LocaleResolver localeResolver;

    public LanguageController(LocaleResolver localeResolver) {
        this.localeResolver = localeResolver;
    }

    @GetMapping("/change-language")
    public String changeLanguage(@RequestParam String lang, HttpServletRequest request, HttpServletResponse response) {
        Locale locale = new Locale(lang);
        localeResolver.setLocale(request, response, locale);
        return "Language changed to " + lang;
    }
}

Теперь запросы вида /change-language?lang=ru будут переключать язык.


Локализация сообщений об ошибках

Локализуем сообщения от Bean Validation API.

1. Аннотируем поля DTO

Наш UserDTO может выглядеть так:


import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public class UserDTO {

    @NotNull(message = "{field.required}")
    private String username;

    @Size(max = 20, message = "{field.length}")
    private String password;

    // Геттеры и сеттеры
}

Ключи сообщений об ошибках (field.required и field.length) берутся из языковых файлов.

2. Пример обработки в контроллере

Создадим REST контроллер, который обрабатывает POST-запрос для регистрации.


import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;

@RestController
@RequestMapping("/users")
public class UserController {

    @PostMapping
    public String createUser(@RequestBody @Valid UserDTO userDTO) {
        return "User created: " + userDTO.getUsername();
    }
}

Spring автоматом валидирует запросы, а при ошибке выбрасывает исключение MethodArgumentNotValidException.


Локализация ошибок через GlobalExceptionHandler

Прошлые лекции научили нас использовать @ControllerAdvice для глобальной обработки ошибок. Локализуем ошибки для пользователей:


import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

@ControllerAdvice
public class GlobalExceptionHandler {

    private final MessageSource messageSource;

    public GlobalExceptionHandler(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationExceptions(MethodArgumentNotValidException ex, Locale locale) {
        Map<String, String> errors = new HashMap<>();
        for (FieldError error : ex.getBindingResult().getFieldErrors()) {
            String localizedErrorMessage = messageSource.getMessage(error, locale);
            errors.put(error.getField(), localizedErrorMessage);
        }
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(errors);
    }
}

Теперь сообщения об ошибках будут возвращаться в зависимости от текущей локали пользователя!


Пример запроса

Тело запроса


{
  "username": null,
  "password": "password_that_is_too_long_for_the_application_rules"
}

Ответ при локали en


{
  "username": "Field is required",
  "password": "Field must not exceed 20 characters"
}

Ответ при локали ru


{
  "username": "Поле обязательно для заполнения",
  "password": "Поле не должно превышать 20 символов"
}

Теперь ваш Spring-приложение понимает разные языки. Это добавляет профессионализма и делает систему дружественной к пользователю! Вы официально справились с локализацией.

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ