feat(creator-channel): 홈 콘텐츠 제목 번역을 적용한다

This commit is contained in:
2026-09-09 23:17:18 +09:00
parent 950ff98e18
commit 12b9a912c0
2 changed files with 190 additions and 17 deletions
@@ -9,7 +9,11 @@ import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.content.order.Order
import kr.co.vividnext.sodalive.content.order.OrderType
import kr.co.vividnext.sodalive.content.pin.PinContent
import kr.co.vividnext.sodalive.content.series.translation.SeriesTranslation
import kr.co.vividnext.sodalive.content.series.translation.SeriesTranslationPayload
import kr.co.vividnext.sodalive.content.theme.AudioContentTheme
import kr.co.vividnext.sodalive.content.translation.ContentTranslation
import kr.co.vividnext.sodalive.content.translation.ContentTranslationPayload
import kr.co.vividnext.sodalive.creator.admin.content.series.Series
import kr.co.vividnext.sodalive.creator.admin.content.series.SeriesContent
import kr.co.vividnext.sodalive.explorer.profile.CreatorCheers
@@ -514,6 +518,84 @@ class DefaultCreatorChannelHomeQueryRepositoryTest @Autowired constructor(
assertTrue(records.last().isPointAvailable)
}
@Test
@DisplayName("홈 오디오 제목과 시리즈명은 요청 locale 번역을 사용하고 공백 번역은 원문으로 fallback한다")
fun shouldFindHomeAudioContentsWithTranslatedTitleFallback() {
val now = LocalDateTime.of(2026, 6, 12, 12, 0)
val creator = saveMember("home-audio-i18n-creator", MemberRole.CREATOR)
val first = saveAudioContent(creator, now.minusDays(3), isAdult = false)
val listed = saveAudioContent(creator, now.minusDays(2), isAdult = false)
val latest = saveAudioContent(creator, now.minusDays(1), isAdult = false)
val series = saveSeries("home-origin-series", creator, isOriginal = true)
saveSeriesContent(series, listed)
saveContentTranslation(latest, "en", "Latest Audio")
saveContentTranslation(latest, "ja", "最新オーディオ")
saveContentTranslation(listed, "en", "Listed Audio")
saveContentTranslation(first, "en", " ")
saveSeriesTranslation(series, "en", "Home Series")
flushAndClear()
val latestRecord = repository.findLatestAudioContent(creator.id!!, now, false, locale = "en")
val records = repository.findAudioContents(
creator.id!!,
now,
latestRecord!!.audioContentId,
false,
locale = "en",
limit = 9
)
val jaLatestRecord = repository.findLatestAudioContent(creator.id!!, now, false, locale = "ja")
assertEquals("Latest Audio", latestRecord.title)
assertEquals("最新オーディオ", jaLatestRecord!!.title)
assertEquals(listOf(listed.id, first.id), records.map { it.audioContentId })
assertEquals("Listed Audio", records.first().title)
assertEquals("Home Series", records.first().seriesName)
assertEquals(first.title, records.last().title)
}
@Test
@DisplayName("홈 AUDIO 스케줄과 시리즈 제목은 요청 locale 번역을 사용하고 라이브 스케줄 제목은 유지한다")
fun shouldFindHomeSchedulesAndSeriesWithTranslatedTitleFallback() {
val now = LocalDateTime.of(2026, 6, 12, 12, 0)
val creator = saveMember("home-schedule-i18n-creator", MemberRole.CREATOR)
val liveSchedule = saveLiveRoom(creator, now.plusHours(1), channelName = null, isAdult = false)
val audioSchedule = saveAudioContent(creator, now.plusHours(2), isAdult = false)
val blankAudioSchedule = saveAudioContent(creator, now.plusHours(3), isAdult = false)
val series = saveSeries("home-origin-series-title", creator, isOriginal = true)
val blankSeries = saveSeries("home-blank-series-title", creator, isOriginal = true)
saveSeriesContent(series, saveAudioContent(creator, now.minusDays(1), isAdult = false))
saveSeriesContent(blankSeries, saveAudioContent(creator, now.minusDays(2), isAdult = false))
saveContentTranslation(audioSchedule, "en", "Scheduled Audio")
saveContentTranslation(audioSchedule, "ja", "予約オーディオ")
saveContentTranslation(blankAudioSchedule, "en", " ")
saveSeriesTranslation(series, "en", "Translated Home Series")
saveSeriesTranslation(series, "ja", "翻訳ホームシリーズ")
saveSeriesTranslation(blankSeries, "en", " ")
flushAndClear()
val schedules = repository.findSchedules(
creator.id!!,
now,
canViewAdultContent = false,
viewerId = null,
isViewerCreator = false,
effectiveViewerGender = null,
locale = "en",
limit = 10
)
val seriesRecords = repository.findSeries(creator.id!!, null, now, false, ContentType.ALL, locale = "en", limit = 8)
val jaSeriesRecords = repository.findSeries(creator.id!!, null, now, false, ContentType.ALL, locale = "ja", limit = 8)
assertEquals(listOf(liveSchedule.id, audioSchedule.id, blankAudioSchedule.id), schedules.map { it.targetId })
assertEquals(liveSchedule.title, schedules.first().title)
assertEquals("Scheduled Audio", schedules[1].title)
assertEquals(blankAudioSchedule.title, schedules.last().title)
assertEquals("Translated Home Series", seriesRecords.first { it.seriesId == series.id }.title)
assertEquals(blankSeries.title, seriesRecords.first { it.seriesId == blankSeries.id }.title)
assertEquals("翻訳ホームシリーズ", jaSeriesRecords.first { it.seriesId == series.id }.title)
}
@Test
@DisplayName("홈 오디오 목록은 최신 오디오를 제외하고 활성 고정 콘텐츠를 최근 고정순으로 먼저 조회한다")
fun shouldSortHomeAudioContentsByActivePinBeforeReleaseDate() {
@@ -1215,6 +1297,40 @@ class DefaultCreatorChannelHomeQueryRepositoryTest @Autowired constructor(
return seriesContent
}
private fun saveSeriesTranslation(series: Series, locale: String, title: String): SeriesTranslation {
val translation = SeriesTranslation(
seriesId = series.id!!,
locale = locale,
renderedPayload = SeriesTranslationPayload(title = title, introduction = "", keywords = emptyList())
)
entityManager.persist(translation)
entityManager.flush()
val payload = "{\"title\":\"$title\",\"introduction\":\"\",\"keywords\":[]}"
entityManager.createNativeQuery(
"update series_translation set rendered_payload = '$payload' format json where id = :id"
)
.setParameter("id", translation.id)
.executeUpdate()
return translation
}
private fun saveContentTranslation(content: AudioContent, locale: String, title: String): ContentTranslation {
val translation = ContentTranslation(
contentId = content.id!!,
locale = locale,
renderedPayload = ContentTranslationPayload(title = title, detail = "", tags = "")
)
entityManager.persist(translation)
entityManager.flush()
val payload = "{\"title\":\"$title\",\"detail\":\"\",\"tags\":\"\"}"
entityManager.createNativeQuery(
"update content_translation set rendered_payload = '$payload' format json where id = :id"
)
.setParameter("id", translation.id)
.executeUpdate()
return translation
}
private fun savePinContent(
creator: Member,
content: AudioContent,