String Catalog가 적용되지 않는 부분을 I18n 파일에 언어별로 하드코딩 하여 보완

This commit is contained in:
Yu Sung
2025-12-17 12:03:32 +09:00
parent da2e8d0209
commit ad9f26c8a0
5 changed files with 198 additions and 124 deletions

View File

@@ -80,6 +80,9 @@
} }
} }
} }
},
" %lld" : {
}, },
" OFF" : { " OFF" : {
"localizations" : { "localizations" : {
@@ -4065,18 +4068,18 @@
} }
} }
}, },
"모집" : { "모집완료" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Recruiting" "value" : "Recruitment closed"
} }
}, },
"ja" : { "ja" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "募集" "value" : "募集終了"
} }
} }
} }
@@ -4097,18 +4100,18 @@
} }
} }
}, },
"모집완료" : { "모집" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "Recruitment closed" "value" : "Recruiting"
} }
}, },
"ja" : { "ja" : {
"stringUnit" : { "stringUnit" : {
"state" : "translated", "state" : "translated",
"value" : "募集終了" "value" : "募集"
} }
} }
} }
@@ -6721,6 +6724,102 @@
} }
} }
}, },
"이벤트 참여하기" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Join the event"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "イベントに参加する"
}
}
}
},
"이용약관" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Terms of service"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "利用規約"
}
}
}
},
"인기" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Popular"
}
},
"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" : { "localizations" : {
"en" : { "en" : {
@@ -6801,38 +6900,6 @@
} }
} }
}, },
"이벤트 참여하기" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Join the event"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "イベントに参加する"
}
}
}
},
"이용약관" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Terms of service"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "利用規約"
}
}
}
},
"이전화" : { "이전화" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
@@ -6849,22 +6916,6 @@
} }
} }
}, },
"인기" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Popular"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "人気"
}
}
}
},
"인기 시리즈" : { "인기 시리즈" : {
"localizations" : { "localizations" : {
"en" : { "en" : {
@@ -6945,54 +6996,6 @@
} }
} }
}, },
"인기순" : {
"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" : { "localizations" : {
"en" : { "en" : {
@@ -9635,4 +9638,4 @@
} }
}, },
"version" : "1.1" "version" : "1.1"
} }

View File

