Статьи Утилиты Telegram YouTube RuTube Отзывы

Локализация текста в 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 это настраивается в SettingsFile 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.

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


См. также


Комментарии

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

×

devmark.ru