카테고리 목록 조회에 언어별 번역 적용
LangContext에 따라 카테고리명을 번역해 반환한다. 번역본이 없으면 Papago API로 번역 후 CategoryTranslation에 저장하고 즉시 결과를 반환한다. 공개 API의 getCategoryList 응답이 요청 로케일을 반영한다.
This commit is contained in:
@@ -4,8 +4,11 @@ import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.content.AudioContentRepository
|
||||
import kr.co.vividnext.sodalive.content.LanguageDetectEvent
|
||||
import kr.co.vividnext.sodalive.content.LanguageDetectTargetType
|
||||
import kr.co.vividnext.sodalive.i18n.LangContext
|
||||
import kr.co.vividnext.sodalive.i18n.translation.LanguageTranslationEvent
|
||||
import kr.co.vividnext.sodalive.i18n.translation.LanguageTranslationTargetType
|
||||
import kr.co.vividnext.sodalive.i18n.translation.PapagoTranslationService
|
||||
import kr.co.vividnext.sodalive.i18n.translation.TranslateRequest
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.block.BlockMemberRepository
|
||||
import org.springframework.context.ApplicationEventPublisher
|
||||
@@ -18,8 +21,11 @@ class CategoryService(
|
||||
private val contentRepository: AudioContentRepository,
|
||||
private val blockMemberRepository: BlockMemberRepository,
|
||||
private val categoryContentRepository: CategoryContentRepository,
|
||||
private val categoryTranslationRepository: CategoryTranslationRepository,
|
||||
|
||||
private val applicationEventPublisher: ApplicationEventPublisher
|
||||
private val langContext: LangContext,
|
||||
private val applicationEventPublisher: ApplicationEventPublisher,
|
||||
private val translationService: PapagoTranslationService
|
||||
) {
|
||||
@Transactional
|
||||
fun createCategory(request: CreateCategoryRequest, member: Member) {
|
||||
@@ -119,11 +125,83 @@ class CategoryService(
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
fun getCategoryList(creatorId: Long, memberId: Long): List<GetCategoryListResponse> {
|
||||
val isBlocked = blockMemberRepository.isBlocked(blockedMemberId = memberId, memberId = creatorId)
|
||||
if (isBlocked) throw SodaException("잘못된 접근입니다.")
|
||||
|
||||
return repository.findByCreatorId(creatorId = creatorId)
|
||||
// 기본 카테고리 목록 조회 (원본 언어 기준)
|
||||
val baseList = repository.findByCreatorId(creatorId = creatorId)
|
||||
if (baseList.isEmpty()) return baseList
|
||||
|
||||
val locale = langContext.lang.code
|
||||
|
||||
// 원본 엔티티를 조회하여 languageCode 파악
|
||||
val categoryIds = baseList.map { it.categoryId }
|
||||
val entities = repository.findAllById(categoryIds)
|
||||
val entityMap = entities.associateBy { it.id!! }
|
||||
|
||||
// 요청 로케일로 이미 저장된 번역 일괄 조회
|
||||
val translations = categoryTranslationRepository
|
||||
.findByCategoryIdInAndLocale(categoryIds, locale)
|
||||
.associateBy { it.categoryId }
|
||||
|
||||
// 각 항목에 대해 번역 적용. 없으면 Papago로 번역 저장 후 적용
|
||||
val result = mutableListOf<GetCategoryListResponse>()
|
||||
for (item in baseList) {
|
||||
val entity = entityMap[item.categoryId]
|
||||
if (entity == null) {
|
||||
result.add(item)
|
||||
continue
|
||||
}
|
||||
|
||||
val sourceLang = entity.languageCode
|
||||
if (!sourceLang.isNullOrBlank() && sourceLang != locale) {
|
||||
val existing = translations[item.categoryId]
|
||||
if (existing != null && !existing.category.isNullOrBlank()) {
|
||||
result.add(GetCategoryListResponse(categoryId = item.categoryId, category = existing.category))
|
||||
continue
|
||||
}
|
||||
|
||||
// 번역본이 없으면 Papago 번역 후 저장
|
||||
val texts = listOf(entity.title)
|
||||
val response = translationService.translate(
|
||||
request = TranslateRequest(
|
||||
texts = texts,
|
||||
sourceLanguage = sourceLang,
|
||||
targetLanguage = locale
|
||||
)
|
||||
)
|
||||
|
||||
val translatedTexts = response.translatedText
|
||||
if (translatedTexts.size == texts.size) {
|
||||
val translatedCategory = translatedTexts[0]
|
||||
|
||||
val existingOne = categoryTranslationRepository
|
||||
.findByCategoryIdAndLocale(entity.id!!, locale)
|
||||
if (existingOne == null) {
|
||||
categoryTranslationRepository.save(
|
||||
CategoryTranslation(
|
||||
categoryId = entity.id!!,
|
||||
locale = locale,
|
||||
category = translatedCategory
|
||||
)
|
||||
)
|
||||
} else {
|
||||
existingOne.category = translatedCategory
|
||||
categoryTranslationRepository.save(existingOne)
|
||||
}
|
||||
|
||||
result.add(GetCategoryListResponse(categoryId = item.categoryId, category = translatedCategory))
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// 번역이 필요 없거나 실패한 경우 원본 사용
|
||||
result.add(item)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
private fun validateTitle(title: String) {
|
||||
|
||||
@@ -4,4 +4,6 @@ import org.springframework.data.jpa.repository.JpaRepository
|
||||
|
||||
interface CategoryTranslationRepository : JpaRepository<CategoryTranslation, Long> {
|
||||
fun findByCategoryIdAndLocale(categoryId: Long, locale: String): CategoryTranslation?
|
||||
|
||||
fun findByCategoryIdInAndLocale(categoryIds: Collection<Long>, locale: String): List<CategoryTranslation>
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user