Статьи
YouTube-канал

Локализация текста в Spring Boot

Видеогайд Исходники

26 октября 2022

Тэги: gradle, Kotlin, rest, Spring Boot, руководство, файлы.

Содержание

  1. Подготовка файлов с ресурсами
  2. Конфигурация
  3. Контроллер
  4. Проверка
  5. Выводы

При разработке приложения, ориентированного на мировой рынок, сразу следует закладывать поддержку нескольких языков. Добавление новой локализации должно выполняться быстро и при этом не требовать значительного рефакторинга. К счастью, если вы разрабатываете приложение на Spring Boot, то реализовать такую поддержку довольно просто.

В качестве примера с помощью Spring Initializr создадим заготовку gradle-проекта на Kotlin и добавим всего 1 зависимость: spring-boot-starter-web. Наше приложение будет в зависимости от переданной локали возвращать текст на соответствующем языке.

Пример приложения также доступен на github.

Подготовка файлов с ресурсами

Суть локализации сводится к тому, что все тексты мы держим в отдельных property-файлах, а для каждого текстового фрагмента используем специальный код.

В проекте в папке resources создадим три файла. Первый назовём messages.properties. Это файл с локализацией по умолчанию, т.е. он будет использоваться, когда локаль не передана в явном виде.

text.welcome = Default welcome text

В данном случае мы сделали локализацию текста с кодом text.welcome.

Далее создадим локализацию для английского языка в файле messages_en.properties:

text.welcome = Hello, world!

Ну и, наконец, создадим локализацию для русского языка в файле messages_ru.properties:

text.welcome = Привет, мир!

Эта группа из трёх файлов называется Resource Bundle.

Важно! Чтобы у вас корректно обрабатывался текст с кириллицей, убедитесь, что этот property-файл имеет кодировку utf-8! Если это не так - настройте вашу IDE соответствующим образом. В IntelliJ Idea это настраивается в Settings - File Encodings - раздел Properties Files.

Конфигурация

Теперь создадим спринговую конфигурацию, которую назовём MessageConfig:

@Configuration
class MessageConfig {
    // ...
}

В этой конфигурации определим два бина.

@Bean
fun localeResolver(): LocaleResolver =
    with(SessionLocaleResolver()) {
        setDefaultLocale(Locale.US)
        this
    }

Бин localeResolver задаёт локаль, которая будет использоваться в том случае, если она не задана явно. В данном случае это Locale.US. Чтобы не создавать лишних переменных, для инициализации используем котлиновскую функцию with().

@Bean
fun messageSource(): ResourceBundleMessageSource =
    with(ResourceBundleMessageSource()) {
        setUseCodeAsDefaultMessage(true)
        setBasenames("messages")
        setDefaultEncoding("UTF-8")
        this
    }

Второй бин называется messageSource, типизированный классом ResourceBundleMessageSource. Он определяет источник локализаций для различных локалей, т.е. группу property-файлов, которые мы создали выше. Метод setUseCodeAsDefaultMessage() определяет, что, если по коду не удалось найти даже дефолтной реализации, то в качестве текста возвращать сам этот код, а не кидать исключение.

Метод setBasenames() устанавливает общий префикс имени всех файлов с локализациями. В нашем случае это «messages». Ну и в конце задаём кодировку файлов с помощью setDefaultEncoding().

Контроллер

Ну а теперь нам осталось создать простенький rest-контроллер с GET-методом, который будет возвращать текстовую строку в зависимости от локали, переданной этому методу в качестве параметра.

@RestController
@RequestMapping("/messages")
class MessageController(
    val messageSource: MessageSource,
) {
    // ...
}

Данный контроллер мы связываем с урлом /messages и подставляем в него компонент MessageSource, который и обеспечит нам функционал локализации.

Далее внутри контроллера определяем следующий GET-метод:

@GetMapping
fun getMessage(
    @RequestHeader(value = HttpHeaders.ACCEPT_LANGUAGE, required = false)
    locale: Locale? = null,
) = messageSource.getMessage(
    "text.welcome",
    null,
    locale ?: Locale.US
)

Единственным параметром тут является локаль, которая передаётся в HTTP-заголовке Accept-Language (аннотация @RequestHeader). Причём этот параметр является необязательным (required = false), а потому по умолчанию равен null.

Все имена стандартных заголовков содержатся в спринговом классе HttpHeaders.

В самом методе вызываем getMessage(), в который передаём код текста (text.welcome) и локаль. Причём если локаль не передали, будем подставлять Locale.US благодаря элвис-оператору.

Проверка

Теперь запускаем приложение и выполяем GET-запрос на эндпоинт /messages. Если мы не передаём заголовок Accept-Language, то в ответе увидим строку на английском.

curl http://127.0.0.1:8080/messages
Hello, world!

Если же в этом заголовке передать значение «ru», то увидим текст на русском.

curl http://127.0.0.1:8080/messages -H "Accept-Language: ru"
Привет, мир!

Таким образом, вы можете добавлять сколько угодно локализаций. Просто создайте новый property-файл с названием нужной вам локали.

Выводы

Благодаря этому простому примеру мы убедились, что создать мультиязычное приложение на Spring Boot не составляет труда. Локализация сводится к добавлению нужного текстового файла без изменения кода. Всю работу с локалями берёт на себя компонент MessageSource.

Напоследок хочу заметить, что, в зависимости от требований, локаль может определяться не параметром запроса (как в нашем случае), а настройками самого сервера.


Облако тэгов

Kotlin, Java, Java 16, Java 11, Java 10, Java 9, Java 8, Spring, Spring Boot, Spring Data, SQL, PostgreSQL, Oracle, Linux, Hibernate, Collections, Stream API, многопоточность, файлы, Nginx, Apache, maven, gradle, JUnit, YouTube, новости, руководство, ООП, алгоритмы, головоломки, rest, GraphQL, Excel, XML, json, yaml.

Последние статьи


Комментарии

Добавить комментарий

×

devmark.ru