«1. Введение

В этом уроке мы узнаем, как форматировать валюты по локали с помощью Thymeleaf.

2. Зависимости Maven

Давайте начнем с импорта зависимости Spring Boot Thymeleaf:

<dependency>
    <groupId>org.springframework.boot</groupId> 
    <artifactId>spring-boot-starter-thymeleaf</artifactId> 
    <version>2.2.7.RELEASE</version>
</dependency>

3. Настройка проекта

Наш проект будет простым веб-приложением Spring, которое отображает валюты в зависимости от локали пользователя. . Давайте создадим наш шаблон Thymeleaf, currency.html, в resources/templates/currencies:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:th="http://www.thymeleaf.org">
    <head>
        <meta charset="UTF-8">
        <title>Currency table</title>
    </head>
</html>

Мы также можем создать класс контроллера, который будет обрабатывать наши запросы:

@Controller
public class CurrenciesController {
    @GetMapping(value = "/currency")
    public String exchange(
      @RequestParam(value = "amount") String amount, Locale locale) {
        return "currencies/currencies";
    }
}

4. Форматирование

Когда касается валют, нам нужно отформатировать их в зависимости от локали запрашивающей стороны.

В этом случае мы будем отправлять заголовок Accept-Language с каждым запросом, чтобы представить локаль нашего пользователя.

4.1. Валюта

Класс Numbers, предоставляемый Thymeleaf, поддерживает форматирование валют. Итак, давайте обновим наше представление, вызвав метод formatCurrency

<p th:text="${#numbers.formatCurrency(param.amount)}"></p>

Когда мы запустим наш пример, мы увидим правильно отформатированную валюту:

@Test
public void whenCallCurrencyWithUSALocale_ThenReturnProperCurrency() throws Exception {
    mockMvc.perform(MockMvcRequestBuilders.get("/currency")
      .header("Accept-Language", "en-US")
      .param("amount", "10032.5"))
      .andExpect(status().isOk())
      .andExpect(content().string(containsString("$10,032.50")));
}

США, валюта отформатирована с десятичной точкой и знаком доллара.

4.2. Денежные массивы

Мы также можем использовать класс Numbers для форматирования массивов. В результате мы добавим еще один параметр запроса в наш контроллер:

@GetMapping(value = "/currency")
public String exchange(
  @RequestParam(value = "amount") String amount,
  @RequestParam(value = "amountList") List amountList, Locale locale) {
    return "currencies/currencies";
}

Далее мы можем обновить наше представление, включив в него вызов метода listFormatCurrency:

<p th:text="${#numbers.listFormatCurrency(param.amountList)}"></p>

Теперь давайте посмотрим, как выглядит результат например:

@Test
public void whenCallCurrencyWithUkLocaleWithArrays_ThenReturnLocaleCurrencies() throws Exception {
    mockMvc.perform(MockMvcRequestBuilders.get("/currency")
      .header("Accept-Language", "en-GB")
      .param("amountList", "10", "20", "30"))
      .andExpect(status().isOk())
      .andExpect(content().string(containsString("£10.00, £20.00, £30.00")));
}

Результат показывает список валют с добавленным правильным форматированием Соединенного Королевства.

4.3. Нули в конце

Используя Strings#replace, мы можем удалить нули в конце.

<p th:text="${#strings.replace(#numbers.formatCurrency(param.amount), '.00', '')}"></p>

Теперь мы можем видеть полную сумму без двойных нулей в конце:

@Test
public void whenCallCurrencyWithUSALocaleWithoutDecimal_ThenReturnCurrencyWithoutTrailingZeros()
  throws Exception {
    mockMvc.perform(MockMvcRequestBuilders.get("/currency")
      .header("Accept-Language", "en-US")
      .param("amount", "10032"))
      .andExpect(status().isOk())
      .andExpect(content().string(containsString("$10,032")));
}

4.4. Десятичные дроби

В зависимости от локали десятичные дроби могут быть отформатированы по-разному. Поэтому, если мы хотим заменить десятичную точку запятой, мы можем использовать метод formatDecimal, предоставляемый классом Numbers:

<p th:text="${#numbers.formatDecimal(param.amount, 1, 2, 'COMMA')}"></p>

Посмотрим на результат в тесте:

@Test
public void whenCallCurrencyWithUSALocale_ThenReturnReplacedDecimalPoint() throws Exception {
    mockMvc.perform(MockMvcRequestBuilders.get("/currency")
      .header("Accept-Language", "en-US")
      .param("amount", "1.5"))
      .andExpect(status().isOk())
      .andExpect(content().string(containsString("1,5")));
}

Значение будет в формате «1,5».

5. Заключение

В этом коротком руководстве мы показали, как Thymeleaf можно использовать с Spring Web для обработки валют с использованием локали пользователя.

Как всегда, код доступен на GitHub.