feat(i18n): 사용자 화면 문구를 I18n 키로 통일한다
This commit is contained in:
@@ -16,9 +16,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
" · %@" : {
|
||||
|
||||
},
|
||||
" (" : {
|
||||
"localizations" : {
|
||||
@@ -828,6 +825,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"%@%@" : {
|
||||
"localizations" : {
|
||||
"ko" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "%1$@%2$@"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"%@님을 차단하시겠습니까?" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -4136,22 +4143,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"목" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Thu"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "木"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"모든 기기에서 로그아웃" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -4203,6 +4194,22 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"목" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Thu"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "木"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"무료" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -6933,134 +6940,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"이용약관" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Terms of service"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "利用規約"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"이전화" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Previous episode"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "前の話"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"인기" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Popular"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "人気"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"인기 캐릭터 채팅" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Top character"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "人気キャラチャット"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"인기 콘텐츠" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Popular content"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "人気コンテンツ"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"인기순" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "By popularity"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "人気順"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"인증완료" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Verification completed"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "認証完了"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"일" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Sun"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "日"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"이메일을 입력하세요" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -7141,6 +7020,54 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"이용약관" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Terms of service"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "利用規約"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"이전화" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Previous episode"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "前の話"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"인기" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Popular"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "人気"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"인기 시리즈" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
@@ -7174,6 +7101,38 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"인기 캐릭터 채팅" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Top character"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "人気キャラチャット"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"인기 콘텐츠" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Popular content"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "人気コンテンツ"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"인기 크리에이터" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
@@ -7190,6 +7149,54 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"인기순" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "By popularity"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "人気順"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"인증완료" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Verification completed"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "認証完了"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"일" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Sun"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "日"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"일간 랭킹" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
|
||||
@@ -355,6 +355,23 @@ enum I18n {
|
||||
pick(ko: "더보기 >", en: "More >", ja: "もっと見る >")
|
||||
}
|
||||
}
|
||||
|
||||
enum SearchChannel {
|
||||
static var title: String {
|
||||
pick(ko: "채널 탐색", en: "Search channels", ja: "チャンネル探索")
|
||||
}
|
||||
}
|
||||
|
||||
enum NotificationList {
|
||||
static var emptyMessage: String {
|
||||
pick(ko: "알림이 없습니다.", en: "No notifications.", ja: "通知がありません。")
|
||||
}
|
||||
|
||||
static var timestampSeparator: String {
|
||||
pick(ko: " · ", en: " · ", ja: " · ")
|
||||
}
|
||||
}
|
||||
|
||||
enum ContentDetail {
|
||||
static var creatorOtherContents: String {
|
||||
pick(
|
||||
@@ -835,6 +852,10 @@ enum I18n {
|
||||
}
|
||||
|
||||
enum Report {
|
||||
static var cheersReportTitle: String {
|
||||
pick(ko: "응원글 신고", en: "Report cheer post", ja: "応援投稿を通報")
|
||||
}
|
||||
|
||||
static var postReportTitle: String {
|
||||
pick(ko: "게시물 신고", en: "Report post", ja: "投稿通報")
|
||||
}
|
||||
@@ -843,6 +864,135 @@ enum I18n {
|
||||
pick(ko: "신고", en: "Report", ja: "報告する")
|
||||
}
|
||||
|
||||
static var cheersReasons: [String] {
|
||||
[
|
||||
cheersReasonSpam,
|
||||
cheersReasonChildAbuse,
|
||||
cheersReasonHateOrViolence,
|
||||
cheersReasonTerrorism,
|
||||
cheersReasonHarassment,
|
||||
cheersReasonSelfHarm,
|
||||
cheersReasonMisinformation
|
||||
]
|
||||
}
|
||||
|
||||
static var userReasons: [String] {
|
||||
[
|
||||
userReasonHarassment,
|
||||
userReasonPrivacy,
|
||||
userReasonImpersonation,
|
||||
userReasonThreat,
|
||||
userReasonChildAbuse,
|
||||
userReasonHate,
|
||||
userReasonSpamFraud,
|
||||
userReasonNone
|
||||
]
|
||||
}
|
||||
|
||||
static var cheersReasonSpam: String {
|
||||
pick(
|
||||
ko: "원치 않는 상업성 콘텐츠 또는 스팸",
|
||||
en: "Unwanted commercial content or spam",
|
||||
ja: "望まない商業コンテンツまたはスパム"
|
||||
)
|
||||
}
|
||||
|
||||
static var cheersReasonChildAbuse: String {
|
||||
pick(ko: "아동 학대", en: "Child abuse", ja: "児童虐待")
|
||||
}
|
||||
|
||||
static var cheersReasonHateOrViolence: String {
|
||||
pick(
|
||||
ko: "증오심 표현 또는 노골적인 폭력",
|
||||
en: "Hate speech or graphic violence",
|
||||
ja: "憎悪表現または過度な暴力表現"
|
||||
)
|
||||
}
|
||||
|
||||
static var cheersReasonTerrorism: String {
|
||||
pick(ko: "테러 조장", en: "Promotion of terrorism", ja: "テロ助長")
|
||||
}
|
||||
|
||||
static var cheersReasonHarassment: String {
|
||||
pick(ko: "희롱 또는 괴롭힘", en: "Harassment or bullying", ja: "嫌がらせまたはいじめ")
|
||||
}
|
||||
|
||||
static var cheersReasonSelfHarm: String {
|
||||
pick(ko: "자살 또는 자해", en: "Suicide or self-harm", ja: "自殺または自傷行為")
|
||||
}
|
||||
|
||||
static var cheersReasonMisinformation: String {
|
||||
pick(ko: "잘못된 정보", en: "Misinformation", ja: "誤情報")
|
||||
}
|
||||
|
||||
static var userReasonHarassment: String {
|
||||
pick(ko: "괴롭힘 및 사이버 폭력", en: "Harassment and cyberbullying", ja: "嫌がらせとサイバー暴力")
|
||||
}
|
||||
|
||||
static var userReasonPrivacy: String {
|
||||
pick(ko: "개인정보 침해", en: "Privacy violation", ja: "プライバシー侵害")
|
||||
}
|
||||
|
||||
static var userReasonImpersonation: String {
|
||||
pick(ko: "명의 도용", en: "Impersonation", ja: "なりすまし")
|
||||
}
|
||||
|
||||
static var userReasonThreat: String {
|
||||
pick(ko: "폭력적 위협", en: "Violent threats", ja: "暴力的な脅迫")
|
||||
}
|
||||
|
||||
static var userReasonChildAbuse: String {
|
||||
pick(ko: "아동 학대", en: "Child abuse", ja: "児童虐待")
|
||||
}
|
||||
|
||||
static var userReasonHate: String {
|
||||
pick(ko: "보호 대상 집단에 대한 증오심 표현", en: "Hate speech toward protected groups", ja: "保護対象グループへの憎悪表現")
|
||||
}
|
||||
|
||||
static var userReasonSpamFraud: String {
|
||||
pick(ko: "스팸 및 사기", en: "Spam and fraud", ja: "スパムと詐欺")
|
||||
}
|
||||
|
||||
static var userReasonNone: String {
|
||||
pick(ko: "나에게 해당하는 문제 없음", en: "None of these apply", ja: "該当する問題なし")
|
||||
}
|
||||
|
||||
static var profilePhotoReportTitle: String {
|
||||
pick(ko: "프로필 사진 신고", en: "Report profile photo", ja: "プロフィール写真を通報")
|
||||
}
|
||||
|
||||
static var profilePhotoReportDescription: String {
|
||||
pick(
|
||||
ko: "신고제도를 남용할 경우, 계정에 제약이 있을 수 있습니다.\n프로필 사진을 신고하시겠습니까?",
|
||||
en: "Abusing the reporting system may restrict your account.\nDo you want to report this profile photo?",
|
||||
ja: "通報制度を乱用した場合、アカウントに制約がかかる可能性があります。\nプロフィール写真を通報しますか?"
|
||||
)
|
||||
}
|
||||
|
||||
static var userReportTitle: String {
|
||||
pick(ko: "사용자 신고", en: "Report user", ja: "ユーザーを通報")
|
||||
}
|
||||
|
||||
static var userReportAction: String {
|
||||
pick(ko: "사용자 신고하기", en: "Report user", ja: "ユーザーを通報")
|
||||
}
|
||||
|
||||
static var profileReportAction: String {
|
||||
pick(ko: "프로필 신고하기", en: "Report profile", ja: "プロフィールを通報")
|
||||
}
|
||||
|
||||
static var blockUserAction: String {
|
||||
pick(ko: "사용자 차단하기", en: "Block user", ja: "ユーザーをブロック")
|
||||
}
|
||||
|
||||
static var unblockUserAction: String {
|
||||
pick(ko: "사용자 차단해제", en: "Unblock user", ja: "ユーザーのブロックを解除")
|
||||
}
|
||||
|
||||
static var profileReportReason: String {
|
||||
pick(ko: "프로필 신고", en: "Report profile", ja: "プロフィールを通報")
|
||||
}
|
||||
|
||||
static var reasons: [String] {
|
||||
[
|
||||
reasonSpam,
|
||||
@@ -2080,7 +2230,149 @@ If you block this user, the following features will be restricted.
|
||||
}
|
||||
}
|
||||
|
||||
enum User {
|
||||
static var emailTitle: String {
|
||||
pick(ko: "이메일", en: "Email", ja: "メール")
|
||||
}
|
||||
|
||||
static var emailPlaceholder: String {
|
||||
pick(ko: "이메일", en: "Email", ja: "メール")
|
||||
}
|
||||
|
||||
static var passwordTitle: String {
|
||||
pick(ko: "비밀번호", en: "Password", ja: "パスワード")
|
||||
}
|
||||
|
||||
static var passwordPlaceholder: String {
|
||||
pick(ko: "비밀번호", en: "Password", ja: "パスワード")
|
||||
}
|
||||
|
||||
static var showPassword: String {
|
||||
pick(ko: "비밀번호 표시", en: "Show password", ja: "パスワードを表示")
|
||||
}
|
||||
|
||||
static var emailRequired: String {
|
||||
pick(ko: "이메일을 입력해 주세요.", en: "Please enter your email.", ja: "メールアドレスを入力してください。")
|
||||
}
|
||||
|
||||
static var emailInvalid: String {
|
||||
pick(ko: "올바른 이메일을 입력하세요", en: "Enter a valid email address.", ja: "正しいメールアドレスを入力してください。")
|
||||
}
|
||||
|
||||
static var passwordRequired: String {
|
||||
pick(ko: "비밀번호를 입력해 주세요.", en: "Please enter your password.", ja: "パスワードを入力してください。")
|
||||
}
|
||||
|
||||
static var blockUserAction: String {
|
||||
pick(ko: "사용자 차단하기", en: "Block user", ja: "ユーザーをブロック")
|
||||
}
|
||||
|
||||
static var unblockUserAction: String {
|
||||
pick(ko: "사용자 차단해제", en: "Unblock user", ja: "ユーザーのブロックを解除")
|
||||
}
|
||||
|
||||
static var reportUserAction: String {
|
||||
pick(ko: "사용자 신고하기", en: "Report user", ja: "ユーザーを通報")
|
||||
}
|
||||
|
||||
static var reportProfileAction: String {
|
||||
pick(ko: "프로필 신고하기", en: "Report profile", ja: "プロフィールを通報")
|
||||
}
|
||||
}
|
||||
|
||||
enum SignUp {
|
||||
static var title: String {
|
||||
pick(ko: "회원가입", en: "Sign up", ja: "会員登録")
|
||||
}
|
||||
|
||||
static var terms: String {
|
||||
pick(ko: "이용약관", en: "Terms of service", ja: "利用規約")
|
||||
}
|
||||
|
||||
static var privacyPolicy: String {
|
||||
pick(ko: "개인정보수집 및 이용동의", en: "Consent to collect and use personal information", ja: "個人情報の収集および利用への同意")
|
||||
}
|
||||
|
||||
static var required: String {
|
||||
pick(ko: "(필수)", en: "(Required)", ja: "(必須)")
|
||||
}
|
||||
|
||||
static var submit: String {
|
||||
pick(ko: "회원가입", en: "Sign up", ja: "会員登録")
|
||||
}
|
||||
|
||||
static var agreementRequired: String {
|
||||
pick(ko: "약관에 동의하셔야 회원가입이 가능합니다.", en: "You must agree to the terms to sign up.", ja: "利用規約に同意する必要があります。")
|
||||
}
|
||||
}
|
||||
|
||||
enum FindPassword {
|
||||
static var title: String {
|
||||
pick(ko: "비밀번호 재설정", en: "Reset password", ja: "パスワード再設定")
|
||||
}
|
||||
|
||||
static var description1: String {
|
||||
pick(ko: "회원가입한 이메일 주소로\n임시 비밀번호를 보내드립니다.", en: "We will send a temporary password to the email address you used to sign up.", ja: "登録したメールアドレスに仮パスワードを送信します。")
|
||||
}
|
||||
|
||||
static var description2: String {
|
||||
pick(ko: "임시 비밀번호로 로그인 후\n마이페이지 > 프로필 설정에서\n비밀번호를 변경하고 이용하세요.", en: "Log in with the temporary password, then change it in My Page > Profile Settings.", ja: "仮パスワードでログイン後、マイページ > プロフィール設定でパスワードを変更してください。")
|
||||
}
|
||||
|
||||
static var emailPlaceholder: String {
|
||||
pick(ko: "이메일을 입력하세요", en: "Enter your email", ja: "メールアドレスを入力してください")
|
||||
}
|
||||
|
||||
static var submit: String {
|
||||
pick(ko: "임시 비밀번호 받기", en: "Get temporary password", ja: "仮パスワードを受け取る")
|
||||
}
|
||||
|
||||
static var contactSupport: String {
|
||||
pick(ko: "고객센터로 문의하기", en: "Contact support", ja: "カスタマーセンターに問い合わせる")
|
||||
}
|
||||
|
||||
static var emailRequired: String {
|
||||
pick(ko: "이메일을 입력하세요.", en: "Please enter your email.", ja: "メールアドレスを入力してください。")
|
||||
}
|
||||
|
||||
static var successMessage: String {
|
||||
pick(ko: "임시 비밀번호가 입력하신 이메일로 발송되었습니다.\n이메일을 확인해 주세요.", en: "A temporary password has been sent to your email.\nPlease check your inbox.", ja: "仮パスワードを入力したメールアドレスに送信しました。\nメールをご確認ください。")
|
||||
}
|
||||
}
|
||||
|
||||
enum Login {
|
||||
static var title: String {
|
||||
pick(ko: "로그인", en: "Log in", ja: "ログイン")
|
||||
}
|
||||
|
||||
static var login: String {
|
||||
pick(ko: "로그인", en: "Log in", ja: "ログイン")
|
||||
}
|
||||
|
||||
static var forgotPassword: String {
|
||||
pick(ko: "비밀번호를 잊으셨나요?", en: "Forgot your password?", ja: "パスワードを忘れましたか?")
|
||||
}
|
||||
|
||||
static var signUpPrompt: String {
|
||||
pick(ko: "보이스온 회원이 아닌가요? 지금 가입하세요.", en: "Not a VoiceOn member? Sign up now.", ja: "VoiceOnの会員ではありませんか?今すぐ登録してください。")
|
||||
}
|
||||
|
||||
static var appleAuthorizationFailed: String {
|
||||
pick(ko: "애플 로그인 정보를 가져오지 못했습니다.", en: "Failed to retrieve Apple sign-in information.", ja: "Appleログイン情報を取得できませんでした。")
|
||||
}
|
||||
|
||||
static var appleTokenMissing: String {
|
||||
pick(ko: "애플 인증 토큰을 가져오지 못했습니다.", en: "Failed to retrieve Apple identity token.", ja: "Apple認証トークンを取得できませんでした。")
|
||||
}
|
||||
|
||||
static var appleRetry: String {
|
||||
pick(ko: "다시 시도해 주세요.", en: "Please try again.", ja: "もう一度お試しください。")
|
||||
}
|
||||
|
||||
static var appleSignInFailed: String {
|
||||
pick(ko: "애플 로그인에 실패했습니다.\n다시 시도해 주세요.", en: "Apple sign-in failed.\nPlease try again.", ja: "Appleログインに失敗しました。\nもう一度お試しください。")
|
||||
}
|
||||
|
||||
enum Google {
|
||||
static var openFailed: String {
|
||||
pick(
|
||||
|
||||
@@ -25,7 +25,7 @@ struct PushNotificationListItemView: View {
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "bbbbbb"))
|
||||
|
||||
Text(" · \(item.relativeSentAtText())")
|
||||
Text("\(I18n.NotificationList.timestampSeparator)\(item.relativeSentAtText())")
|
||||
.appFont(size: 10, weight: .medium)
|
||||
.foregroundColor(Color(hex: "909090"))
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ struct PushNotificationListView: View {
|
||||
.resizable()
|
||||
.frame(width: 60, height: 60)
|
||||
|
||||
Text("알림이 없습니다.")
|
||||
Text(I18n.NotificationList.emptyMessage)
|
||||
.appFont(size: 10.7, weight: .medium)
|
||||
.foregroundColor(Color(hex: "bbbbbb"))
|
||||
}
|
||||
@@ -61,7 +61,7 @@ struct PushNotificationListView: View {
|
||||
|
||||
private var titleBar: some View {
|
||||
ZStack {
|
||||
DetailNavigationBar(title: "알림")
|
||||
DetailNavigationBar(title: I18n.Common.alertTitle)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Spacer()
|
||||
|
||||
@@ -13,15 +13,7 @@ struct CheersReportDialogView: View {
|
||||
let confirmAction: (String) -> Void
|
||||
|
||||
@State private var selectedIndex: Int? = nil
|
||||
let reasons = [
|
||||
"원치 않는 상업성 콘텐츠 또는 스팸",
|
||||
"아동 학대",
|
||||
"증오심 표현 또는 노골적인 폭력",
|
||||
"테러 조장",
|
||||
"희롱 또는 괴롭힘",
|
||||
"자살 또는 자해",
|
||||
"잘못된 정보"
|
||||
]
|
||||
let reasons = I18n.Report.cheersReasons
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
@@ -31,7 +23,7 @@ struct CheersReportDialogView: View {
|
||||
.onTapGesture { isShowing = false }
|
||||
|
||||
VStack(spacing: 13.3) {
|
||||
Text("응원글 신고")
|
||||
Text(I18n.Report.cheersReportTitle)
|
||||
.appFont(size: 16.7, weight: .medium)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
@@ -59,14 +51,14 @@ struct CheersReportDialogView: View {
|
||||
HStack(spacing: 26.7) {
|
||||
Spacer()
|
||||
|
||||
Text("취소")
|
||||
Text(I18n.Common.cancel)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "3bb9f1"))
|
||||
.onTapGesture {
|
||||
isShowing = false
|
||||
}
|
||||
|
||||
Text("신고")
|
||||
Text(I18n.Report.reportAction)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "3bb9f1"))
|
||||
.onTapGesture {
|
||||
|
||||
@@ -20,25 +20,25 @@ struct ProfileReportDialogView: View {
|
||||
.onTapGesture { isShowing = false }
|
||||
|
||||
VStack(spacing: 13.3) {
|
||||
Text("프로필 사진 신고")
|
||||
Text(I18n.Report.profilePhotoReportTitle)
|
||||
.appFont(size: 16.7, weight: .medium)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
Text("신고제도를 남용할 경우, 계정에 제약이 있을 수 있습니다.\n프로필 사진을 신고하시겠습니까?")
|
||||
Text(I18n.Report.profilePhotoReportDescription)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "909090"))
|
||||
|
||||
HStack(spacing: 26.7) {
|
||||
Spacer()
|
||||
|
||||
Text("취소")
|
||||
Text(I18n.Common.cancel)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "3bb9f1"))
|
||||
.onTapGesture {
|
||||
isShowing = false
|
||||
}
|
||||
|
||||
Text("신고")
|
||||
Text(I18n.Report.reportAction)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "3bb9f1"))
|
||||
.onTapGesture {
|
||||
|
||||
@@ -29,7 +29,7 @@ struct ProfileReportMenuView: View {
|
||||
|
||||
VStack(spacing: 13.3) {
|
||||
HStack(spacing: 0) {
|
||||
Text(isBlockedUser ? "사용자 차단해제" : "사용자 차단하기")
|
||||
Text(isBlockedUser ? I18n.User.unblockUserAction : I18n.User.blockUserAction)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
|
||||
@@ -48,7 +48,7 @@ struct ProfileReportMenuView: View {
|
||||
}
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("사용자 신고하기")
|
||||
Text(I18n.User.reportUserAction)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
|
||||
@@ -63,7 +63,7 @@ struct ProfileReportMenuView: View {
|
||||
}
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Text("프로필 신고하기")
|
||||
Text(I18n.User.reportProfileAction)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
|
||||
|
||||
@@ -13,16 +13,7 @@ struct UserReportDialogView: View {
|
||||
let confirmAction: (String) -> Void
|
||||
|
||||
@State private var selectedIndex: Int? = nil
|
||||
let reasons = [
|
||||
"괴롭힘 및 사이버 폭력",
|
||||
"개인정보 침해",
|
||||
"명의 도용",
|
||||
"폭력적 위협",
|
||||
"아동 학대",
|
||||
"보호 대상 집단에 대한 증오심 표현",
|
||||
"스팸 및 사기",
|
||||
"나에게 해당하는 문제 없음"
|
||||
]
|
||||
let reasons = I18n.Report.userReasons
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
@@ -32,7 +23,7 @@ struct UserReportDialogView: View {
|
||||
.onTapGesture { isShowing = false }
|
||||
|
||||
VStack(spacing: 13.3) {
|
||||
Text("사용자 신고")
|
||||
Text(I18n.Report.userReportTitle)
|
||||
.appFont(size: 16.7, weight: .medium)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
|
||||
@@ -60,14 +51,14 @@ struct UserReportDialogView: View {
|
||||
HStack(spacing: 26.7) {
|
||||
Spacer()
|
||||
|
||||
Text("취소")
|
||||
Text(I18n.Common.cancel)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "3bb9f1"))
|
||||
.onTapGesture {
|
||||
isShowing = false
|
||||
}
|
||||
|
||||
Text("신고")
|
||||
Text(I18n.Report.reportAction)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "3bb9f1"))
|
||||
.onTapGesture {
|
||||
|
||||
@@ -16,7 +16,7 @@ struct SearchChannelView: View {
|
||||
var body: some View {
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
VStack(spacing: 0) {
|
||||
DetailNavigationBar(title: "채널 탐색")
|
||||
DetailNavigationBar(title: I18n.SearchChannel.title)
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Image("ic_title_search_black")
|
||||
@@ -77,7 +77,7 @@ struct SearchChannelView: View {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text("검색 결과가 없습니다.")
|
||||
Text(I18n.Search.noResults)
|
||||
.appFont(size: 18.3, weight: .medium)
|
||||
.foregroundColor(.white)
|
||||
.padding(.top, 20)
|
||||
|
||||
@@ -17,11 +17,11 @@ struct FindPasswordView: View {
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
GeometryReader { proxy in
|
||||
VStack(spacing: 0) {
|
||||
DetailNavigationBar(title: String(localized: "비밀번호 재설정"))
|
||||
DetailNavigationBar(title: I18n.FindPassword.title)
|
||||
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(spacing: 0) {
|
||||
Text("회원가입한 이메일 주소로\n임시 비밀번호를 보내드립니다.")
|
||||
Text(I18n.FindPassword.description1)
|
||||
.appFont(size: 16, weight: .bold)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
.multilineTextAlignment(.center)
|
||||
@@ -29,7 +29,7 @@ struct FindPasswordView: View {
|
||||
.padding(.top, 40)
|
||||
.padding(.horizontal, 26.7)
|
||||
|
||||
Text("임시 비밀번호로 로그인 후\n마이페이지 > 프로필 설정에서\n비밀번호를 변경하고 이용하세요.")
|
||||
Text(I18n.FindPassword.description2)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(Color(hex: "909090"))
|
||||
.multilineTextAlignment(.center)
|
||||
@@ -37,7 +37,7 @@ struct FindPasswordView: View {
|
||||
.padding(.top, 40)
|
||||
.padding(.horizontal, 26.7)
|
||||
|
||||
TextField("이메일을 입력하세요", text: $viewModel.email)
|
||||
TextField(I18n.FindPassword.emailPlaceholder, text: $viewModel.email)
|
||||
.focused($isFocused)
|
||||
.autocapitalization(.none)
|
||||
.disableAutocorrection(true)
|
||||
@@ -54,7 +54,7 @@ struct FindPasswordView: View {
|
||||
isFocused = true
|
||||
}
|
||||
|
||||
Text("임시 비밀번호 받기")
|
||||
Text(I18n.FindPassword.submit)
|
||||
.appFont(size: 18.3, weight: .bold)
|
||||
.foregroundColor(Color.white)
|
||||
.frame(maxWidth: proxy.size.width - 26.7)
|
||||
@@ -67,7 +67,7 @@ struct FindPasswordView: View {
|
||||
HStack(spacing: 13.3) {
|
||||
Image("ic_headphones_blue")
|
||||
|
||||
Text("고객센터로 문의하기")
|
||||
Text(I18n.FindPassword.contactSupport)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(.button)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ final class FindPasswordViewModel: ObservableObject {
|
||||
|
||||
func findPassword() {
|
||||
if email.trimmingCharacters(in: .whitespaces).isEmpty {
|
||||
errorMessage = "이메일을 입력하세요."
|
||||
errorMessage = I18n.FindPassword.emailRequired
|
||||
isShowPopup = true
|
||||
return
|
||||
}
|
||||
@@ -45,7 +45,7 @@ final class FindPasswordViewModel: ObservableObject {
|
||||
|
||||
if decoded.success {
|
||||
self.email = ""
|
||||
self.errorMessage = "임시 비밀번호가 입력하신 이메일로 발송되었습니다.\n이메일을 확인해 주세요."
|
||||
self.errorMessage = I18n.FindPassword.successMessage
|
||||
self.isShowPopup = true
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
||||
AppState.shared.back()
|
||||
@@ -54,13 +54,13 @@ final class FindPasswordViewModel: 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,11 +29,11 @@ struct LoginView: View {
|
||||
}
|
||||
|
||||
VStack(spacing: 0) {
|
||||
DetailNavigationBar(title: "로그인")
|
||||
DetailNavigationBar(title: I18n.Login.title)
|
||||
|
||||
Spacer()
|
||||
|
||||
TextField("이메일", text: $viewModel.email)
|
||||
TextField(I18n.User.emailPlaceholder, text: $viewModel.email)
|
||||
.submitLabel(.next)
|
||||
.focused($focusedField, equals: .email)
|
||||
.autocapitalization(.none)
|
||||
@@ -56,9 +56,9 @@ struct LoginView: View {
|
||||
HStack {
|
||||
Group {
|
||||
if isPasswordVisible {
|
||||
TextField("비밀번호", text: $viewModel.password)
|
||||
TextField(I18n.User.passwordPlaceholder, text: $viewModel.password)
|
||||
} else {
|
||||
SecureField("비밀번호", text: $viewModel.password)
|
||||
SecureField(I18n.User.passwordPlaceholder, text: $viewModel.password)
|
||||
}
|
||||
}
|
||||
.submitLabel(.done)
|
||||
@@ -92,7 +92,7 @@ struct LoginView: View {
|
||||
viewModel.login()
|
||||
}
|
||||
) {
|
||||
Text("로그인")
|
||||
Text(I18n.Login.login)
|
||||
.appFont(size: 15, weight: .bold)
|
||||
.frame(width: screenSize().width - 26.6, height: 46.7)
|
||||
.foregroundColor(.white)
|
||||
@@ -101,7 +101,7 @@ struct LoginView: View {
|
||||
}
|
||||
.padding(.top, 40)
|
||||
|
||||
Text("비밀번호를 잊으셨나요?")
|
||||
Text(I18n.Login.forgotPassword)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color.graybb)
|
||||
.padding(.vertical, 10)
|
||||
@@ -111,7 +111,7 @@ struct LoginView: View {
|
||||
}
|
||||
.padding(.top, 30)
|
||||
|
||||
Text("보이스온 회원이 아닌가요? 지금 가입하세요.")
|
||||
Text(I18n.Login.signUpPrompt)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color.graybb)
|
||||
.padding(.vertical, 10)
|
||||
|
||||
@@ -33,13 +33,13 @@ final class LoginViewModel: NSObject, ObservableObject {
|
||||
|
||||
func login() {
|
||||
if email.isEmpty {
|
||||
self.errorMessage = "이메일을 입력해 주세요."
|
||||
self.errorMessage = I18n.User.emailRequired
|
||||
self.isShowPopup = true
|
||||
return
|
||||
}
|
||||
|
||||
if password.isEmpty {
|
||||
self.errorMessage = "비밀번호를 입력해 주세요."
|
||||
self.errorMessage = I18n.User.passwordRequired
|
||||
self.isShowPopup = true
|
||||
return
|
||||
}
|
||||
@@ -309,13 +309,13 @@ final class LoginViewModel: NSObject, 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
|
||||
}
|
||||
}
|
||||
@@ -365,20 +365,20 @@ final class LoginViewModel: NSObject, ObservableObject {
|
||||
extension LoginViewModel: ASAuthorizationControllerDelegate {
|
||||
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
|
||||
guard let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential else {
|
||||
self.errorMessage = "애플 로그인 정보를 가져오지 못했습니다."
|
||||
self.errorMessage = I18n.Login.appleAuthorizationFailed
|
||||
self.isShowPopup = true
|
||||
return
|
||||
}
|
||||
|
||||
guard let identityTokenData = appleIDCredential.identityToken,
|
||||
let identityToken = String(data: identityTokenData, encoding: .utf8) else {
|
||||
self.errorMessage = "애플 인증 토큰을 가져오지 못했습니다."
|
||||
self.errorMessage = I18n.Login.appleTokenMissing
|
||||
self.isShowPopup = true
|
||||
return
|
||||
}
|
||||
|
||||
guard let nonce = currentNonce else {
|
||||
self.errorMessage = "다시 시도해 주세요."
|
||||
self.errorMessage = I18n.Login.appleRetry
|
||||
self.isShowPopup = true
|
||||
return
|
||||
}
|
||||
@@ -389,7 +389,7 @@ extension LoginViewModel: ASAuthorizationControllerDelegate {
|
||||
|
||||
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
|
||||
ERROR_LOG(error.localizedDescription)
|
||||
self.errorMessage = "애플 로그인에 실패했습니다.\n다시 시도해 주세요."
|
||||
self.errorMessage = I18n.Login.appleSignInFailed
|
||||
self.isShowPopup = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,11 +23,11 @@ struct SignUpView: View {
|
||||
BaseView(isLoading: $viewModel.isLoading) {
|
||||
GeometryReader { proxy in
|
||||
VStack(spacing: 0) {
|
||||
DetailNavigationBar(title: "회원가입")
|
||||
DetailNavigationBar(title: I18n.SignUp.title)
|
||||
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
VStack(spacing: 0) {
|
||||
TextField("이메일", text: $viewModel.email)
|
||||
TextField(I18n.User.emailPlaceholder, text: $viewModel.email)
|
||||
.submitLabel(.next)
|
||||
.focused($focusedField, equals: .email)
|
||||
.autocapitalization(.none)
|
||||
@@ -51,9 +51,9 @@ struct SignUpView: View {
|
||||
HStack {
|
||||
Group {
|
||||
if isPasswordVisible {
|
||||
TextField("비밀번호", text: $viewModel.password)
|
||||
TextField(I18n.User.passwordPlaceholder, text: $viewModel.password)
|
||||
} else {
|
||||
SecureField("비밀번호", text: $viewModel.password)
|
||||
SecureField(I18n.User.passwordPlaceholder, text: $viewModel.password)
|
||||
}
|
||||
}
|
||||
.submitLabel(.done)
|
||||
@@ -96,11 +96,11 @@ struct SignUpView: View {
|
||||
}
|
||||
|
||||
HStack(spacing: 5) {
|
||||
Text("이용약관")
|
||||
Text(I18n.SignUp.terms)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Text("(필수)")
|
||||
Text(I18n.SignUp.required)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(Color.button)
|
||||
}
|
||||
@@ -129,11 +129,11 @@ struct SignUpView: View {
|
||||
}
|
||||
|
||||
HStack(spacing: 5) {
|
||||
Text("개인정보수집 및 이용동의")
|
||||
Text(I18n.SignUp.privacyPolicy)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(Color.grayee)
|
||||
|
||||
Text("(필수)")
|
||||
Text(I18n.SignUp.required)
|
||||
.appFont(size: 12, weight: .medium)
|
||||
.foregroundColor(Color.button)
|
||||
}
|
||||
@@ -152,7 +152,7 @@ struct SignUpView: View {
|
||||
.padding(.top, 20)
|
||||
.padding(.horizontal, 13.3)
|
||||
|
||||
Text("회원가입")
|
||||
Text(I18n.SignUp.submit)
|
||||
.appFont(size: 18.3, weight: .bold)
|
||||
.foregroundColor(Color.white)
|
||||
.padding(.vertical, 16)
|
||||
|
||||
@@ -67,13 +67,13 @@ final class SignUpViewModel: 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
|
||||
}
|
||||
}
|
||||
@@ -83,25 +83,25 @@ final class SignUpViewModel: ObservableObject {
|
||||
|
||||
private func validate() -> Bool {
|
||||
if email.trimmingCharacters(in: .whitespaces).isEmpty || !validateEmail() {
|
||||
errorMessage = "올바른 이메일을 입력하세요"
|
||||
errorMessage = I18n.User.emailInvalid
|
||||
isShowPopup = true
|
||||
return false
|
||||
}
|
||||
|
||||
if password.trimmingCharacters(in: .whitespaces).isEmpty {
|
||||
errorMessage = "비밀번호를 입력하세요"
|
||||
errorMessage = I18n.User.passwordRequired
|
||||
isShowPopup = true
|
||||
return false
|
||||
}
|
||||
|
||||
if !validatePassword() {
|
||||
errorMessage = "영문, 숫자 포함 8자 이상의 비밀번호를 입력해 주세요."
|
||||
errorMessage = I18n.ProfileUpdate.passwordRuleHint
|
||||
isShowPopup = true
|
||||
return false
|
||||
}
|
||||
|
||||
if !isAgreeTerms || !isAgreePrivacyPolicy {
|
||||
errorMessage = "약관에 동의하셔야 회원가입이 가능합니다."
|
||||
errorMessage = I18n.SignUp.agreementRequired
|
||||
isShowPopup = true
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ struct UserTextField: View {
|
||||
Image("btn_select_normal")
|
||||
}
|
||||
|
||||
Text("비밀번호 표시")
|
||||
Text(I18n.User.showPassword)
|
||||
.appFont(size: 13.3, weight: .medium)
|
||||
.foregroundColor(Color(hex: "eeeeee"))
|
||||
}
|
||||
@@ -74,8 +74,8 @@ struct UserTextField: View {
|
||||
struct UserTextField_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
UserTextField(
|
||||
title: "이메일",
|
||||
hint: "user_id@email.com",
|
||||
title: I18n.User.passwordTitle,
|
||||
hint: I18n.User.passwordPlaceholder,
|
||||
isSecure: true,
|
||||
variable: .constant("test"),
|
||||
isPasswordVisibleButton: true
|
||||
|
||||
@@ -54,13 +54,13 @@ final class UserViewModel: 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
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ final class UserViewModel: ObservableObject {
|
||||
let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData)
|
||||
|
||||
if decoded.success {
|
||||
self.errorMessage = "차단하였습니다."
|
||||
self.errorMessage = I18n.MemberChannel.userBlocked
|
||||
self.dismissDialog = true
|
||||
|
||||
self.memberId = 0
|
||||
@@ -97,13 +97,13 @@ final class UserViewModel: 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
|
||||
}
|
||||
}
|
||||
@@ -129,7 +129,7 @@ final class UserViewModel: ObservableObject {
|
||||
let decoded = try jsonDecoder.decode(ApiResponseWithoutData.self, from: responseData)
|
||||
|
||||
if decoded.success {
|
||||
self.errorMessage = "차단이 해제 되었습니다."
|
||||
self.errorMessage = I18n.MemberChannel.userUnblocked
|
||||
self.dismissDialog = true
|
||||
|
||||
self.memberId = 0
|
||||
@@ -138,20 +138,20 @@ final class UserViewModel: 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
|
||||
}
|
||||
}
|
||||
.store(in: &subscription)
|
||||
}
|
||||
|
||||
func report(type: ReportType, reason: String = "프로필 신고") {
|
||||
func report(type: ReportType, reason: String = I18n.Report.profileReportReason) {
|
||||
isLoading = true
|
||||
|
||||
let request = ReportRequest(type: type, reason: reason, reportedMemberId: memberId, cheersId: nil, audioContentId: nil)
|
||||
@@ -178,12 +178,12 @@ final class UserViewModel: 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,20 +416,17 @@
|
||||
- [ ] `SodaLive/Sources/MyPage/ServiceCenter/ServiceCenterViewModel.swift`
|
||||
|
||||
### Notification (2)
|
||||
- [ ] `SodaLive/Sources/Notification/List/PushNotificationListItemView.swift`
|
||||
- [ ] `SodaLive/Sources/Notification/List/PushNotificationListView.swift`
|
||||
|
||||
### Onboarding (1)
|
||||
- [ ] `SodaLive/Sources/Onboarding/OnboardingView.swift`
|
||||
- [x] `SodaLive/Sources/Notification/List/PushNotificationListItemView.swift`
|
||||
- [x] `SodaLive/Sources/Notification/List/PushNotificationListView.swift`
|
||||
|
||||
### Report (4)
|
||||
- [ ] `SodaLive/Sources/Report/CheersReportDialogView.swift`
|
||||
- [ ] `SodaLive/Sources/Report/ProfileReportDialogView.swift`
|
||||
- [ ] `SodaLive/Sources/Report/ProfileReportMenuView.swift`
|
||||
- [ ] `SodaLive/Sources/Report/UserReportDialogView.swift`
|
||||
- [x] `SodaLive/Sources/Report/CheersReportDialogView.swift`
|
||||
- [x] `SodaLive/Sources/Report/ProfileReportDialogView.swift`
|
||||
- [x] `SodaLive/Sources/Report/ProfileReportMenuView.swift`
|
||||
- [x] `SodaLive/Sources/Report/UserReportDialogView.swift`
|
||||
|
||||
### SearchChannel (1)
|
||||
- [ ] `SodaLive/Sources/SearchChannel/SearchChannelView.swift`
|
||||
- [x] `SodaLive/Sources/SearchChannel/SearchChannelView.swift`
|
||||
|
||||
### Settings (15)
|
||||
- [ ] `SodaLive/Sources/Settings/Content/ContentSettingsView.swift`
|
||||
@@ -457,14 +454,14 @@
|
||||
- [ ] `SodaLive/Sources/UI/Component/SeriesListItemView.swift`
|
||||
|
||||
### User (8)
|
||||
- [ ] `SodaLive/Sources/User/FindPassword/FindPasswordView.swift`
|
||||
- [ ] `SodaLive/Sources/User/FindPassword/FindPasswordViewModel.swift`
|
||||
- [ ] `SodaLive/Sources/User/Login/LoginView.swift`
|
||||
- [ ] `SodaLive/Sources/User/Login/LoginViewModel.swift`
|
||||
- [ ] `SodaLive/Sources/User/SignUp/SignUpView.swift`
|
||||
- [ ] `SodaLive/Sources/User/SignUp/SignUpViewModel.swift`
|
||||
- [ ] `SodaLive/Sources/User/UserTextField.swift`
|
||||
- [ ] `SodaLive/Sources/User/UserViewModel.swift`
|
||||
- [x] `SodaLive/Sources/User/FindPassword/FindPasswordView.swift`
|
||||
- [x] `SodaLive/Sources/User/FindPassword/FindPasswordViewModel.swift`
|
||||
- [x] `SodaLive/Sources/User/Login/LoginView.swift`
|
||||
- [x] `SodaLive/Sources/User/Login/LoginViewModel.swift`
|
||||
- [x] `SodaLive/Sources/User/SignUp/SignUpView.swift`
|
||||
- [x] `SodaLive/Sources/User/SignUp/SignUpViewModel.swift`
|
||||
- [x] `SodaLive/Sources/User/UserTextField.swift`
|
||||
- [x] `SodaLive/Sources/User/UserViewModel.swift`
|
||||
|
||||
## 검증 기록
|
||||
### 1차 계획 수립 (2026-03-31)
|
||||
@@ -612,3 +609,19 @@
|
||||
- 모듈 재검증 결과, 남은 한글 문자열은 Preview 샘플/`DEBUG_LOG`/SDK 입력값(비노출)만 존재.
|
||||
- 빌드 검증: `SodaLive`, `SodaLive-dev` Debug 빌드 모두 성공(`** BUILD SUCCEEDED **`).
|
||||
- 테스트 검증: 두 스킴 모두 `Scheme ... is not currently configured for the test action.`로 테스트 액션 미구성 확인(코드 실패 아님, 스킴 제약).
|
||||
|
||||
### 9차 구현 (User/SearchChannel/Report/Notification 15개 파일 i18n 전환, 2026-03-31)
|
||||
- 무엇/왜/어떻게:
|
||||
- 무엇: 변경 대상 목록 중 `User`, `SearchChannel`, `Report`, `Notification` 모듈의 15개 파일을 처리해 화면 문자열과 사용자 노출 에러 메시지를 `I18n.*`로 통일했다.
|
||||
- 왜: 로그인/회원가입/비밀번호 재설정/채널 탐색/신고/알림 화면에 하드코딩 문구가 남아 있어 다국어 접근이 일관되지 않았기 때문이다.
|
||||
- 어떻게: 관련 뷰와 뷰모델의 문자열을 교체하고, `I18n.swift`에 `User`, `SignUp`, `FindPassword`, `SearchChannel`, `NotificationList`, `Report` 키를 보강했다.
|
||||
- 실행 명령/도구:
|
||||
- `rg -n 'Text\\(\"|SecureField\\(\"|TextField\\(\"|DetailNavigationBar\\(title: \\\"|String\\(localized: \\\"|errorMessage = \\\"|let reasons = \\[' SodaLive/Sources/User SodaLive/Sources/SearchChannel SodaLive/Sources/Report SodaLive/Sources/Notification -g '!**/generated/**'`
|
||||
- `rg -n 'I18n\\.(User|SignUp|FindPassword|Login|SearchChannel|NotificationList|Report|Common)' SodaLive/Sources/User SodaLive/Sources/SearchChannel SodaLive/Sources/Report SodaLive/Sources/Notification -g '!**/generated/**'`
|
||||
- `xcodebuild -project "SodaLive.xcodeproj" -scheme "SodaLive" -configuration Debug build`
|
||||
- `HOME=/tmp/codexhome xcodebuild -project "SodaLive.xcodeproj" -scheme "SodaLive" -configuration Debug -derivedDataPath /tmp/SodaLiveDerivedData -clonedSourcePackagesDirPath /tmp/SodaLiveSPM build`
|
||||
- 결과:
|
||||
- `User` 8개 파일, `SearchChannel` 1개 파일, `Report` 4개 파일, `Notification` 2개 파일 체크박스를 완료 처리했다.
|
||||
- `PushNotificationListItemView.swift`의 시간 구분자도 `I18n.NotificationList.timestampSeparator`로 이관했다.
|
||||
- `xcodebuild`는 샌드박스 내 캐시/시뮬레이터 접근 제약과 이후 네트워크 차단으로 실패했다. 첫 시도는 workspace 인식 문제와 CoreSimulator 환경 오류가 섞여 있었고, 프로젝트 빌드로 전환한 뒤에는 Swift Package 의존성(`objectbox-swift-spm`)을 GitHub에서 가져오지 못해 중단되었다.
|
||||
- 따라서 이번 턴에서는 정적 치환과 문서 동기화까지 완료했고, 실제 컴파일 성공 여부는 네트워크가 허용되는 환경에서 추가 확인이 필요하다.
|
||||
|
||||
Reference in New Issue
Block a user