JavaRush /Курси /Модуль 5. Spring /Локалізація повідомлень про помилки

Локалізація повідомлень про помилки

Модуль 5. Spring
Рівень 8 , Лекція 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. Підключення бібліотеки

Для початку переконайся, що в тебе підключені залежності web і валідації в 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-додаток розуміє різні мови. Це додає професіоналізму і робить систему дружньою до користувача! Вітаю — ти офіційно впорався з локалізацією.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