feat(creator-community): 게시물 번역 서비스를 추가한다

This commit is contained in:
2026-09-10 15:11:22 +09:00
parent 3e9ba0b23e
commit 6efecf5495
3 changed files with 1044 additions and 1 deletions
@@ -18,8 +18,13 @@ import kr.co.vividnext.sodalive.content.theme.translation.ContentThemeTranslatio
import kr.co.vividnext.sodalive.content.translation.ContentTranslation
import kr.co.vividnext.sodalive.content.translation.ContentTranslationPayload
import kr.co.vividnext.sodalive.content.translation.ContentTranslationRepository
import kr.co.vividnext.sodalive.explorer.profile.creatorCommunity.CreatorCommunityRepository
import kr.co.vividnext.sodalive.v2.creator.channel.community.translation.adapter.out.persistence.CreatorCommunityTranslation
import kr.co.vividnext.sodalive.v2.creator.channel.community.translation.adapter.out.persistence.CreatorCommunityTranslationRepository
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import javax.persistence.EntityManager
import javax.persistence.LockModeType
@Service
class TranslationReadModelMaterializer(
@@ -31,7 +36,10 @@ class TranslationReadModelMaterializer(
private val seriesTranslationRepository: SeriesTranslationRepository,
private val seriesGenreTranslationRepository: SeriesGenreTranslationRepository,
private val originalWorkTranslationRepository: OriginalWorkTranslationRepository,
private val categoryTranslationRepository: CategoryTranslationRepository
private val categoryTranslationRepository: CategoryTranslationRepository,
private val creatorCommunityRepository: CreatorCommunityRepository,
private val creatorCommunityTranslationRepository: CreatorCommunityTranslationRepository,
private val entityManager: EntityManager
) {
@Transactional
fun materialize(resourceType: LanguageTranslationTargetType, resourceId: Long, targetLanguage: String): Boolean {
@@ -46,6 +54,9 @@ class TranslationReadModelMaterializer(
LanguageTranslationTargetType.SERIES_GENRE -> upsertSeriesGenre(resourceId, targetLanguage, translations)
LanguageTranslationTargetType.ORIGINAL_WORK -> upsertOriginalWork(resourceId, targetLanguage, translations)
LanguageTranslationTargetType.CREATOR_CONTENT_CATEGORY -> upsertCategory(resourceId, targetLanguage, translations)
LanguageTranslationTargetType.CREATOR_COMMUNITY -> {
return upsertCreatorCommunity(source, targetLanguage.lowercase(), translations)
}
}
return true
@@ -180,6 +191,47 @@ class TranslationReadModelMaterializer(
}
}
private fun upsertCreatorCommunity(
source: TranslationSource,
targetLanguage: String,
translations: Map<String, String>
): Boolean {
val sourceRevision = source.sourceRevision ?: return false
val sourceHash = SourceTextNormalizer.hash(source.fields.single().sourceText)
val creatorCommunity = creatorCommunityRepository.findByIdAndIsActiveTrueForUpdate(source.resourceId) ?: return false
entityManager.refresh(creatorCommunity, LockModeType.PESSIMISTIC_WRITE)
if (
!creatorCommunity.isActive ||
creatorCommunity.contentRevision != sourceRevision ||
creatorCommunity.languageCode?.lowercase() != source.sourceLanguage.lowercase() ||
SourceTextNormalizer.hash(creatorCommunity.content) != sourceHash
) {
return false
}
val existing = creatorCommunityTranslationRepository
.findByCreatorCommunityIdAndLocaleForUpdate(source.resourceId, targetLanguage)
if (existing == null) {
creatorCommunityTranslationRepository.save(
CreatorCommunityTranslation(
creatorCommunityId = source.resourceId,
locale = targetLanguage,
content = translations["content"].orEmpty(),
sourceRevision = sourceRevision,
sourceHash = sourceHash,
sourceLanguage = source.sourceLanguage.lowercase()
)
)
} else {
existing.content = translations["content"].orEmpty()
existing.sourceRevision = sourceRevision
existing.sourceHash = sourceHash
existing.sourceLanguage = source.sourceLanguage.lowercase()
creatorCommunityTranslationRepository.save(existing)
}
return true
}
companion object {
const val DEFAULT_PROVIDER = "papago"
}