From 0c52804f066ae99ff7fc2f0623590f33a590f430 Mon Sep 17 00:00:00 2001 From: Klaus Date: Tue, 16 Dec 2025 06:19:15 +0900 Subject: [PATCH] =?UTF-8?q?=EC=9B=90=EC=9E=91=20=EB=AA=A9=EB=A1=9D?= =?UTF-8?q?=EC=9D=98=20=EC=A0=9C=EB=AA=A9=EA=B3=BC=20=EC=BD=98=ED=85=90?= =?UTF-8?q?=EC=B8=A0=20=ED=83=80=EC=9E=85=EC=9D=84=20=ED=98=84=EC=9E=AC=20?= =?UTF-8?q?=EC=96=B8=EC=96=B4(locale)=EC=97=90=20=EB=A7=9E=EC=B6=B0=20?= =?UTF-8?q?=EC=9D=BC=EA=B4=84=20=EB=B2=88=EC=97=AD=20=EA=B8=B0=EB=8A=A5=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 --- .../controller/OriginalWorkController.kt | 58 ++++++++++++++++++- .../OriginalWorkTranslationRepository.kt | 2 + 2 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/chat/original/controller/OriginalWorkController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/chat/original/controller/OriginalWorkController.kt index eb8cbfb..6efc678 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/chat/original/controller/OriginalWorkController.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/chat/original/controller/OriginalWorkController.kt @@ -7,8 +7,10 @@ import kr.co.vividnext.sodalive.chat.original.dto.OriginalWorkDetailResponse import kr.co.vividnext.sodalive.chat.original.dto.OriginalWorkListItemResponse import kr.co.vividnext.sodalive.chat.original.dto.OriginalWorkListResponse import kr.co.vividnext.sodalive.chat.original.service.OriginalWorkQueryService +import kr.co.vividnext.sodalive.chat.original.translation.OriginalWorkTranslationRepository import kr.co.vividnext.sodalive.common.ApiResponse import kr.co.vividnext.sodalive.common.SodaException +import kr.co.vividnext.sodalive.i18n.LangContext import kr.co.vividnext.sodalive.member.Member import org.springframework.beans.factory.annotation.Value import org.springframework.security.core.annotation.AuthenticationPrincipal @@ -30,6 +32,10 @@ class OriginalWorkController( private val queryService: OriginalWorkQueryService, private val characterImageRepository: CharacterImageRepository, + private val langContext: LangContext, + + private val originalWorkTranslationRepository: OriginalWorkTranslationRepository, + @Value("\${cloud.aws.cloud-front.host}") private val imageHost: String ) { @@ -51,7 +57,57 @@ class OriginalWorkController( val includeAdult = member?.auth != null val pageRes = queryService.listForAppPage(includeAdult, page, size) val content = pageRes.content.map { OriginalWorkListItemResponse.from(it, imageHost) } - ApiResponse.ok(OriginalWorkListResponse(totalCount = pageRes.totalElements, content = content)) + + /** + * 원작 목록의 제목과 콘텐츠 타입을 현재 언어(locale)에 맞춰 일괄 번역한다. + * + * 처리 절차: + * - 입력된 원작들의 originalWorkId 집합을 만들고, 요청 언어 코드(langContext.lang.code)로 + * originalWorkTranslationRepository 번역 데이터를 한 번에 조회한다. + * - 각 항목에 대해 번역된 제목과 콘텐츠 타입이 존재하고 비어있지 않으면 title과 contentType을 번역 값으로 교체한다. + * - 번역이 없거나 공백이면 원본 항목을 그대로 반환한다. + * + * 성능: + * - N건의 항목을 1회의 조회로 해결하기 위해 IN 쿼리를 사용한다. + */ + val translatedContent = run { + if (content.isEmpty()) { + content + } else { + val ids = content.map { it.id }.toSet() + val locale = langContext.lang.code + val translations = originalWorkTranslationRepository + .findByOriginalWorkIdInAndLocale(ids, locale) + .associateBy { it.originalWorkId } + + content.map { item -> + val payload = translations[item.id]?.renderedPayload + if (payload != null) { + val newTitle = payload.title.trim() + val newContentType = payload.contentType.trim() + val hasTitle = newTitle.isNotEmpty() + val hasContentType = newContentType.isNotEmpty() + if (hasTitle || hasContentType) { + item.copy( + title = if (hasTitle) newTitle else item.title, + contentType = if (hasContentType) newContentType else item.contentType + ) + } else { + item + } + } else { + item + } + } + } + } + + ApiResponse.ok( + OriginalWorkListResponse( + totalCount = pageRes.totalElements, + content = translatedContent + ) + ) } /** diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/chat/original/translation/OriginalWorkTranslationRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/chat/original/translation/OriginalWorkTranslationRepository.kt index e63fbeb..0e88a4a 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/chat/original/translation/OriginalWorkTranslationRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/chat/original/translation/OriginalWorkTranslationRepository.kt @@ -4,4 +4,6 @@ import org.springframework.data.jpa.repository.JpaRepository interface OriginalWorkTranslationRepository : JpaRepository { fun findByOriginalWorkIdAndLocale(originalWorkId: Long, locale: String): OriginalWorkTranslation? + + fun findByOriginalWorkIdInAndLocale(originalWorkIds: Set, locale: String): List }