From 082f255773463a31f506186fe53ebaf9d5a3ae0d Mon Sep 17 00:00:00 2001 From: Klaus Date: Fri, 12 Dec 2025 16:57:34 +0900 Subject: [PATCH] =?UTF-8?q?=EC=9A=94=EC=B2=AD=20=EC=8A=A4=EC=BD=94?= =?UTF-8?q?=ED=94=84=20=EC=96=B8=EC=96=B4=20=EC=BB=A8=ED=85=8D=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=EC=99=80=20=EC=9D=B8=ED=84=B0=EC=85=89=ED=84=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Interceptor에서 Accept-Language 헤더를 파싱 - 요청 단위 LangContext에 언어 정보 저장 - 서비스 및 예외 처리 계층에서 언어 컨텍스트 주입 - enum 및 when 기반 언어 정책을 한 곳으로 통합 --- .../vividnext/sodalive/configs/WebConfig.kt | 10 ++++++++- .../kr/co/vividnext/sodalive/i18n/Lang.kt | 22 +++++++++++++++++++ .../co/vividnext/sodalive/i18n/LangContext.kt | 15 +++++++++++++ .../sodalive/i18n/LangInterceptor.kt | 21 ++++++++++++++++++ 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/i18n/Lang.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/i18n/LangContext.kt create mode 100644 src/main/kotlin/kr/co/vividnext/sodalive/i18n/LangInterceptor.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/configs/WebConfig.kt b/src/main/kotlin/kr/co/vividnext/sodalive/configs/WebConfig.kt index 6c38c9c..6ef72f9 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/configs/WebConfig.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/configs/WebConfig.kt @@ -1,11 +1,19 @@ package kr.co.vividnext.sodalive.configs +import kr.co.vividnext.sodalive.i18n.LangInterceptor import org.springframework.context.annotation.Configuration import org.springframework.web.servlet.config.annotation.CorsRegistry +import org.springframework.web.servlet.config.annotation.InterceptorRegistry import org.springframework.web.servlet.config.annotation.WebMvcConfigurer @Configuration -class WebConfig : WebMvcConfigurer { +class WebConfig( + private val langInterceptor: LangInterceptor +) : WebMvcConfigurer { + override fun addInterceptors(registry: InterceptorRegistry) { + registry.addInterceptor(langInterceptor).addPathPatterns("/**") + } + override fun addCorsMappings(registry: CorsRegistry) { registry.addMapping("/**") .allowedOrigins( diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/i18n/Lang.kt b/src/main/kotlin/kr/co/vividnext/sodalive/i18n/Lang.kt new file mode 100644 index 0000000..d40abe3 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/i18n/Lang.kt @@ -0,0 +1,22 @@ +package kr.co.vividnext.sodalive.i18n + +import java.util.Locale + +enum class Lang(val code: String, val locale: Locale) { + KO("ko", Locale.KOREAN), + EN("en", Locale.ENGLISH), + JA("ja", Locale.JAPANESE); + + companion object { + fun fromAcceptLanguage(header: String?): Lang { + if (header.isNullOrBlank()) return KO + val two = header.trim().lowercase().take(2) // 앱은 2자리만 보내지만 안전하게 처리 + return when (two) { + "ko" -> KO + "en" -> EN + "ja" -> JA + else -> KO + } + } + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/i18n/LangContext.kt b/src/main/kotlin/kr/co/vividnext/sodalive/i18n/LangContext.kt new file mode 100644 index 0000000..61bd91b --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/i18n/LangContext.kt @@ -0,0 +1,15 @@ +package kr.co.vividnext.sodalive.i18n + +import org.springframework.stereotype.Component +import org.springframework.web.context.annotation.RequestScope + +@Component +@RequestScope +class LangContext { + var lang: Lang = Lang.KO + internal set + + fun setLang(lang: Lang) { + this.lang = lang + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/i18n/LangInterceptor.kt b/src/main/kotlin/kr/co/vividnext/sodalive/i18n/LangInterceptor.kt new file mode 100644 index 0000000..8e06329 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/i18n/LangInterceptor.kt @@ -0,0 +1,21 @@ +package kr.co.vividnext.sodalive.i18n + +import org.springframework.stereotype.Component +import org.springframework.web.servlet.HandlerInterceptor +import javax.servlet.http.HttpServletRequest +import javax.servlet.http.HttpServletResponse + +@Component +class LangInterceptor( + private val langContext: LangContext +) : HandlerInterceptor { + override fun preHandle( + request: HttpServletRequest, + response: HttpServletResponse, + handler: Any + ): Boolean { + val acceptLanguage = request.getHeader("Accept-Language") + langContext.setLang(Lang.fromAcceptLanguage(acceptLanguage)) + return true + } +}