다이얼로그 문구를 공통 번역으로 제공

콘텐츠, 라이브, 스플래시 화면의 안내 문구를
공통 번역 키로 제공해 지역화 품질을 개선한다
This commit is contained in:
Yu Sung
2025-12-29 16:44:55 +09:00
parent 64bb5668f4
commit 19380ccc70
18 changed files with 224 additions and 90 deletions

View File

@@ -54,14 +54,14 @@ final class CharacterDetailViewModel: ObservableObject {
if let message = decoded.message { if let message = decoded.message {
self?.errorMessage = message self?.errorMessage = message
} else { } else {
self?.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self?.errorMessage = I18n.Common.commonError
} }
self?.isShowPopup = true self?.isShowPopup = true
} }
} catch { } catch {
ERROR_LOG(String(describing: error)) ERROR_LOG(String(describing: error))
self?.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self?.errorMessage = I18n.Common.commonError
self?.isShowPopup = true self?.isShowPopup = true
} }
} }
@@ -94,14 +94,14 @@ final class CharacterDetailViewModel: ObservableObject {
if let message = decoded.message { if let message = decoded.message {
self?.errorMessage = message self?.errorMessage = message
} else { } else {
self?.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self?.errorMessage = I18n.Common.commonError
} }
self?.isShowPopup = true self?.isShowPopup = true
} }
} catch { } catch {
ERROR_LOG(String(describing: error)) ERROR_LOG(String(describing: error))
self?.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self?.errorMessage = I18n.Common.commonError
self?.isShowPopup = true self?.isShowPopup = true
} }
} }

View File

@@ -78,11 +78,11 @@ struct CharacterDetailGalleryView: View {
.overlay { .overlay {
if viewModel.isShowPurchaseDialog { if viewModel.isShowPurchaseDialog {
SodaDialog( SodaDialog(
title: "구매 확인", title: I18n.CharacterDetailGallery.purchaseConfirmTitle,
desc: "선택한 이미지를 구매하시겠습니까?", desc: I18n.CharacterDetailGallery.purchaseConfirmDescription,
confirmButtonTitle: viewModel.selectedItemPrice, confirmButtonTitle: viewModel.selectedItemPrice,
confirmButtonAction: viewModel.onPurchaseConfirm, confirmButtonAction: viewModel.onPurchaseConfirm,
cancelButtonTitle: "취소", cancelButtonTitle: I18n.Common.cancel,
cancelButtonAction: viewModel.onPurchaseCancel cancelButtonAction: viewModel.onPurchaseCancel
) )
} }

View File

@@ -44,7 +44,7 @@ final class CharacterDetailGalleryViewModel: ObservableObject {
} }
var selectedItemPrice: String { var selectedItemPrice: String {
return "\(selectedItem?.imagePriceCan ?? 0)캔으로 구매" return I18n.CharacterDetailGallery.purchaseWithCans(selectedItem?.imagePriceCan ?? 0)
} }
// MARK: - Public Methods // MARK: - Public Methods
@@ -112,7 +112,7 @@ final class CharacterDetailGalleryViewModel: ObservableObject {
if let message = decoded.message { if let message = decoded.message {
self.errorMessage = message self.errorMessage = message
} else { } else {
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.errorMessage = I18n.Common.commonError
} }
self.isShowPopup = true self.isShowPopup = true
@@ -124,7 +124,7 @@ final class CharacterDetailGalleryViewModel: ObservableObject {
self.selectedImageIndex = 0 self.selectedImageIndex = 0
self.selectedItem = nil self.selectedItem = nil
ERROR_LOG(String(describing: error)) ERROR_LOG(String(describing: error))
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.errorMessage = I18n.Common.commonError
self.isShowPopup = true self.isShowPopup = true
} }
} }
@@ -172,14 +172,14 @@ final class CharacterDetailGalleryViewModel: ObservableObject {
if let message = decoded.message { if let message = decoded.message {
self?.errorMessage = message self?.errorMessage = message
} else { } else {
self?.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self?.errorMessage = I18n.Common.commonError
} }
self?.isShowPopup = true self?.isShowPopup = true
} }
} catch { } catch {
ERROR_LOG(String(describing: error)) ERROR_LOG(String(describing: error))
self?.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self?.errorMessage = I18n.Common.commonError
self?.isShowPopup = true self?.isShowPopup = true
} }
} }
@@ -219,14 +219,14 @@ final class CharacterDetailGalleryViewModel: ObservableObject {
if let message = decoded.message { if let message = decoded.message {
self?.errorMessage = message self?.errorMessage = message
} else { } else {
self?.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self?.errorMessage = I18n.Common.commonError
} }
self?.isShowPopup = true self?.isShowPopup = true
} }
} catch { } catch {
ERROR_LOG(String(describing: error)) ERROR_LOG(String(describing: error))
self?.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self?.errorMessage = I18n.Common.commonError
self?.isShowPopup = true self?.isShowPopup = true
} }
} }