@@ -14,7 +14,7 @@ struct HomeLatestContentView: View {
let contentList: [AudioContentMainItem] let contentList: [AudioContentMainItem]
let selectTheme: (String) -> Void let selectTheme: (String) -> Void
@State private var selectedTheme = "전체" @State private var selectedTheme = I18n.Category.all
let rows = [ let rows = [
GridItem(.flexible(), alignment: .leading), GridItem(.flexible(), alignment: .leading),

View File

@@ -40,10 +40,10 @@ final class HomeTabViewModel: ObservableObject {
@Published var recommendContentList: [AudioContentMainItem] = [] @Published var recommendContentList: [AudioContentMainItem] = []
private let sortType = [ private let sortType = [
"매출": ContentRankingSortType.REVENUE, I18n.RankingSort.revenue: ContentRankingSortType.REVENUE,
"판매량": ContentRankingSortType.SALES_COUNT, I18n.RankingSort.salesVolume: ContentRankingSortType.SALES_COUNT,
"댓글": ContentRankingSortType.COMMENT_COUNT, I18n.RankingSort.comments: ContentRankingSortType.COMMENT_COUNT,
"좋아요": ContentRankingSortType.LIKE_COUNT I18n.RankingSort.likes: ContentRankingSortType.LIKE_COUNT
] ]
func fetchData() { func fetchData() {
@@ -67,7 +67,7 @@ final class HomeTabViewModel: ObservableObject {
if let data = decoded.data, decoded.success { if let data = decoded.data, decoded.success {
self.liveList = data.liveList self.liveList = data.liveList
self.creatorRanking = data.creatorRanking self.creatorRanking = data.creatorRanking
self.latestContentThemeList = ["전체"] + data.latestContentThemeList self.latestContentThemeList = [I18n.Category.all] + data.latestContentThemeList
self.latestContentList = data.latestContentList self.latestContentList = data.latestContentList
self.eventBannerList = data.bannerList self.eventBannerList = data.bannerList
self.originalAudioDramaList = data.originalAudioDramaList self.originalAudioDramaList = data.originalAudioDramaList
@@ -82,13 +82,13 @@ final class HomeTabViewModel: 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 {
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.errorMessage = I18n.Common.commonError
self.isShowPopup = true self.isShowPopup = true
} }
@@ -100,7 +100,7 @@ final class HomeTabViewModel: ObservableObject {
func getLatestContentByTheme(theme: String) { func getLatestContentByTheme(theme: String) {
isLoading = true isLoading = true
repository.getLatestContentByTheme(theme: theme == "전체" ? "" : theme) repository.getLatestContentByTheme(theme: theme == I18n.Category.all ? "" : theme)
.sink { result in .sink { result in
switch result { switch result {
case .finished: case .finished:
@@ -121,13 +121,13 @@ final class HomeTabViewModel: 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 {
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.errorMessage = I18n.Common.commonError
self.isShowPopup = true self.isShowPopup = true
} }
@@ -160,13 +160,13 @@ final class HomeTabViewModel: 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 {
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.errorMessage = I18n.Common.commonError
self.isShowPopup = true self.isShowPopup = true
} }
@@ -198,13 +198,13 @@ final class HomeTabViewModel: 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 {
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.errorMessage = I18n.Common.commonError
self.isShowPopup = true self.isShowPopup = true
} }
} }
@@ -236,13 +236,13 @@ final class HomeTabViewModel: 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 {
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.errorMessage = I18n.Common.commonError
self.isShowPopup = true self.isShowPopup = true
} }
} }
@@ -274,13 +274,13 @@ final class HomeTabViewModel: 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 {
self.errorMessage = "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다." self.errorMessage = I18n.Common.commonError
self.isShowPopup = true self.isShowPopup = true
} }
} }

View File

@@ -20,8 +20,13 @@ struct HomeWeeklyChartView: View {
let contentList: [GetAudioContentRankingItem] let contentList: [GetAudioContentRankingItem]
let onTapSort: (String) -> Void let onTapSort: (String) -> Void
let sortList = ["매출", "판매량", "댓글", "좋아요"] let sortList = [
@State private var selectedSort = "매출" I18n.RankingSort.revenue,
I18n.RankingSort.salesVolume,
I18n.RankingSort.comments,
I18n.RankingSort.likes
]
@State private var selectedSort = I18n.RankingSort.revenue
var body: some View { var body: some View {
VStack(spacing: 16) { VStack(spacing: 16) {

View File

@@ -0,0 +1,66 @@
//
// I18n.swift
// SodaLive
//
// Created by Junie (AI) on 2025/12/17.
//
import Foundation
// MARK: - I18n
// String Catalog i18n.
// LanguageHeaderProvider.current("ko"|"en"|"ja").
enum I18n {
enum Common {
//
static var apply: String { pick(ko: "적용", en: "Apply", ja: "適用") }
static var confirm: String { pick(ko: "확인", en: "Confirm", ja: "確認") }
static var cancel: String { pick(ko: "취소", en: "Cancel", ja: "キャンセル") }
//
static var settings: String { pick(ko: "설정", en: "Settings", ja: "設定") }
static var commonError: String { pick(ko: "다시 시도해 주세요.\n계속 같은 문제가 발생할 경우 고객센터로 문의 주시기 바랍니다.", en: "Settings", ja: "設定") }
}
enum Category {
static var all: String { pick(ko: "전체", en: "All", ja: "すべて") }
}
enum RankingSort {
// /
static var revenue: String { pick(ko: "매출", en: "Revenue", ja: "売上高") }
static var salesVolume: String { pick(ko: "판매량", en: "Sales", ja: "販売量") }
static var comments: String { pick(ko: "댓글", en: "Comments", ja: "コメント") }
static var likes: String { pick(ko: "좋아요", en: "Likes", ja: "いいね") }
}
enum Tab {
// /
static var character: String { pick(ko: "캐릭터", en: "Character", ja: "キャラクター") }
static var work: String { pick(ko: "작품", en: "Work", ja: "作品") }
static var talk: String { pick(ko: "", en: "Talk", ja: "トーク") }
}
}
// MARK: -
@inline(__always)
private func pick(ko: String, en: String, ja: String) -> String {
switch LanguageHeaderProvider.current {
case "ko": return ko
case "ja": return ja
default: return en
}
}
/*
(ViewModel, Service Text ):
// ViewModel
let title = I18n.Common.all
// View (Text UI )
let menuLabel = I18n.Common.settings
: Text("...") String Catalog .
*/