From 6ade9b024a83ecf44143cdadcec955f71debcbc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=BC=ED=98=81?= Date: Sat, 29 Aug 2026 15:57:52 +0900 Subject: [PATCH 1/3] =?UTF-8?q?refactor(afternote,receiver):=20contentDesc?= =?UTF-8?q?ription=20=ED=95=98=EB=93=9C=EC=BD=94=EB=94=A9=206=EA=B1=B4?= =?UTF-8?q?=EC=9D=84=20=EB=AC=B8=EC=9E=90=EC=97=B4=20=EB=A6=AC=EC=86=8C?= =?UTF-8?q?=EC=8A=A4=EB=A1=9C=20=EC=98=AE=EA=B8=B4=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TalkBack 이 그대로 낭독하는 사용자 노출 문자열인데 코드에 박혀 있었다. 「영상 재생」은 content_description_video_play 가 이미 있고 MemorialVideoUpload 는 그걸 쓰는데, 추억 노트 상세 두 곳만 같은 문구를 리터럴로 다시 적고 있었다. 신설이 아니라 미사용 리소스 연결이다. 영상 썸네일 라벨은 신설하되 #1079 가 정한 afternote_ 프리픽스를 처음부터 따른다. 기존 무접두 키의 리네임은 그 이슈의 일괄 처리 몫이라 건드리지 않는다. 수신 상세의 "Play" 는 리소스화하지 않고 없앤다. 영상이 없을 때만 그리는 플레이스홀더라 clickable 이 없는데 재생으로 읽히면 없는 어포던스를 알린다. 맥락은 바로 위 섹션 헤더가 이미 읽어 준다. 에디터 섹션 라벨은 "$text, $필수항목" 조합을 포맷 리소스 한 개로 합쳤다. 구분자가 로케일에 딸린 문자열이라 코드에 두면 번역이 갈린다. --- .../presentation/author/detail/MemorialDetailScreen.kt | 5 +++-- .../presentation/author/editor/EditorSectionLabel.kt | 6 +++--- .../presentation/src/main/res/values/strings.xml | 3 ++- .../detail/MemorialReceivedDetailScreen.kt | 10 +++++++--- 4 files changed, 15 insertions(+), 9 deletions(-) diff --git a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/detail/MemorialDetailScreen.kt b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/detail/MemorialDetailScreen.kt index 0d117d433f..3270417ece 100644 --- a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/detail/MemorialDetailScreen.kt +++ b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/detail/MemorialDetailScreen.kt @@ -278,7 +278,8 @@ private fun VideoThumbnail(thumbnailUrl: String?) { if (!thumbnailUrl.isNullOrBlank()) { AsyncImage( model = thumbnailUrl, - contentDescription = "장례식에 남길 영상 썸네일", + contentDescription = + stringResource(R.string.afternote_content_description_memorial_video_thumbnail), modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Crop, ) @@ -304,7 +305,7 @@ private fun VideoThumbnail(thumbnailUrl: String?) { // 재생 아이콘 Image( painter = painterResource(R.drawable.feature_afternote_ic_playback), - contentDescription = "영상 재생", + contentDescription = stringResource(R.string.content_description_video_play), modifier = Modifier .align(Alignment.Center) diff --git a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/EditorSectionLabel.kt b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/EditorSectionLabel.kt index ebe6c87acf..81a4999f06 100644 --- a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/EditorSectionLabel.kt +++ b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/editor/EditorSectionLabel.kt @@ -43,14 +43,14 @@ fun EditorSectionLabel( fontWeight = FontWeight.Medium, ), ) { - val requiredMarkerDescription = - stringResource(R.string.afternote_editor_semantics_required_field) + val requiredFieldDescription = + stringResource(R.string.afternote_editor_semantics_required_field_description, text) Row( modifier = modifier.semantics(mergeDescendants = true) { if (isRequired) { - contentDescription = "$text, $requiredMarkerDescription" + contentDescription = requiredFieldDescription } }, verticalAlignment = Alignment.CenterVertically, diff --git a/feature/afternote/presentation/src/main/res/values/strings.xml b/feature/afternote/presentation/src/main/res/values/strings.xml index 4826ae46f8..197bf3a319 100644 --- a/feature/afternote/presentation/src/main/res/values/strings.xml +++ b/feature/afternote/presentation/src/main/res/values/strings.xml @@ -180,6 +180,7 @@ %d명에게 아래로 영상 재생 + 장례식에 남길 영상 썸네일 마지막 인사말을 입력해주세요 확인 @@ -230,7 +231,7 @@ 드롭다운 추가 더보기 - 필수 항목 + %1$s, 필수 항목 장례식에 남길 영상 영상 변경 영상 추가 diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/detail/MemorialReceivedDetailScreen.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/detail/MemorialReceivedDetailScreen.kt index 2358ffbf70..124cfa86ae 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/detail/MemorialReceivedDetailScreen.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/detail/MemorialReceivedDetailScreen.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import androidx.core.net.toUri @@ -204,7 +205,9 @@ private fun ReceiverVideoSection( ) { Icon( painter = painterResource(R.drawable.receiver_ic_play_arrow), - contentDescription = "Play", + // 영상이 없을 때만 그리는 플레이스홀더다. clickable 이 없어 재생 액션이 없으므로 + // 라벨을 붙이면 없는 어포던스를 알린다. 맥락은 위 ReceiverSectionHeader 가 읽어 준다. + contentDescription = null, tint = AfternoteDesign.colors.white, modifier = Modifier @@ -231,7 +234,8 @@ private fun ReceiverMemorialVideoThumbnail(thumbnailUrl: String?) { if (!thumbnailUrl.isNullOrBlank()) { AsyncImage( model = thumbnailUrl, - contentDescription = "장례식에 남길 영상 썸네일", + contentDescription = + stringResource(AfternoteR.string.afternote_content_description_memorial_video_thumbnail), modifier = Modifier.fillMaxSize(), contentScale = ContentScale.Crop, ) @@ -253,7 +257,7 @@ private fun ReceiverMemorialVideoThumbnail(thumbnailUrl: String?) { ) Image( painter = painterResource(AfternoteR.drawable.feature_afternote_ic_playback), - contentDescription = "영상 재생", + contentDescription = stringResource(AfternoteR.string.content_description_video_play), modifier = Modifier .align(Alignment.Center) From 9cc6f8a6bd0fa5c9e448b902e3ac92120497e1dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=BC=ED=98=81?= Date: Sat, 29 Aug 2026 16:53:39 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor(core,afternote,receiver,onboarding?= =?UTF-8?q?):=20=ED=99=94=EB=A9=B4=20=EB=85=B8=EC=B6=9C=20=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=EC=97=B4=2027=EA=B1=B4=EC=9D=84=20=EB=A6=AC=EC=86=8C?= =?UTF-8?q?=EC=8A=A4=EB=A1=9C=20=EC=98=AE=EA=B8=B4=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit contentDescription 만 보던 범위를 화면에 그려지는 문자열 전체로 넓혔다. 성격이 같은데 앞 커밋에서 빠져 있었다. 절반 가까이가 신설이 아니라 이미 있는 리소스의 미사용이었다. 「장례식에 남길 영상」·「추억 플레이리스트」·「영상을 재생할 수 있는 앱이 없습니다.」는 리소스가 있는데 같은 문구를 리터럴로 다시 적고 있었고, 약관 상세는 본문 6개가 리소스인데 제목 6개만 코드에 남아 있었다. nav_afternote 는 참조 0건인 죽은 키였다. 값이 같은 키를 새로 만드는 대신 afternote_home_title 로 이름을 바꿔 실제 쓰이게 했다 — 키 수는 그대로다. MemorialPlaylist 의 label 은 기본값이 이미 그 리소스라 호출부에서 같은 값을 다시 넘기던 인자를 지웠다. 두 화면이 쓰던 「현재 N개의 노래가 담겨 있습니다.」는 문구가 완전히 같아 키 하나로 묶었다. 요일 라벨은 순서·개수가 고정된 집합이라 string-array 로 뒀다. 개별 키 7개는 호출부에서 listOf 로 다시 조립해야 해 순서가 어긋날 여지를 남긴다. 수신자 홈의 건수 문장은 rememberCountLine 이 숫자 앞부분과 뒷문장을 서로 다른 스타일로 그려 리소스도 그 경계대로 둘로 나눴다. 끝 공백이 렌더 결과에 유효해 XML 에서 따옴표로 감쌌고, 결합 결과를 단언하는 기존 테스트로 확인했다. 제외 2건은 노출 문자열이 아니다 — TextFieldShort 의 것은 @Preview 인자이고, SaveAfternotePayloadBuilder 의 MEMORIAL_DEFAULT_TITLE 은 서버로 보내는 serviceName 값이라 리소스로 옮기면 로케일에 따라 전송값이 바뀐다. --- .../core/ui/calendar/BottomSheetCalendar.kt | 5 +++-- core/ui/src/main/res/values/strings.xml | 12 +++++++++++ .../author/detail/MemorialDetailScreen.kt | 20 +++++++++++++------ .../author/home/HomeHeaderSection.kt | 6 ++++-- .../shared/detail/song/MemorialPlaylist.kt | 4 ++-- .../src/main/res/values/strings.xml | 11 +++++++++- .../presentation/terms/TermsDetailScreen.kt | 12 +++++------ .../src/main/res/values/strings.xml | 7 +++++++ .../detail/MemorialReceivedDetailScreen.kt | 11 ++++------ .../home/component/AfternoteSection.kt | 4 ++-- .../home/component/MindRecordSection.kt | 5 +++-- .../home/component/TimeLetterSection.kt | 5 +++-- .../src/main/res/values/strings.xml | 8 ++++++++ 13 files changed, 78 insertions(+), 32 deletions(-) diff --git a/core/ui/src/main/kotlin/com/afternote/core/ui/calendar/BottomSheetCalendar.kt b/core/ui/src/main/kotlin/com/afternote/core/ui/calendar/BottomSheetCalendar.kt index 088bfa63c1..7e8a35a25a 100644 --- a/core/ui/src/main/kotlin/com/afternote/core/ui/calendar/BottomSheetCalendar.kt +++ b/core/ui/src/main/kotlin/com/afternote/core/ui/calendar/BottomSheetCalendar.kt @@ -34,6 +34,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringArrayResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.semantics.Role import androidx.compose.ui.semantics.selected @@ -177,7 +178,7 @@ fun DatePickerContent( verticalAlignment = Alignment.CenterVertically, ) { Text( - text = "${currentYear}년 ${currentMonth}월", + text = stringResource(R.string.core_ui_calendar_year_month, currentYear, currentMonth), style = AfternoteDesign.typography.bodySmallR, color = AfternoteDesign.colors.gray9, modifier = Modifier.weight(1f), @@ -240,7 +241,7 @@ fun CalendarGridContent( modifier: Modifier = Modifier, ) { Column(modifier = modifier) { - val dayLabels = listOf("일", "월", "화", "수", "목", "금", "토") + val dayLabels = stringArrayResource(R.array.core_ui_calendar_day_labels) Row(modifier = Modifier.fillMaxWidth()) { dayLabels.forEach { label -> Text( diff --git a/core/ui/src/main/res/values/strings.xml b/core/ui/src/main/res/values/strings.xml index 3673fd97f9..36161cc788 100644 --- a/core/ui/src/main/res/values/strings.xml +++ b/core/ui/src/main/res/values/strings.xml @@ -35,4 +35,16 @@ 다시 시도하기 설정 + + %1$d년 %2$d월 + + 일 + 월 + 화 + 수 + 목 + 금 + 토 + diff --git a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/detail/MemorialDetailScreen.kt b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/detail/MemorialDetailScreen.kt index 3270417ece..c5ce955eff 100644 --- a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/detail/MemorialDetailScreen.kt +++ b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/detail/MemorialDetailScreen.kt @@ -167,15 +167,23 @@ private fun TitleSection( categoryLabel: String, userName: String, ) { + // 프로필 로드 실패·로딩 경합으로 이름이 비어 있으면 이름 세그먼트를 생략해 + // "…에 대한 님의 기록" 렌더를 막는다. + // buildAnnotatedString 람다는 @Composable 이 아니라 stringResource 를 그 안에서 부를 수 없다. + val recordSuffix = + if (userName.isBlank()) { + stringResource(R.string.afternote_detail_record_suffix_anonymous) + } else { + stringResource(R.string.afternote_detail_record_suffix_named, userName) + } + Text( text = buildAnnotatedString { withStyle(style = SpanStyle(color = AfternoteDesign.colors.gray9)) { append(categoryLabel) } - // 프로필 로드 실패·로딩 경합으로 이름이 비어 있으면 이름 세그먼트를 생략해 - // "…에 대한 님의 기록" 렌더를 막는다. - append(if (userName.isBlank()) "에 대한 기록" else "에 대한 ${userName}님의 기록") + append(recordSuffix) }, style = AfternoteDesign.typography.bodyLargeB, ) @@ -247,7 +255,7 @@ private fun VideoCard( content = { Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { Text( - text = "장례식에 남길 영상", + text = stringResource(R.string.afternote_editor_funeral_video_label), style = AfternoteDesign.typography.textField.copy( fontWeight = FontWeight.Medium, @@ -331,7 +339,7 @@ private fun PlaylistCard( content = { Column { Text( - text = "추억 플레이리스트", + text = stringResource(R.string.afternote_editor_playlist_screen_title), style = AfternoteDesign.typography.textField.copy( fontWeight = FontWeight.Medium, @@ -344,7 +352,7 @@ private fun PlaylistCard( } Spacer(Modifier.height(8.dp)) Text( - text = "현재 ${songCount}개의 노래가 담겨 있습니다.", + text = stringResource(R.string.afternote_detail_playlist_song_count, songCount), style = AfternoteDesign.typography.bodySmallR.copy( color = AfternoteDesign.colors.black, diff --git a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/home/HomeHeaderSection.kt b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/home/HomeHeaderSection.kt index 70e0f27c2a..d21f9acc51 100644 --- a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/home/HomeHeaderSection.kt +++ b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/author/home/HomeHeaderSection.kt @@ -14,11 +14,13 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.afternote.core.ui.AfternoteOutlinedCard import com.afternote.core.ui.AfternoteSectionHeader import com.afternote.core.ui.icon.RightArrowIcon import com.afternote.core.ui.theme.AfternoteDesign +import com.afternote.feature.afternote.presentation.R /** * NEXT STEP 카드에 필요한 값 묶음. @@ -52,7 +54,7 @@ internal fun HomeHeaderSection( .padding(horizontal = 25.dp), ) { Text( - text = "애프터노트", + text = stringResource(R.string.afternote_home_title), style = AfternoteDesign.typography.h1, color = AfternoteDesign.colors.gray9, ) @@ -82,7 +84,7 @@ private fun NextStepCard( modifier = modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(4.dp), ) { - AfternoteSectionHeader(title = "NEXT STEP") + AfternoteSectionHeader(title = stringResource(R.string.afternote_home_next_step_section_title)) AfternoteOutlinedCard( onClick = onClick, contentPadding = PaddingValues(start = 16.dp, top = 16.dp, bottom = 16.dp, end = 20.dp), diff --git a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/shared/detail/song/MemorialPlaylist.kt b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/shared/detail/song/MemorialPlaylist.kt index 1cfaf96627..410ec9bf4b 100644 --- a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/shared/detail/song/MemorialPlaylist.kt +++ b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/shared/detail/song/MemorialPlaylist.kt @@ -50,7 +50,7 @@ import com.afternote.feature.afternote.presentation.shared.model.AlbumCover @Composable fun MemorialPlaylist( modifier: Modifier = Modifier, - label: String = "추억 플레이리스트", + label: String = stringResource(R.string.afternote_editor_playlist_screen_title), songCount: Int = 0, albumCovers: List = emptyList(), onCardClick: (() -> Unit)? = null, @@ -133,7 +133,7 @@ private fun MemorialPlaylistCardContent( ) Spacer(modifier = Modifier.size(24.dp)) Text( - text = "현재 ${songCount}개의 노래가 담겨 있습니다.", + text = stringResource(R.string.afternote_detail_playlist_song_count, songCount), style = AfternoteDesign.typography.bodySmallR.copy( color = AfternoteDesign.colors.black, diff --git a/feature/afternote/presentation/src/main/res/values/strings.xml b/feature/afternote/presentation/src/main/res/values/strings.xml index 197bf3a319..214c1857ff 100644 --- a/feature/afternote/presentation/src/main/res/values/strings.xml +++ b/feature/afternote/presentation/src/main/res/values/strings.xml @@ -4,7 +4,7 @@ 홈 기록 타임 레터 - 애프터노트 + 애프터노트 홈 (준비 중) 안녕하세요, %1$s님 @@ -250,4 +250,13 @@ 사진 삭제 영상 삭제 카메라를 사용할 수 없습니다. + + 에 대한 기록 + 에 대한 %1$s님의 기록 + 현재 %1$d개의 노래가 담겨 있습니다. + NEXT STEP + + 故 %1$s님의 애프터노트 + 애프터노트 확인하기 diff --git a/feature/onboarding/presentation/src/main/java/com/afternote/feature/onboarding/presentation/terms/TermsDetailScreen.kt b/feature/onboarding/presentation/src/main/java/com/afternote/feature/onboarding/presentation/terms/TermsDetailScreen.kt index c6bf26f6ba..e77426cac1 100644 --- a/feature/onboarding/presentation/src/main/java/com/afternote/feature/onboarding/presentation/terms/TermsDetailScreen.kt +++ b/feature/onboarding/presentation/src/main/java/com/afternote/feature/onboarding/presentation/terms/TermsDetailScreen.kt @@ -50,27 +50,27 @@ fun TermsDetailScreen( // 각 약관 섹션들 (반복되는 구조는 별도 컴포저블로 분리하여 가독성 확보) TermsSectionText( - title = "1. 서비스 이용약관", + title = stringResource(R.string.onboarding_terms_detail_section_1_title), content = stringResource(R.string.onboarding_terms_detail_section_1), ) TermsSectionText( - title = "2. 개인정보 수집 및 이용 동의", + title = stringResource(R.string.onboarding_terms_detail_section_2_title), content = stringResource(R.string.onboarding_terms_detail_section_2), ) TermsSectionText( - title = "3. 기록 및 콘텐츠 저장에 대한 안내", + title = stringResource(R.string.onboarding_terms_detail_section_3_title), content = stringResource(R.string.onboarding_terms_detail_section_3), ) TermsSectionText( - title = "4. 계정 및 데이터 관리", + title = stringResource(R.string.onboarding_terms_detail_section_4_title), content = stringResource(R.string.onboarding_terms_detail_section_4), ) TermsSectionText( - title = "5. 서비스 변경 및 종료", + title = stringResource(R.string.onboarding_terms_detail_section_5_title), content = stringResource(R.string.onboarding_terms_detail_section_5), ) TermsSectionText( - title = "6. 동의 철회", + title = stringResource(R.string.onboarding_terms_detail_section_6_title), content = stringResource(R.string.onboarding_terms_detail_section_6), ) diff --git a/feature/onboarding/presentation/src/main/res/values/strings.xml b/feature/onboarding/presentation/src/main/res/values/strings.xml index 230695399a..7b7a6d656d 100644 --- a/feature/onboarding/presentation/src/main/res/values/strings.xml +++ b/feature/onboarding/presentation/src/main/res/values/strings.xml @@ -100,4 +100,11 @@ 애프터노트에서의\n프로필을 설정해주세요 이름을 지정해주세요 회원가입 완료 + + 1. 서비스 이용약관 + 2. 개인정보 수집 및 이용 동의 + 3. 기록 및 콘텐츠 저장에 대한 안내 + 4. 계정 및 데이터 관리 + 5. 서비스 변경 및 종료 + 6. 동의 철회 diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/detail/MemorialReceivedDetailScreen.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/detail/MemorialReceivedDetailScreen.kt index 124cfa86ae..190ae118d2 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/detail/MemorialReceivedDetailScreen.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/detail/MemorialReceivedDetailScreen.kt @@ -84,7 +84,7 @@ fun MemorialReceivedDetailScreen( // → 탑바가 상태바(시계·배터리) 밑에서 시작(겹침 방지). 동적 인셋이라 회전·분할화면에도 대응. Column(modifier = Modifier.statusBarsPadding()) { DetailTopBar( - title = "故 ${senderName}님의 애프터노트", + title = stringResource(AfternoteR.string.afternote_receiver_detail_title, senderName), onBackClick = { onBackClick() }, ) } @@ -119,7 +119,6 @@ fun MemorialReceivedDetailScreen( }, playlistContent = { MemorialPlaylist( - label = "추억 플레이리스트", songCount = songCount, albumCovers = albumCovers, onCardClick = onNavigateToPlaylist, @@ -145,7 +144,7 @@ fun MemorialReceivedDetailScreen( Spacer(modifier = Modifier.height(70.dp)) AfternoteButton( - text = "애프터노트 확인하기", + text = stringResource(AfternoteR.string.afternote_receiver_detail_confirm), onClick = onNavigateToFullList, type = AfternoteButtonType.Default, ) @@ -155,8 +154,6 @@ fun MemorialReceivedDetailScreen( } } -private const val LABEL_VIDEO_SECTION = "장례식에 남길 영상" - @Composable private fun ReceiverVideoSection( memorialVideoUrl: String? = null, @@ -185,7 +182,7 @@ private fun ReceiverVideoSection( Toast .makeText( context, - "영상을 재생할 수 있는 앱이 없습니다.", + context.getString(AfternoteR.string.receiver_memorial_video_no_app), Toast.LENGTH_SHORT, ).show() } @@ -267,7 +264,7 @@ private fun ReceiverMemorialVideoThumbnail(thumbnailUrl: String?) { } @Composable -private fun ReceiverSectionHeader(title: String = LABEL_VIDEO_SECTION) { +private fun ReceiverSectionHeader(title: String = stringResource(AfternoteR.string.afternote_editor_funeral_video_label)) { Text( text = title, style = diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/AfternoteSection.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/AfternoteSection.kt index 7ef83765c3..fe1d8b69de 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/AfternoteSection.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/AfternoteSection.kt @@ -45,8 +45,8 @@ fun AfternoteSection( description = stringResource(R.string.receiver_home_afternote_section_desc), countLine = rememberCountLine( - prefix = "${countText(totalCount)}개", - suffix = "의 애프터노트가 있습니다.", + prefix = stringResource(R.string.receiver_home_afternote_count_prefix, countText(totalCount)), + suffix = stringResource(R.string.receiver_home_afternote_count_suffix), ), buttonText = stringResource(R.string.receiver_home_afternote_section_button), onButtonClick = onGoClick, diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/MindRecordSection.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/MindRecordSection.kt index 266d778521..bdbb94fad2 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/MindRecordSection.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/MindRecordSection.kt @@ -29,8 +29,9 @@ fun MindRecordSection( description = stringResource(R.string.receiver_home_mindrecord_section_desc), countLine = rememberCountLine( - prefix = "${countText(summary?.totalCount)}개 ", - suffix = "마음의 기록이 있습니다.", + prefix = + stringResource(R.string.receiver_home_mindrecord_count_prefix, countText(summary?.totalCount)), + suffix = stringResource(R.string.receiver_home_mindrecord_count_suffix), ), buttonText = stringResource(R.string.receiver_home_mindrecord_section_button), onButtonClick = onGoClick, diff --git a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/TimeLetterSection.kt b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/TimeLetterSection.kt index 52243a6d0a..e8e8174962 100644 --- a/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/TimeLetterSection.kt +++ b/feature/receiver/presentation/src/main/kotlin/com/afternote/feature/receiver/presentation/home/component/TimeLetterSection.kt @@ -18,8 +18,9 @@ fun TimeLetterSection( description = stringResource(R.string.receiver_home_timeletter_section_desc), countLine = rememberCountLine( - prefix = "${countText(totalCount)}개 ", - suffix = "라이프 이벤트 레터가 있습니다.", + prefix = + stringResource(R.string.receiver_home_timeletter_count_prefix, countText(totalCount)), + suffix = stringResource(R.string.receiver_home_timeletter_count_suffix), ), buttonText = stringResource(R.string.receiver_home_timeletter_section_button), onButtonClick = onGoClick, diff --git a/feature/receiver/presentation/src/main/res/values/strings.xml b/feature/receiver/presentation/src/main/res/values/strings.xml index e9d40279c9..0e7147b853 100644 --- a/feature/receiver/presentation/src/main/res/values/strings.xml +++ b/feature/receiver/presentation/src/main/res/values/strings.xml @@ -129,4 +129,12 @@ 제출하신 서류를 확인 중입니다.\n빠르게 검토하여 열람하실 수 있도록 안내드리겠습니다. 받은 기록함으로 돌아가기 수신자 인증 진행도 4단계 중 %1$d단계 + + "%1$s개 " + 마음의 기록이 있습니다. + "%1$s개 " + 라이프 이벤트 레터가 있습니다. + %1$s개 + 의 애프터노트가 있습니다. From 9fe9b1890d1a746e9e9b27d18c7921fdefe0fd47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=BC=ED=98=81?= Date: Sat, 29 Aug 2026 19:53:08 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix(afternote):=20=EB=9E=8C=EB=8B=A4=20?= =?UTF-8?q?=EB=B0=96=EC=9C=BC=EB=A1=9C=20=EB=AC=B8=EC=9E=90=EC=97=B4=20?= =?UTF-8?q?=EB=A6=AC=EC=86=8C=EC=8A=A4=EB=A5=BC=20=EC=98=AC=EB=A0=A4=20Lin?= =?UTF-8?q?t=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EC=86=8C=20(#1469)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../receiver/detail/MemorialReceivedDetailScreen.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/receiver/detail/MemorialReceivedDetailScreen.kt b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/receiver/detail/MemorialReceivedDetailScreen.kt index 0fbd86f478..c3ab2d23e6 100644 --- a/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/receiver/detail/MemorialReceivedDetailScreen.kt +++ b/feature/afternote/presentation/src/main/kotlin/com/afternote/feature/afternote/presentation/receiver/detail/MemorialReceivedDetailScreen.kt @@ -159,6 +159,7 @@ private fun ReceiverVideoSection( memorialThumbnailUrl: String? = null, ) { val context = LocalContext.current + val noVideoAppMessage = stringResource(R.string.receiver_memorial_video_no_app) Column(modifier = Modifier.fillMaxWidth()) { ReceiverSectionHeader() Spacer(modifier = Modifier.height(12.dp)) @@ -181,7 +182,7 @@ private fun ReceiverVideoSection( Toast .makeText( context, - context.getString(R.string.receiver_memorial_video_no_app), + noVideoAppMessage, Toast.LENGTH_SHORT, ).show() }