View File

@@ -637,11 +637,9 @@ struct ContentCreateView: View {
if viewModel.isShowCompletePopup { if viewModel.isShowCompletePopup {
SodaDialog( SodaDialog(
title: "콘텐츠 업로드", title: I18n.CreateContent.uploadTitle,
desc: "등록한 콘텐츠가 업로드 중입니다.\n" + desc: I18n.CreateContent.uploadDescription,
"콘텐츠 등록이 완료되면 알림을 보내드립니다.\n" + confirmButtonTitle: I18n.Common.confirm,
"이 페이지를 나가도 콘텐츠는 자동으로 등록됩니다.",
confirmButtonTitle: "확인",
confirmButtonAction: { AppState.shared.back() }, confirmButtonAction: { AppState.shared.back() },
cancelButtonTitle: "", cancelButtonTitle: "",
cancelButtonAction: {} cancelButtonAction: {}

View File

@@ -160,15 +160,15 @@ struct AudioContentCommentListView: View {
if isShowDeletePopup && commentId > 0 { if isShowDeletePopup && commentId > 0 {
SodaDialog( SodaDialog(
title: "댓글 삭제", title: I18n.Common.commentDeleteTitle,
desc: "삭제하시겠습니까?", desc: I18n.Common.confirmDeleteQuestion,
confirmButtonTitle: "삭제", confirmButtonTitle: I18n.Common.delete,
confirmButtonAction: { confirmButtonAction: {
viewModel.modifyComment(commentId: commentId, audioContentId: audioContentId, isActive: false) viewModel.modifyComment(commentId: commentId, audioContentId: audioContentId, isActive: false)
commentId = 0 commentId = 0
isShowDeletePopup = false isShowDeletePopup = false
}, },
cancelButtonTitle: "취소", cancelButtonTitle: I18n.Common.cancel,
cancelButtonAction: { cancelButtonAction: {
commentId = 0 commentId = 0
isShowDeletePopup = false isShowDeletePopup = false

View File

@@ -150,15 +150,15 @@ struct AudioContentListReplyView: View {
if isShowDeletePopup && commentId > 0 { if isShowDeletePopup && commentId > 0 {
SodaDialog( SodaDialog(
title: "댓글 삭제", title: I18n.Common.commentDeleteTitle,
desc: "삭제하시겠습니까?", desc: I18n.Common.confirmDeleteQuestion,
confirmButtonTitle: "삭제", confirmButtonTitle: I18n.Common.delete,
confirmButtonAction: { confirmButtonAction: {
viewModel.modifyComment(commentId: commentId, audioContentId: audioContentId, isActive: false) viewModel.modifyComment(commentId: commentId, audioContentId: audioContentId, isActive: false)
commentId = 0 commentId = 0
isShowDeletePopup = false isShowDeletePopup = false
}, },
cancelButtonTitle: "취소", cancelButtonTitle: I18n.Common.cancel,
cancelButtonAction: { cancelButtonAction: {
commentId = 0 commentId = 0
isShowDeletePopup = false isShowDeletePopup = false

View File

@@ -364,16 +364,14 @@ struct ContentDetailView: View {
if viewModel.isShowNoticePinContentPopup { if viewModel.isShowNoticePinContentPopup {
SodaDialog( SodaDialog(
title: "고정 한도 도달", title: I18n.ContentDetail.pinLimitTitle,
desc: "이 콘텐츠를 고정하시겠어요? " + desc: I18n.ContentDetail.pinLimitDesc,
"채널에 콘텐츠를 최대 3개까지 고정할 수 있습니다." + confirmButtonTitle: I18n.Common.confirm,
"이 콘텐츠를 고정하면 가장 오래된 콘텐츠가 대체됩니다.",
confirmButtonTitle: "확인",
confirmButtonAction: { confirmButtonAction: {
viewModel.isShowNoticePinContentPopup = false viewModel.isShowNoticePinContentPopup = false
viewModel.pinContent(contentId: contentId) viewModel.pinContent(contentId: contentId)
}, },
cancelButtonTitle: "취소", cancelButtonTitle: I18n.Common.cancel,
cancelButtonAction: { cancelButtonAction: {
viewModel.isShowNoticePinContentPopup = false viewModel.isShowNoticePinContentPopup = false
} }

View File

@@ -297,9 +297,11 @@ struct ContentPlaylistDetailView: View {
.onTapGesture { isShowDeleteConfirm = false } .onTapGesture { isShowDeleteConfirm = false }
SodaDialog( SodaDialog(
title: "재생 목록 삭제", title: I18n.Playlist.deleteTitle,
desc: viewModel.response != nil ? "\(viewModel.response!.title)을 삭제하시겠습니까?" : "삭제하시겠습니까?", desc: viewModel.response != nil ?
confirmButtonTitle: "삭제", I18n.Playlist.deleteQuestion(viewModel.response!.title) :
I18n.Common.confirmDeleteQuestion,
confirmButtonTitle: I18n.Common.delete,
confirmButtonAction: { confirmButtonAction: {
isShowDeleteConfirm = false isShowDeleteConfirm = false
viewModel.deletePlaylist { viewModel.deletePlaylist {
@@ -307,7 +309,7 @@ struct ContentPlaylistDetailView: View {
isShowing = false isShowing = false
} }
}, },
cancelButtonTitle: "취소", cancelButtonTitle: I18n.Common.cancel,
cancelButtonAction: { isShowDeleteConfirm = false } cancelButtonAction: { isShowDeleteConfirm = false }
) )
} }

View File

@@ -278,9 +278,9 @@ struct ContentView: View {
if isShowDialog { if isShowDialog {
SodaDialog( SodaDialog(
title: "포인트 지급", title: I18n.Common.pointGrantTitle,
desc: message, desc: message,
confirmButtonTitle: "확인" confirmButtonTitle: I18n.Common.confirm
) { ) {
isShowDialog = false isShowDialog = false
message = "" message = ""

View File

@@ -161,15 +161,15 @@ struct CreatorCommunityCommentListView: View {
if isShowDeletePopup && commentId > 0 { if isShowDeletePopup && commentId > 0 {
SodaDialog( SodaDialog(
title: "댓글 삭제", title: I18n.Common.commentDeleteTitle,
desc: "삭제하시겠습니까?", desc: I18n.Common.confirmDeleteQuestion,
confirmButtonTitle: "삭제", confirmButtonTitle: I18n.Common.delete,
confirmButtonAction: { confirmButtonAction: {
viewModel.modifyComment(commentId: commentId, postId: postId, isActive: false) viewModel.modifyComment(commentId: commentId, postId: postId, isActive: false)
commentId = 0 commentId = 0
isShowDeletePopup = false isShowDeletePopup = false
}, },
cancelButtonTitle: "취소", cancelButtonTitle: I18n.Common.cancel,
cancelButtonAction: { cancelButtonAction: {
commentId = 0 commentId = 0
isShowDeletePopup = false isShowDeletePopup = false

View File

@@ -149,15 +149,15 @@ struct CreatorCommunityCommentReplyView: View {
if isShowDeletePopup && commentId > 0 { if isShowDeletePopup && commentId > 0 {
SodaDialog( SodaDialog(
title: "댓글 삭제", title: I18n.Common.commentDeleteTitle,
desc: "삭제하시겠습니까?", desc: I18n.Common.confirmDeleteQuestion,
confirmButtonTitle: "삭제", confirmButtonTitle: I18n.Common.delete,
confirmButtonAction: { confirmButtonAction: {
viewModel.modifyComment(commentId: commentId, postId: postId, isActive: false) viewModel.modifyComment(commentId: commentId, postId: postId, isActive: false)
commentId = 0 commentId = 0
isShowDeletePopup = false isShowDeletePopup = false
}, },
cancelButtonTitle: "취소", cancelButtonTitle: I18n.Common.cancel,
cancelButtonAction: { cancelButtonAction: {
commentId = 0 commentId = 0
isShowDeletePopup = false isShowDeletePopup = false

View File

@@ -117,14 +117,14 @@ struct CreatorCommunityAllView: View {
if viewModel.isShowDeleteConfirm { if viewModel.isShowDeleteConfirm {
SodaDialog( SodaDialog(
title: "게시물 삭제", title: I18n.Common.postDeleteTitle,
desc: "삭제하시겠습니까?", desc: I18n.Common.confirmDeleteQuestion,
confirmButtonTitle: "삭제", confirmButtonTitle: I18n.Common.delete,
confirmButtonAction: { confirmButtonAction: {
viewModel.deleteCommunityPost() viewModel.deleteCommunityPost()
viewModel.isShowDeleteConfirm = false viewModel.isShowDeleteConfirm = false
}, },
cancelButtonTitle: "취소", cancelButtonTitle: I18n.Common.cancel,
cancelButtonAction: { cancelButtonAction: {
viewModel.isShowDeleteConfirm = false viewModel.isShowDeleteConfirm = false
} }

View File

@@ -165,15 +165,15 @@ struct UserProfileFanTalkAllView: View {
if viewModel.isShowCheersDeleteView { if viewModel.isShowCheersDeleteView {
if viewModel.isShowCheersDeleteView { if viewModel.isShowCheersDeleteView {
SodaDialog( SodaDialog(
title: "응원글 삭제", title: I18n.MemberChannel.cheersDeleteTitle,
desc: "삭제하시겠습니까?", desc: I18n.Common.confirmDeleteQuestion,
confirmButtonTitle: "삭제", confirmButtonTitle: I18n.Common.delete,
confirmButtonAction: { confirmButtonAction: {
viewModel.modifyCheers(cheersId: cheersId, creatorId: userId, isActive: false) viewModel.modifyCheers(cheersId: cheersId, creatorId: userId, isActive: false)
viewModel.isShowCheersDeleteView = false viewModel.isShowCheersDeleteView = false
self.cheersId = 0 self.cheersId = 0
}, },
cancelButtonTitle: "취소", cancelButtonTitle: I18n.Common.cancel,
cancelButtonAction: { viewModel.isShowCheersDeleteView = false } cancelButtonAction: { viewModel.isShowCheersDeleteView = false }
) )
} }

View File

@@ -78,6 +78,43 @@ enum I18n {
ja: "このテーマの他のコンテンツ" ja: "このテーマの他のコンテンツ"
) )
} }
static var pinLimitTitle: String {
pick(
ko: "고정 한도 도달",
en: "Pin limit reached",
ja: "固定上限に到達"
)
}
static var pinLimitDesc: String {
pick(
ko: "이 콘텐츠를 고정하시겠어요? 채널에 콘텐츠를 최대 3개까지 고정할 수 있습니다. 이 콘텐츠를 고정하면 가장 오래된 콘텐츠가 대체됩니다.",
en: "Do you want to pin this content? You can pin up to 3 contents in a channel. Pinning this will replace the oldest pinned content.",
ja: "このコンテンツを固定しますかチャンネルには最大3件まで固定できます。このコンテンツを固定すると最も古い固定コンテンツが置き換えられます。"
)
}
}
enum CharacterDetailGallery {
static var purchaseConfirmTitle: String {
pick(ko: "구매 확인", en: "Purchase confirmation", ja: "購入確認")
}
static var purchaseConfirmDescription: String {
pick(
ko: "선택한 이미지를 구매하시겠습니까?",
en: "Do you want to purchase the selected image?",
ja: "選択した画像を購入しますか?"
)
}
static func purchaseWithCans(_ cans: Int) -> String {
pick(
ko: "\(cans)캔으로 구매",
en: "Purchase for \(cans) cans",
ja: "\(cans)CANで購入"
)
}
} }
enum Time { enum Time {
static var justNow: String { static var justNow: String {
@@ -131,11 +168,18 @@ enum I18n {
static var apply: String { pick(ko: "적용", en: "Apply", ja: "適用") } static var apply: String { pick(ko: "적용", en: "Apply", ja: "適用") }
static var confirm: String { pick(ko: "확인", en: "Confirm", ja: "確認") } static var confirm: String { pick(ko: "확인", en: "Confirm", ja: "確認") }
static var cancel: String { pick(ko: "취소", en: "Cancel", ja: "キャンセル") } static var cancel: String { pick(ko: "취소", en: "Cancel", ja: "キャンセル") }
static var yes: String { pick(ko: "", en: "Yes", ja: "はい") }
static var no: String { pick(ko: "아니오", en: "No", ja: "いいえ") }
// / // /
static var delete: String { pick(ko: "삭제", en: "Delete", ja: "削除") } static var delete: String { pick(ko: "삭제", en: "Delete", ja: "削除") }
static var commentDeleteTitle: String { pick(ko: "댓글 삭제", en: "Delete comment", ja: "コメントを削除") }
static var postDeleteTitle: String { pick(ko: "게시물 삭제", en: "Delete post", ja: "投稿を削除") }
// //
static var settings: String { pick(ko: "설정", en: "Settings", ja: "設定") } static var settings: String { pick(ko: "설정", en: "Settings", ja: "設定") }
static var alertTitle: String { pick(ko: "알림", en: "Notice", ja: "お知らせ") }
static var noticeTitle: String { pick(ko: "안내", en: "Notice", ja: "お知らせ") }
static var pointGrantTitle: String { pick(ko: "포인트 지급", en: "Points granted", ja: "ポイント付与") }
static var commonError: String { pick(ko: "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다.", en: "Please try again.\nIf the problem persists, please contact customer support.", ja: "恐れ入りますが再度お試しください。\n問題が続く場合はカスタマーセンターにお問い合わせください。") } static var commonError: String { pick(ko: "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다.", en: "Please try again.\nIf the problem persists, please contact customer support.", ja: "恐れ入りますが再度お試しください。\n問題が続く場合はカスタマーセンターにお問い合わせください。") }
@@ -151,6 +195,48 @@ enum I18n {
static var points: String { pick(ko: "포인트", en: "Points", ja: "ポイント") } static var points: String { pick(ko: "포인트", en: "Points", ja: "ポイント") }
} }
enum Splash {
static var maintenanceTitle: String {
pick(ko: "안내", en: "Notice", ja: "お知らせ")
}
static var maintenanceDesc: String {
pick(
ko: "서비스 점검중입니다.",
en: "The service is under maintenance.",
ja: "ただいまメンテナンス中です。"
)
}
static var updateTitle: String {
pick(ko: "업데이트", en: "Update", ja: "アップデート")
}
static var updateDesc: String {
pick(
ko: "최신 업데이트가 있습니다.\n업데이트 하시겠습니까?",
en: "A new update is available.\nWould you like to update now?",
ja: "最新のアップデートがあります。\nアップデートしますか?"
)
}
static var updateConfirm: String {
pick(ko: "업데이트", en: "Update", ja: "アップデート")
}
static var updateCancel: String {
pick(ko: "다음에", en: "Later", ja: "あとで")
}
static var forcedUpdateDesc: String {
pick(
ko: "필수 업데이트가 있습니다.\n업데이트 후 사용가능합니다.",
en: "A required update is available.\nPlease update to continue.",
ja: "必須アップデートがあります。\nアップデート後に利用できます。"
)
}
}
// Settings // Settings
// > (SignOut) // > (SignOut)
@@ -460,10 +546,51 @@ enum I18n {
static var enterPassword6: String { pick(ko: "방 입장 비밀번호 6자리를 입력해 주세요.", en: "Please enter a 6-digit room entry password.", ja: "入室パスワード6桁を入力してください。") } static var enterPassword6: String { pick(ko: "방 입장 비밀번호 6자리를 입력해 주세요.", en: "Please enter a 6-digit room entry password.", ja: "入室パスワード6桁を入力してください。") }
} }
enum LiveRoom {
static var ageRestrictionDesc: String {
pick(
ko: "지금 참여하던 라이브는 '19세 이상' 연령제한이 설정되어 정보통신망 이용촉진 및 정보 보호 등에 관한 법률 및 청소년 보호법의 규정에 의해 만 19세 미만의 청소년은 이용할 수 없습니다.\n마이페이지에서 본인인증 후 다시 이용하시기 바랍니다.",
en: "The live you were joining has been set to '19+' and, under applicable laws, minors under 19 cannot use it.\nPlease verify your identity in My Page and try again.",
ja: "参加中のライブは「19歳以上」に設定されており、関連法令により19歳未満の方はご利用いただけません。\nマイページで本人認証後、再度お試しください。"
)
}
static var likeHeartNoticeDesc: String {
pick(
ko: "'좋아해요'는 유료 후원입니다.\n클릭시 1캔이 소진됩니다.",
en: "'Like' is a paid donation.\nClicking consumes 1 can.",
ja: "「좋아요」は有料の支援です。\nクリックすると1缶消費されます。"
)
}
static var quitTitle: String { pick(ko: "라이브 나가기", en: "Leave live", ja: "ライブを退出") }
static var quitDesc: String { pick(ko: "라이브에서 나가시겠습니까?", en: "Do you want to leave the live?", ja: "ライブから退出しますか?") }
static var endTitle: String { pick(ko: "라이브 종료", en: "End live", ja: "ライブ終了") }
static var endDesc: String {
pick(
ko: "라이브를 종료하시겠습니까?\n라이브를 종료하면 대화내용은\n저장되지 않고 사라집니다.\n참여자들 또한 라이브가 종료되어\n강제퇴장 됩니다.",
en: "Do you want to end the live?\nEnding the live will erase the chat history.\nParticipants will also be removed.",
ja: "ライブを終了しますか?\nライブを終了すると会話内容は保存されず消去されます。\n参加者も終了に伴い強制退場となります。"
)
}
static var kickOutTitle: String { pick(ko: "내보내기", en: "Kick out", ja: "退場させる") }
static var kickOutConfirm: String { pick(ko: "내보내기", en: "Kick out", ja: "退場させる") }
}
enum CreateContent { enum CreateContent {
static var selectFile: String { pick(ko: "파일 선택", en: "Select file", ja: "ファイル選択") } static var selectFile: String { pick(ko: "파일 선택", en: "Select file", ja: "ファイル選択") }
static var selectTheme: String { pick(ko: "테마 선택", en: "Select theme", ja: "テーマを選択") } static var selectTheme: String { pick(ko: "테마 선택", en: "Select theme", ja: "テーマを選択") }
static var uploadContentDescriptionHint: String { pick(ko: "내용을 입력하세요", en: "Enter a description", ja: "内容を入力してください") } static var uploadContentDescriptionHint: String { pick(ko: "내용을 입력하세요", en: "Enter a description", ja: "内容を入力してください") }
static var uploadTitle: String { pick(ko: "콘텐츠 업로드", en: "Content upload", ja: "コンテンツのアップロード") }
static var uploadDescription: String {
pick(
ko: "등록한 콘텐츠가 업로드 중입니다.\n콘텐츠 등록이 완료되면 알림을 보내드립니다.\n이 페이지를 나가도 콘텐츠는 자동으로 등록됩니다.",
en: "Your content is being uploaded.\nWe will notify you when the upload is complete.\nYou can leave this page and the content will still be registered.",
ja: "登録したコンテンツはアップロード中です。\nアップロードが完了すると通知します。\nこのページを離れても自動で登録されます。"
)
}
// / // /
static var free: String { pick(ko: "무료", en: "Free", ja: "無料") } static var free: String { pick(ko: "무료", en: "Free", ja: "無料") }
@@ -495,6 +622,20 @@ enum I18n {
static var publishReserved: String { pick(ko: "예약 공개", en: "Scheduled", ja: "予約公開") } static var publishReserved: String { pick(ko: "예약 공개", en: "Scheduled", ja: "予約公開") }
} }
enum Playlist {
static var deleteTitle: String {
pick(ko: "재생 목록 삭제", en: "Delete playlist", ja: "プレイリストを削除")
}
static func deleteQuestion(_ title: String) -> String {
pick(
ko: "\(title)을 삭제하시겠습니까?",
en: "Do you want to delete \(title)?",
ja: "\(title)を削除しますか?"
)
}
}
enum Category { enum Category {
static var all: String { pick(ko: "전체", en: "All", ja: "すべて") } static var all: String { pick(ko: "전체", en: "All", ja: "すべて") }
} }

View File

@@ -229,13 +229,13 @@ struct LiveRoomProfilesDialogView: View {
if viewModel.isShowKickOutPopup { if viewModel.isShowKickOutPopup {
SodaDialog( SodaDialog(
title: "내보내기", title: I18n.LiveRoom.kickOutTitle,
desc: viewModel.kickOutDesc, desc: viewModel.kickOutDesc,
confirmButtonTitle: "내보내기", confirmButtonTitle: I18n.LiveRoom.kickOutConfirm,
confirmButtonAction: { confirmButtonAction: {
viewModel.kickOut() viewModel.kickOut()
}, },
cancelButtonTitle: "취소", cancelButtonTitle: I18n.Common.cancel,
cancelButtonAction: { cancelButtonAction: {
viewModel.isShowKickOutPopup = false viewModel.isShowKickOutPopup = false
viewModel.kickOutDesc = "" viewModel.kickOutDesc = ""

View File

@@ -209,14 +209,14 @@ struct LiveRoomUserProfileDialogView: View {
if viewModel.isShowKickOutPopup { if viewModel.isShowKickOutPopup {
SodaDialog( SodaDialog(
title: "내보내기", title: I18n.LiveRoom.kickOutTitle,
desc: viewModel.kickOutDesc, desc: viewModel.kickOutDesc,
confirmButtonTitle: "내보내기", confirmButtonTitle: I18n.LiveRoom.kickOutConfirm,
confirmButtonAction: { confirmButtonAction: {
viewModel.kickOut() viewModel.kickOut()
isShowing = false isShowing = false
}, },
cancelButtonTitle: "취소", cancelButtonTitle: I18n.Common.cancel,
cancelButtonAction: { cancelButtonAction: {
viewModel.isShowKickOutPopup = false viewModel.isShowKickOutPopup = false
viewModel.kickOutDesc = "" viewModel.kickOutDesc = ""

View File

@@ -512,9 +512,9 @@ struct LiveRoomViewV2: View {
if viewModel.changeIsAdult && !UserDefaults.bool(forKey: .auth) { if viewModel.changeIsAdult && !UserDefaults.bool(forKey: .auth) {
SodaDialog( SodaDialog(
title: "알림", title: I18n.Common.alertTitle,
desc: "지금 참여하던 라이브는 '19세 이상' 연령제한이 설정되어 정보통신망 이용촉진 및 정보 보호 등에 관한 법률 및 청소년 보호법의 규정에 의해 만 19세 미만의 청소년은 이용할 수 없습니다.\n마이페이지에서 본인인증 후 다시 이용하시기 바랍니다.", desc: I18n.LiveRoom.ageRestrictionDesc,
confirmButtonTitle: "확인", confirmButtonTitle: I18n.Common.confirm,
confirmButtonAction: { confirmButtonAction: {
viewModel.quitRoom() viewModel.quitRoom()
} }
@@ -523,10 +523,9 @@ struct LiveRoomViewV2: View {
if viewModel.isShowNoticeLikeHeart { if viewModel.isShowNoticeLikeHeart {
SodaDialog( SodaDialog(
title: "안내", title: I18n.Common.noticeTitle,
desc: "'좋아해요'는 유료 후원입니다.\n" + desc: I18n.LiveRoom.likeHeartNoticeDesc,
"클릭시 1캔이 소진됩니다.", confirmButtonTitle: I18n.Common.confirm
confirmButtonTitle: "확인"
) { ) {
viewModel.isShowNoticeLikeHeart = false viewModel.isShowNoticeLikeHeart = false
} }
@@ -534,14 +533,14 @@ struct LiveRoomViewV2: View {
if viewModel.isShowQuitPopup { if viewModel.isShowQuitPopup {
SodaDialog( SodaDialog(
title: "라이브 나가기", title: I18n.LiveRoom.quitTitle,
desc: "라이브에서 나가시겠습니까?", desc: I18n.LiveRoom.quitDesc,
confirmButtonTitle: "", confirmButtonTitle: I18n.Common.yes,
confirmButtonAction: { confirmButtonAction: {
viewModel.isShowQuitPopup = false viewModel.isShowQuitPopup = false
viewModel.quitRoom() viewModel.quitRoom()
}, },
cancelButtonTitle: "아니오", cancelButtonTitle: I18n.Common.no,
cancelButtonAction: { cancelButtonAction: {
viewModel.isShowQuitPopup = false viewModel.isShowQuitPopup = false
} }
@@ -550,18 +549,14 @@ struct LiveRoomViewV2: View {
if viewModel.isShowLiveEndPopup { if viewModel.isShowLiveEndPopup {
SodaDialog( SodaDialog(
title: "라이브 종료", title: I18n.LiveRoom.endTitle,
desc: "라이브를 종료하시겠습니까?\n" + desc: I18n.LiveRoom.endDesc,
"라이브를 종료하면 대화내용은\n" + confirmButtonTitle: I18n.Common.yes,
"저장되지 않고 사라집니다.\n" +
"참여자들 또한 라이브가 종료되어\n" +
"강제퇴장 됩니다.",
confirmButtonTitle: "",
confirmButtonAction: { confirmButtonAction: {
viewModel.isShowLiveEndPopup = false viewModel.isShowLiveEndPopup = false
viewModel.quitRoom() viewModel.quitRoom()
}, },
cancelButtonTitle: "아니오", cancelButtonTitle: I18n.Common.no,
cancelButtonAction: { cancelButtonAction: {
viewModel.isShowLiveEndPopup = false viewModel.isShowLiveEndPopup = false
} }

View File

@@ -40,22 +40,22 @@ struct SplashView: View {
if isShowMaintenancePopup { if isShowMaintenancePopup {
SodaDialog( SodaDialog(
title: "안내", title: I18n.Splash.maintenanceTitle,
desc: "서비스 점검중입니다.", desc: I18n.Splash.maintenanceDesc,
confirmButtonTitle: "확인", confirmButtonTitle: I18n.Common.confirm,
confirmButtonAction: { isShowMaintenancePopup = false } confirmButtonAction: { isShowMaintenancePopup = false }
) )
} }
if isShowUpdatePopup { if isShowUpdatePopup {
SodaDialog( SodaDialog(
title: "업데이트", title: I18n.Splash.updateTitle,
desc: "최신 업데이트가 있습니다.\n업데이트 하시겠습니까?", desc: I18n.Splash.updateDesc,
confirmButtonTitle: "업데이트", confirmButtonTitle: I18n.Splash.updateConfirm,
confirmButtonAction: { confirmButtonAction: {
UIApplication.shared.open(URL(string: "https://apps.apple.com/us/app/id6461721697?mt=8")!, options: [:]) UIApplication.shared.open(URL(string: "https://apps.apple.com/us/app/id6461721697?mt=8")!, options: [:])
}, },
cancelButtonTitle: "다음에", cancelButtonTitle: I18n.Splash.updateCancel,
cancelButtonAction: { cancelButtonAction: {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
AppState.shared.setAppStep(step: .main) AppState.shared.setAppStep(step: .main)
@@ -66,9 +66,9 @@ struct SplashView: View {
if isShowForcedUpdatePopup { if isShowForcedUpdatePopup {
SodaDialog( SodaDialog(
title: "업데이트", title: I18n.Splash.updateTitle,
desc: "필수 업데이트가 있습니다.\n업데이트 후 사용가능합니다.", desc: I18n.Splash.forcedUpdateDesc,
confirmButtonTitle: "업데이트", confirmButtonTitle: I18n.Splash.updateConfirm,
confirmButtonAction: { confirmButtonAction: {
UIApplication.shared.open(URL(string: "https://apps.apple.com/us/app/id6461721697?mt=8")!, options: [:]) UIApplication.shared.open(URL(string: "https://apps.apple.com/us/app/id6461721697?mt=8")!, options: [:])
} }