From 7307e5b25542efb7f5d21de27166b4427b6059fd Mon Sep 17 00:00:00 2001 From: Yu Sung Date: Fri, 19 Dec 2025 23:31:14 +0900 Subject: [PATCH] =?UTF-8?q?=EB=A9=94=EC=8B=9C=EC=A7=80=20=ED=98=84?= =?UTF-8?q?=EC=A7=80=ED=99=94=EC=99=80=20=EC=A2=85=EB=A3=8C=20=EB=9D=BC?= =?UTF-8?q?=EC=9D=B4=EB=B8=8C=20=EB=82=A0=EC=A7=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 문자 메시지 화면에 새 현지화 문구를 추가한다. --- SodaLive/Resources/Localizable.xcstrings | 128 +++++++++++------- SodaLive/Sources/I18n/I18n.swift | 39 ++++++ SodaLive/Sources/Message/MessageView.swift | 2 +- .../SelectRecipient/SelectRecipientView.swift | 2 +- .../Message/Text/TextMessageViewModel.swift | 26 ++-- .../Voice/Write/VoiceMessageWriteView.swift | 2 +- 6 files changed, 135 insertions(+), 64 deletions(-) diff --git a/SodaLive/Resources/Localizable.xcstrings b/SodaLive/Resources/Localizable.xcstrings index 109f7da..0de2a8d 100644 --- a/SodaLive/Resources/Localizable.xcstrings +++ b/SodaLive/Resources/Localizable.xcstrings @@ -4008,6 +4008,22 @@ } } }, + "메시지" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Message" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "メッセージ" + } + } + } + }, "메시지 보관" : { "localizations" : { "en" : { @@ -4104,22 +4120,6 @@ } } }, - "모든 기기에서 로그아웃" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Log out from all devices" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "すべての端末でログアウト" - } - } - } - }, "목" : { "localizations" : { "en" : { @@ -4136,6 +4136,22 @@ } } }, + "모든 기기에서 로그아웃" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Log out from all devices" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "すべての端末でログアウト" + } + } + } + }, "모집완료" : { "localizations" : { "en" : { @@ -4360,6 +4376,22 @@ } } }, + "받는 사람 검색" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search recipient" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "受信者を検索" + } + } + } + }, "받은 메시지" : { "localizations" : { "en" : { @@ -6856,6 +6888,38 @@ } } }, + "이용약관" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Terms of service" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "利用規約" + } + } + } + }, + "일" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sun" + } + }, + "ja" : { + "stringUnit" : { + "state" : "translated", + "value" : "日" + } + } + } + }, "이메일" : { "localizations" : { "en" : { @@ -6952,22 +7016,6 @@ } } }, - "이용약관" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Terms of service" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "利用規約" - } - } - } - }, "이전화" : { "localizations" : { "en" : { @@ -7112,22 +7160,6 @@ } } }, - "일" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Sun" - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "日" - } - } - } - }, "일간 랭킹" : { "localizations" : { "en" : { diff --git a/SodaLive/Sources/I18n/I18n.swift b/SodaLive/Sources/I18n/I18n.swift index 82ab38d..5fdefbe 100644 --- a/SodaLive/Sources/I18n/I18n.swift +++ b/SodaLive/Sources/I18n/I18n.swift @@ -713,6 +713,45 @@ enum I18n { ) } } + + // 문자 메시지(Text Message) 관련 문자열 + enum TextMessage { + // 전송 버튼 라벨 + static var send: String { + pick(ko: "메시지 보내기", en: "Send message", ja: "メッセージを送る") + } + + // 입력창 플레이스홀더 + static var placeholder: String { + pick(ko: "내용을 입력해 주세요.", en: "Please enter your message.", ja: "内容を入力してください。") + } + + // 수신자 입력 플레이스홀더 + static var recipientPlaceholder: String { + pick(ko: "받는 사람", en: "Recipient", ja: "受信者") + } + + // 수신자 미선택 오류 + static var selectRecipient: String { + pick(ko: "받는 사람을 선택해 주세요.", en: "Please select a recipient.", ja: "受信者を選択してください。") + } + + // 전송 성공 토스트/팝업 문구 + static var sendSuccess: String { + pick(ko: "메시지 전송이 완료되었습니다.", en: "Your message has been sent.", ja: "メッセージの送信が完了しました。") + } + + enum Validation { + // 최소 글자 수 안내 + static func minLength(_ count: Int) -> String { + pick( + ko: "\(count)글자 이상 입력해 주세요.", + en: "Please enter at least \(count) characters.", + ja: "\(count)文字以上で入力してください。" + ) + } + } + } } // MARK: - 내부 헬퍼 diff --git a/SodaLive/Sources/Message/MessageView.swift b/SodaLive/Sources/Message/MessageView.swift index 7bad883..43559ac 100644 --- a/SodaLive/Sources/Message/MessageView.swift +++ b/SodaLive/Sources/Message/MessageView.swift @@ -17,7 +17,7 @@ struct MessageView: View { Color.black VStack { - DetailNavigationBar(title: "메시지") + DetailNavigationBar(title: String(localized: "메시지")) Tab() diff --git a/SodaLive/Sources/Message/Text/SelectRecipient/SelectRecipientView.swift b/SodaLive/Sources/Message/Text/SelectRecipient/SelectRecipientView.swift index 9e9b363..bebb01e 100644 --- a/SodaLive/Sources/Message/Text/SelectRecipient/SelectRecipientView.swift +++ b/SodaLive/Sources/Message/Text/SelectRecipient/SelectRecipientView.swift @@ -18,7 +18,7 @@ struct SelectRecipientView: View { var body: some View { BaseView { VStack(spacing: 20) { - DetailNavigationBar(title: "받는 사람 검색") { + DetailNavigationBar(title: String(localized: "받는 사람 검색")) { isShowing = false } diff --git a/SodaLive/Sources/Message/Text/TextMessageViewModel.swift b/SodaLive/Sources/Message/Text/TextMessageViewModel.swift index b582cc5..95a6baf 100644 --- a/SodaLive/Sources/Message/Text/TextMessageViewModel.swift +++ b/SodaLive/Sources/Message/Text/TextMessageViewModel.swift @@ -40,9 +40,9 @@ final class TextMessageViewModel: ObservableObject { @Published var recipientNickname: String = "" @Published var recipientId = 0 - @Published var sendText = "메시지 보내기" + @Published var sendText = I18n.TextMessage.send - let placeholder = "내용을 입력해 주세요." + let placeholder = I18n.TextMessage.placeholder var isLast = false var page = 1 @@ -51,13 +51,13 @@ final class TextMessageViewModel: ObservableObject { func write() { let textMessage = message.trimmingCharacters(in: .whitespacesAndNewlines) != placeholder ? message : "" if recipientId <= 0 { - errorMessage = "받는 사람을 선택해 주세요." + errorMessage = I18n.TextMessage.selectRecipient isShowPopup = true return } if textMessage.count < 10 { - errorMessage = "10글자 이상 입력해 주세요." + errorMessage = I18n.TextMessage.Validation.minLength(10) isShowPopup = true return } @@ -82,7 +82,7 @@ final class TextMessageViewModel: ObservableObject { let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData) if decoded.success { - self.errorMessage = "메시지 전송이 완료되었습니다." + self.errorMessage = I18n.TextMessage.sendSuccess self.isShowPopup = true DispatchQueue.main.asyncAfter(deadline: .now() + 1) { AppState.shared.back() @@ -91,13 +91,13 @@ final class TextMessageViewModel: ObservableObject { if let message = decoded.message { self.errorMessage = message } else { - self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + self.errorMessage = I18n.Common.commonError } self.isShowPopup = true } } catch { - self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + self.errorMessage = I18n.Common.commonError self.isShowPopup = true } } @@ -140,13 +140,13 @@ final class TextMessageViewModel: ObservableObject { if let message = decoded.message { self.errorMessage = message } else { - self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + self.errorMessage = I18n.Common.commonError } self.isShowPopup = true } } catch { - self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + self.errorMessage = I18n.Common.commonError self.isShowPopup = true } } @@ -188,13 +188,13 @@ final class TextMessageViewModel: ObservableObject { if let message = decoded.message { self.errorMessage = message } else { - self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + self.errorMessage = I18n.Common.commonError } self.isShowPopup = true } } catch { - self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + self.errorMessage = I18n.Common.commonError self.isShowPopup = true } } @@ -236,13 +236,13 @@ final class TextMessageViewModel: ObservableObject { if let message = decoded.message { self.errorMessage = message } else { - self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + self.errorMessage = I18n.Common.commonError } self.isShowPopup = true } } catch { - self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." + self.errorMessage = I18n.Common.commonError self.isShowPopup = true } } diff --git a/SodaLive/Sources/Message/Voice/Write/VoiceMessageWriteView.swift b/SodaLive/Sources/Message/Voice/Write/VoiceMessageWriteView.swift index 01b93ea..bbbf73e 100644 --- a/SodaLive/Sources/Message/Voice/Write/VoiceMessageWriteView.swift +++ b/SodaLive/Sources/Message/Voice/Write/VoiceMessageWriteView.swift @@ -64,7 +64,7 @@ struct VoiceMessageWriteView: View { Text( viewModel.recipientNickname.count > 0 ? viewModel.recipientNickname : - "받는 사람" + I18n.TextMessage.recipientPlaceholder ) .font( .custom(