Springでエラーレスポンスを多言語化してみる

# 背景
業務でAPIのエラーレスポンスのメッセージを多言語で返したかったので試してみました。

## project作成
いつも通りSpring Initializrでprojectを作ります。
https://start.spring.io/

## messages.propertiesの作成
resources/i18n 配下に配置しました。
![01.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121447/757df283-ff2b-3bf2-b078-c3543bd92480.jpeg)

今回は英語をデフォルトします。
中身はこんな感じです。
![02.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121447/a1d4a98f-54c9-4fe6-d855-acd281248507.jpeg)
![03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121447/f3b24dbb-3008-3130-ca47-4041dd6958aa.png)

## MessageSourceConfigの作成
```kotlin:MessageSourceConfig.kt
@Configuration
class MessageSourceConfig {

    @Bean
    fun messageSource(): MessageSource {
        val messageSource = ResourceBundleMessageSource()
        messageSource.setBasenames("i18n/messages")
        messageSource.setDefaultEncoding(StandardCharsets.UTF_8.name())
        messageSource.setFallbackToSystemLocale(false)
        return messageSource
    }
}
```
resourceファイルの指定と、デフォルトEncode設定や、
未設定のLocaleが来たときのデフォルト設定のためにConfigファイルを作成します。

## Conrtollerの作成
```kotlin:HogeController.kt

@RestController
@RequestMapping("hoge")
class HogeController {

    @Autowired
    lateinit var messageSource: MessageSource

    @GetMapping("message")
    fun getMessage(locale: Locale): ResponseEntity<String> {
        val errorMsg = messageSource.getMessage("hoge", null, locale)
        return ResponseEntity.ok(errorMsg)
    }

    @GetMapping("exception")
    fun getException(): ResponseEntity<String> {
        // コンパイルを通すためにif分を挟む
        if (true) {
            throw DataNotFoundException()
        }
        return ResponseEntity.ok("")
    }
}
```
通常とExceptionをThrowするパターンを作っておきます。
通常のエンドポイントでmessageが取得できることを確認します。
まずはjaで叩いてみます。
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121447/b791b773-5d73-6522-dff3-61d048c5b6cf.png)
ちゃんと日本語で返ってきましたね！！

次にenで叩いてみます。
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121447/73010bbf-2564-bc50-ece0-e84d90bb22d8.png)
こちらもちゃんと英語で返ってきてますね！！

未作成のkoで叩いてみます。
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121447/e754a1d1-901e-068d-2b0d-2b1f80453526.png)
setFallbackToSystemLocaleの設定が効いているので英語で返ってきてますね！



## エラーレスポンス用のExceptionHandlerの作成
```kotlin:ExceptionHandler.kt

@RestControllerAdvice
class ExceptionHandler {

    @Autowired
    lateinit var messageSource: MessageSource

    @ExceptionHandler(DataNotFoundException::class)
    fun handleDataNotFoundException(e: DataNotFoundException, locale: Locale): ResponseEntity<String> {
        val errorMsg = messageSource.getMessage("dataNotFound", null, locale)
        return ResponseEntity(errorMsg, HttpStatus.NOT_FOUND)
    }

}
```
ExcrptionをCatchしてエラーレスポンスを返すためにHandlerを作ります。
作成後、Excptionをthrowするエンドポイントを叩き、messageが取得できることを確認します。
通常と同様、ja, en koで叩いてみます。
![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121447/5706c126-94c6-1165-99b5-672b4fa76237.png)

![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121447/747422e3-8a6a-b2f7-ced1-c096d7eb3c87.png)

![10_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121447/fb3e3271-169e-a772-093f-cf08e47589e8.png)
すべて意図したとおりに返ってきてますね！



# 終わりに
以上で、Springでエラーレスポンスを多言語化してみました。
フロントによってはAPIのレスポンスメッセージをそのまま出す場合があるのでサーバ側でいい感じにできると嬉しいですね。

サンプルソース
https://github.com/akawai11/spring-message-source-sample