feat(i18n): 일본어 문자열을 최신화한다

This commit is contained in:
Yu Sung
2026-08-11 20:04:01 +09:00
parent c8636a22f1
commit f4fffa3d70
5 changed files with 1236 additions and 64 deletions

View File

@@ -0,0 +1,307 @@
,KR,JP,,,,
,,ホーム,,,,
,콘텐츠,コンテンツ,,,,
,대화,トーク,,,,
,마이,マイページ,,,,
,추천,おすすめ,,,,
,랭킹,ランキング,,,,
,팔로잉,フォロー中,,,,
,전체,すべて,,,,
,방금 활동한 크리에이터,最近活動したクリエイター,,,,
,최근 데뷔한 크리에이터,新着クリエイター,,,,
,처음부터 함께 성장!,今から推せる,,,,
,크리에이터와 이야기를 나눠요!,クリエイターと話す,,,,
,추천 필모그래피,おすすめフィルモグラフィー,,,,
,또 다른 모습,写真集,,,,
,{{장르}}의 크리에이터,{{ジャンル}}のクリエイター,,,,
,최근 응원이 많은 크리에이터,最近応援の多いクリエイター,,,,
,인기 커뮤니티,人気コミュニティ,,,,
,주간 인기,週間人気,,,,
,지금 뜨는 중,急上昇,,,,
,남성 인기,男性人気,,,,
,여성 인기,女性人気,,,,
,최근 대화,最近のトーク,,,,
,이달의 스케줄,今月のスケジュール,,,,
,최근 소식,最新情報,,,,
,{{크리에이터 이름}}님이 이번 주 랭킹 n위에 올랐어요!,{{크리에이터 이름}}が今週のランキングでn位にランクイン,,,,
,아직 팔로우한 크리에이터가 없어요. 관심 있는 크리에이터를 팔로우해 보세요.,"まだフォローしているクリエイターがいません。
気になるクリエイターをフォローしてみましょう。",,,,
,찾아보기,探す,,,,
,오직 보이스온에서만!,VOICE ON限定,,,,
,새로 올라온 오디오,新着オーディオ,,,,
,추천 시리즈,おすすめシリーズ,,,,
,무료 오디오,無料オーディオ,,,,
,포인트 오디오,ポイントオーディオ,,,,
,최근 댓글이 많은 오디오,最近コメントの多いオーディオ,,,,
,{{키워드}}의 오디오,{{キーワード}}のオーディオ,,,,
,추천 오디오,おすすめオーディオ,,,,
,매출,売上,,,,
,판매량,販売数,,,,
,댓글수,コメント数,,,,
,좋아요,いいね,,,,
,오디오,オーディオ,,,,
,시리즈,シリーズ,,,,
,오리지널,オリジナル,,,,
,무료,無料,,,,
,포인트,ポイント,,,,
,화보,フォト,,,,
,최신순,最新順,,,,
,추천순,おすすめ順,,,,
,인기순,人気順,,,,
,높은 가격순,高い順,,,,
,낮은 가격순,安い順,,,,
,소장순,保有順,,,,
,팔로우,フォロー,,,,
,팔로워,フォロワー,,,,
,대화하기,トークする,,,,
,DM 보내기,DMを送る,,,,
,라이브,ライブ,,,,
,커뮤니티,コミュニティ,,,,
,팬Talk,ファントーク,,,,
,후원,サポート,,,,
,팬레터,ファンレター,,,,
,후원하기,サポートする,,,,
,공지,お知らせ,,,,
,스케줄,スケジュール,,,,
,전체보기,すべて見る,,,,
,전체 오디오의 n%를 소장하고 있어요.,全オーディオのn%を所持しています。,,,,
,전체 화보의 n%를 소장하고 있어요.,全フォトのn%を所持しています。,,,,
,전체소장,全話購入,,,,
,완결,完結,,,,
,연재,連載,,,,
,소장중,保有中,,,,
,리스트형,リスト,,,,
,썸네일형,グリッド,,,,
,구매완료,購入済み,,,,
,삭제,削除,,,,
,신고,通報,,,,
,후원 랭킹,サポートランキング,,,,
,"크리에이터가 라이브를 준비 중입니다.
기대해 주세요!","クリエイターがライブを準備しています。
お楽しみに!",,,,
,"크리에이터가 오디오를 준비 중입니다.
기대해 주세요!","クリエイターがオーディオを準備しています。
お楽しみに!",,,,
,"크리에이터가 시리즈를 준비 중입니다.
기대해 주세요!","クリエイターがシリーズを準備しています。
お楽しみに!",,,,
,"크리에이터가 화보를 준비 중입니다.
기대해 주세요!","クリエイターがフォトを準備しています。
お楽しみに!",,,,
,"크리에이터가 커뮤니티를 준비 중입니다.
기대해 주세요!","クリエイターがコミュニティを準備しています。
お楽しみに!",,,,
,"아직 응원이 없습니다.
처음으로 크리에이터를 응원해 보세요!","まだファンレターがありません。
最初のファンレターを送ってみましょう!",,,,
,응원 남기기,ファンレターを送る,,,,
,"아직 후원이 없습니다.
처음으로 크리에이터를 후원해 보세요!","まだサポートがありません。
最初のサポートをしてみましょう!",,,,
,당신의 첫 응원을 기다리고 있어요!,あなたの最初のファンレターを待っています!,,,,
,댓글,コメント,,,,
,취소,キャンセル,,,,
,보내기,送信,,,,
,입력 종료,入力終了,,,,
,"입력을 종료할까요?
지금 나가면 입력한 내용이 저장되지 않아요.","入力を終了しますか?
終了すると、入力内容は保存されません。",,,,
,종료,終了,,,,
,계속 작성,続ける,,,,
,응원 삭제,ファンレターを削除,,,,
,"응원을 삭제할까요?
삭제 시 크리에이터의 답글도 같이 사라져요.","ファンレターを削除しますか?
削除すると、クリエイターからの返信も削除されます。",,,,
,오늘,今日,,,,
,지금,,,,,
,지난,終了,,,,
,"아직 대화가 없어요.
크리에이터와 이야기를 시작해 보세요.","まだ会話がありません。
クリエイターと話してみましょう。",,,,
,"아직 나눈 AI 채팅이 없어요.
크리에이터와 대화를 시작해 보세요.","まだAIチャットがありません。
クリエイターと会話を始めてみましょう。",,,,
,"아직 나눈 대화가 없어요.
좋아하는 크리에이터에게 메세지를 보내보세요.","まだメッセージがありません。
好きなクリエイターにメッセージを送ってみましょう。",,,,
,크리에이터의 이름을 입력하세요,クリエイター名を入力,,,,
,대화 시작,トーク開始,,,,
,{{크리에이터이름}}님과 AI 채팅 혹은 DM을 시작해 볼까요?,{{クリエイター名}}とAIチャットまたはDMを始めてみませんか,,,,
,AI 채팅하기,AIチャット,,,,
,채팅 설정,チャット設定,,,,
,이미지 보관함,ギャラリー,,,,
,배경 이미지 설정,背景設定,,,,
,채팅 초기화,チャットを初期化,,,,
,신규 크리에이터,新着クリエイター,,,,
,나의 크리에이터,マイクリエイター,,,,
,AI 캐릭터 채팅,AIキャラクターチャット,,,,
,팔로우 해제,フォロー解除,,,,
,"팔로우를 해제할까요?
{{크리에이터이름}}의 소식을 받을 수 없어요.","{{크리에이터이름}}からの最新情報を受け取れなくなります。
フォローを解除しますか?",,,,
,해제하기,解除する,,,,
,검색어를 입력하세요,キーワードを入力,,,,
,전체삭제,すべて削除,,,,
,최근 검색,最近の検索,,,,
,인기 검색어,急上昇ワード,,,,
,AI 채팅 인기 검색 키워드,AIチャット急上昇ワード,,,,
,시리즈 인기 검색 키워드,シリーズ急上昇ワード,,,,
,오디오 인기 검색 키워드,オーディオ急上昇ワード,,,,
,키워드,キーワード,,,,
,검색 결과,検索結果,,,,
,정확도순,関連度順,,,,
,많이 찾는 크리에이터,人気のクリエイター,,,,
,"관련 크리에이터가 없어요.
다른 검색어로 다시 찾아보세요.","該当するクリエイターがいません。
別のキーワードで検索してください。",,,,
,"관련 시리즈가 없어요.
다른 검색어로 다시 찾아보세요.","該当するシリーズがありません。
別のキーワードで検索してください。",,,,
,"관련 화보가 없어요.
다른 검색어로 다시 찾아보세요.","該当するフォトがありません。
別のキーワードで検索してください。",,,,
,"관련 키워드가 없어요.
다른 검색어로 다시 찾아보세요.","該当するキーワードがありません。
別のキーワードで検索してください。",,,,
,라이브 시작하기,ライブを開始,,,,
,오디오 올리기,オーディオを投稿,,,,
,커뮤니티 글 올리기,コミュニティ投稿,,,,
,이메일을 입력해 주세요,メールアドレスを入力してください,,,,
,이메일,メールアドレス,,,,
,이용약관,利用規約,,,,
,개인정보수집 및 이용동의,個人情報の収集・利用への同意,,,,
,올바른 이메일을 입력해 주세요,正しいメールアドレスを入力してください,,,,
,다음으로,次へ,,,,
,이미 가입된 이메일이에요,登録済みのメールアドレスです,,,,
,비밀번호를 입력해 주세요,パスワードを入力してください,,,,
,비밀번호,パスワード,,,,
,"8자 이상 (영문 대/소문자, 특수문자 포함)",8文字以上英大文字・小文字・記号を含む,,,,
,완료,完了,,,,
,"8자 이상, 영문 대/소문자와 특수문자를 포함해 주세요",8文字以上、英大文字・小文字・記号を含めてください,,,,
,이메일로 로그인하기,メールアドレスでログイン,,,,
,로그인,ログイン,,,,
,가입되지 않은 이메일이에요,登録されていないメールアドレスです,,,,
,입력한 비밀번호를 다시 확인해 주세요,パスワードをもう一度確認してください,,,,
,인증코드를 입력해 주세요,認証コードを入力してください,,,,
,{email}로 인증코드를 보냈어요,{email}に認証コードを送信しました,,,,
,인증코드,認証コード,,,,
,0:00 후에 인증코드 다시 보내기,0:00後に認証コードを再送する,,,,
,인증 가능한 시간을 초과했어요,認証可能時間を超過しました,,,,
,인증코드 다시 보내기,認証コードを再送する,,,,
,올바른 인증코드를 입력해 주세요,正しい認証コードを入力してください,,,,
,새 비밀번호를 입력해 주세요,新しいパスワードを入力してください,,,,
,기존 비밀번호와 다르게 설정해 주세요,現在のパスワードとは異なるものを設定してください,,,,
,비밀번호 설정 완료!,パスワード設定完了!,,,,
,"비밀번호 설정을 완료했어요.
다시 로그인해 주세요.","パスワードを設定しました。
もう一度ログインしてください。",,,,
,재설정 종료,再設定を終了,,,,
,"지금 나가면 현재 진행중인 재설정이 종료되고,
처음부터 다시 진행해야 해요.","終了すると、進行中の再設定が終了し、
最初からやり直す必要があります。",,,,
,계속 재설정,再設定を続ける,,,,
,AI 채팅,AIチャット,,,,
,전체 크리에이터,すべてのクリエイター,,,,
,필수,必須,,,,
,가입한 이메일을 입력해 주세요,"登録メールアドレスを
入力してください",,,,
,존재하지 않는 이메일이에요,登録されていないメールアドレスです,,,,
,모두 팔로우하기,すべてフォロー,,,,
,대여중,レンタル中,,,,
,데뷔,デビュー,,,,
,라이브 총 진행 수,ライブ配信回数,,,,
,라이브 누적 진행 시간,ライブ累計配信時間,,,,
,라이브 누적 참여자,ライブ累計参加者数,,,,
,고정 해제,固定を解除,,,,
,수정하기,編集,,,,
,삭제하기,削除,,,,
,크리에이터에게만 보여요.,クリエイターにのみ表示されます。,,,,
,답글쓰기,返信する,,,,
,신고하기,通報する,,,,
,댓글을 입력하세요,コメントを入力,,,,
,크리에이터에게 응원의 메세지를 보내주세요!,クリエイターへファンレターを送りましょう!,,,,
,답글을 삭제할까요?,返信を削除しますか?,,,,
,답글 삭제,返信を削除,,,,
,크리에이터,クリエイター,,,,
,시리즈 자세히 보기,シリーズの詳細を見る,,,,
,소개,紹介,,,,
,장르,ジャンル,,,,
,연령 제한,年齢制限,,,,
,소장,購入,,,,
,페이지 수,ページ数,,,,
,발매일,発売日,,,,
,크리에이터의 다른 화보,このクリエイターの他のフォト,,,,
,{{화보이름 12자 ...}}와 비슷한 화보,「{{화보이름 12자 ...}}」に似たフォト,,,,
,[Premium Photo]의 다른 화보,「Premium Photo」の他のフォト,,,,
,소장하기,購入する,,,,
,스크랩,クリップ,,,,
,"마음에 드는 페이지를 스크랩하여
감상해 보세요!","お気に入りのページをクリップして
楽しみましょう!",,,,
,마지막 페이지,最後のページ,,,,
,"{{메거진 이름 12자 초과시...}}은 어떠셨나요?
후기를 댓글로 남겨보세요.","「{{雑誌名...}}」はいかがでしたか
感想をコメントでお聞かせください。",,,,
,댓글 쓰기,コメントを書く,,,,
,첫 페이지에요.,最初のページです。,,,,
,오래된순,古い順,,,,
,보관함,ライブラリ,,,,
,구매,購入,,,,
,재생목록,プレイリスト,,,,
,최근,最近,,,,
,제목순,タイトル順,,,,
,발매순,発売日順,,,,
,대여,レンタル,,,,
,업로드순,アップロード順,,,,
,"구매한 오디오가 없어요.
관심있는 오디오를 구매해 보세요!","購入したオーディオはありません。
気になるオーディオを購入してみましょう!",,,,
,"구매한 화보가 없어요.
관심있는 화보를 구매해 보세요!","購入したフォトはありません。
気になるフォトを購入してみましょう!",,,,
,"구매한 커뮤니티 글이 없어요.
좋아하는 크리에이터의 글을 구매해 보세요!","購入したコミュニティ投稿はありません。
お気に入りのクリエイターの投稿を購入してみましょう!",,,,
,나중에 들을 오디오,あとで聴く,,,,
,"좋아요한 오디오가 없어요.
마음에 드는 오디오에 좋아요를 남겨 보세요!","「いいね」したオーディオはありません。
お気に入りのオーディオに「いいね」してみましょう!",,,,
,"좋아요한 화보가 없어요.
마음에 드는 화보에 좋아요를 남겨 보세요!","「いいね」したフォトはありません。
お気に入りのフォトに「いいね」してみましょう!",,,,
,"좋아요한 커뮤니티 글이 없어요.
마음에 드는 글에 좋아요를 남겨 보세요!","「いいね」した投稿はありません。
お気に入りの投稿に「いいね」してみましょう!",,,,
,"최근 본 콘텐츠가 없어요.
새로운 콘텐츠를 만나보세요!","最近見たコンテンツはありません。
新しいコンテンツを見つけましょう!",,,,
,"최근 본 오디오가 없어요.
새로운 오디오를 만나보세요!","最近聴いたオーディオはありません。
新しいオーディオを見つけましょう!",,,,
,"최근 본 시리즈가 없어요.
새로운 시리즈를 만나보세요!","最近見たシリーズはありません。
しいシリーズを見つけましょう!",,,,
,"최근 본 화보가 없어요.
새로운 화보를 만나보세요!","最近見たフォトはありません。
新しいフォトを見つけましょう!",,,,
,충전하기,チャージ,,,,
,현재 보유한 캔,現在のカン,,,,
,사용할 캔,使用するカン,,,,
,사용할 포인트,使用するポイント,,,,
,*포인트 일부를 차감하여 대여합니다.,*ポイントを使用してレンタルします。,,,,
,캔이 부족해요! 충전 후 이용해 주세요.,カンが不足しています。チャージしてご利用ください。,,,,
,소장이 완료되었어요!,購入が完了しました!,,,,
,대여가 완료되었어요!,レンタルが完了しました!,,,,
,구매에 실패했어요. 다시 시도해 주세요.,購入に失敗しました。もう一度お試しください。,,,,
,오늘 하루 보지 않기,今日一日は表示しない,,,,
,닫기,閉じる,,,,
,콘텐츠 보호를 위해 캡처를 지원하지 않아요.,コンテンツ保護のため、スクリーンショットはご利用いただけません。,,,,
,답글을 입력하세요,返信を入力,,,,
,전체 인기,人気ランキング,,,,
,현재 보유,所持数,,,,
,활동,アクティビティ,,,,
,익명,匿名,,,,
,DM 확인하기,DMを確認,,,,
,예정,予定,,,,
,대화 찾기,トークを探す,,,,
,{요일}요 인기 시리즈,{요일}曜人気シリーズ,,,,
1 KR JP
2 ホーム
3 콘텐츠 コンテンツ
4 대화 トーク
5 마이 マイページ
6 추천 おすすめ
7 랭킹 ランキング
8 팔로잉 フォロー中
9 전체 すべて
10 방금 활동한 크리에이터 最近活動したクリエイター
11 최근 데뷔한 크리에이터 新着クリエイター
12 처음부터 함께 성장! 今から推せる
13 크리에이터와 이야기를 나눠요! クリエイターと話す
14 추천 필모그래피 おすすめフィルモグラフィー
15 또 다른 모습 写真集
16 {{장르}}의 크리에이터 {{ジャンル}}のクリエイター
17 최근 응원이 많은 크리에이터 最近応援の多いクリエイター
18 인기 커뮤니티 人気コミュニティ
19 주간 인기 週間人気
20 지금 뜨는 중 急上昇
21 남성 인기 男性人気
22 여성 인기 女性人気
23 최근 대화 最近のトーク
24 이달의 스케줄 今月のスケジュール
25 최근 소식 最新情報
26 {{크리에이터 이름}}님이 이번 주 랭킹 n위에 올랐어요! {{크리에이터 이름}}が今週のランキングでn位にランクイン!
27 아직 팔로우한 크리에이터가 없어요. 관심 있는 크리에이터를 팔로우해 보세요. まだフォローしているクリエイターがいません。 気になるクリエイターをフォローしてみましょう。
28 찾아보기 探す
29 오직 보이스온에서만! VOICE ON限定
30 새로 올라온 오디오 新着オーディオ
31 추천 시리즈 おすすめシリーズ
32 무료 오디오 無料オーディオ
33 포인트 오디오 ポイントオーディオ
34 최근 댓글이 많은 오디오 最近コメントの多いオーディオ
35 {{키워드}}의 오디오 {{キーワード}}のオーディオ
36 추천 오디오 おすすめオーディオ
37 매출 売上
38 판매량 販売数
39 댓글수 コメント数
40 좋아요 いいね
41 오디오 オーディオ
42 시리즈 シリーズ
43 오리지널 オリジナル
44 무료 無料
45 포인트 ポイント
46 화보 フォト
47 최신순 最新順
48 추천순 おすすめ順
49 인기순 人気順
50 높은 가격순 高い順
51 낮은 가격순 安い順
52 소장순 保有順
53 팔로우 フォロー
54 팔로워 フォロワー
55 대화하기 トークする
56 DM 보내기 DMを送る
57 라이브 ライブ
58 커뮤니티 コミュニティ
59 팬Talk ファントーク
60 후원 サポート
61 팬레터 ファンレター
62 후원하기 サポートする
63 공지 お知らせ
64 스케줄 スケジュール
65 전체보기 すべて見る
66 전체 오디오의 n%를 소장하고 있어요. 全オーディオのn%を所持しています。
67 전체 화보의 n%를 소장하고 있어요. 全フォトのn%を所持しています。
68 전체소장 全話購入
69 완결 完結
70 연재 連載
71 소장중 保有中
72 리스트형 リスト
73 썸네일형 グリッド
74 구매완료 購入済み
75 삭제 削除
76 신고 通報
77 후원 랭킹 サポートランキング
78 크리에이터가 라이브를 준비 중입니다. 기대해 주세요! クリエイターがライブを準備しています。 お楽しみに!
79 크리에이터가 오디오를 준비 중입니다. 기대해 주세요! クリエイターがオーディオを準備しています。 お楽しみに!
80 크리에이터가 시리즈를 준비 중입니다. 기대해 주세요! クリエイターがシリーズを準備しています。 お楽しみに!
81 크리에이터가 화보를 준비 중입니다. 기대해 주세요! クリエイターがフォトを準備しています。 お楽しみに!
82 크리에이터가 커뮤니티를 준비 중입니다. 기대해 주세요! クリエイターがコミュニティを準備しています。 お楽しみに!
83 아직 응원이 없습니다. 처음으로 크리에이터를 응원해 보세요! まだファンレターがありません。 最初のファンレターを送ってみましょう!
84 응원 남기기 ファンレターを送る
85 아직 후원이 없습니다. 처음으로 크리에이터를 후원해 보세요! まだサポートがありません。 最初のサポートをしてみましょう!
86 당신의 첫 응원을 기다리고 있어요! あなたの最初のファンレターを待っています!
87 댓글 コメント
88 취소 キャンセル
89 보내기 送信
90 입력 종료 入力終了
91 입력을 종료할까요? 지금 나가면 입력한 내용이 저장되지 않아요. 入力を終了しますか? 終了すると、入力内容は保存されません。
92 종료 終了
93 계속 작성 続ける
94 응원 삭제 ファンレターを削除
95 응원을 삭제할까요? 삭제 시 크리에이터의 답글도 같이 사라져요. ファンレターを削除しますか? 削除すると、クリエイターからの返信も削除されます。
96 오늘 今日
97 지금
98 지난 終了
99 아직 대화가 없어요. 크리에이터와 이야기를 시작해 보세요. まだ会話がありません。 クリエイターと話してみましょう。
100 아직 나눈 AI 채팅이 없어요. 크리에이터와 대화를 시작해 보세요. まだAIチャットがありません。 クリエイターと会話を始めてみましょう。
101 아직 나눈 대화가 없어요. 좋아하는 크리에이터에게 메세지를 보내보세요. まだメッセージがありません。 好きなクリエイターにメッセージを送ってみましょう。
102 크리에이터의 이름을 입력하세요 クリエイター名を入力
103 대화 시작 トーク開始
104 {{크리에이터이름}}님과 AI 채팅 혹은 DM을 시작해 볼까요? {{クリエイター名}}とAIチャットまたはDMを始めてみませんか?
105 AI 채팅하기 AIチャット
106 채팅 설정 チャット設定
107 이미지 보관함 ギャラリー
108 배경 이미지 설정 背景設定
109 채팅 초기화 チャットを初期化
110 신규 크리에이터 新着クリエイター
111 나의 크리에이터 マイクリエイター
112 AI 캐릭터 채팅 AIキャラクターチャット
113 팔로우 해제 フォロー解除
114 팔로우를 해제할까요? {{크리에이터이름}}의 소식을 받을 수 없어요. {{크리에이터이름}}からの最新情報を受け取れなくなります。 フォローを解除しますか?
115 해제하기 解除する
116 검색어를 입력하세요 キーワードを入力
117 전체삭제 すべて削除
118 최근 검색 最近の検索
119 인기 검색어 急上昇ワード
120 AI 채팅 인기 검색 키워드 AIチャット急上昇ワード
121 시리즈 인기 검색 키워드 シリーズ急上昇ワード
122 오디오 인기 검색 키워드 オーディオ急上昇ワード
123 키워드 キーワード
124 검색 결과 検索結果
125 정확도순 関連度順
126 많이 찾는 크리에이터 人気のクリエイター
127 관련 크리에이터가 없어요. 다른 검색어로 다시 찾아보세요. 該当するクリエイターがいません。 別のキーワードで検索してください。
128 관련 시리즈가 없어요. 다른 검색어로 다시 찾아보세요. 該当するシリーズがありません。 別のキーワードで検索してください。
129 관련 화보가 없어요. 다른 검색어로 다시 찾아보세요. 該当するフォトがありません。 別のキーワードで検索してください。
130 관련 키워드가 없어요. 다른 검색어로 다시 찾아보세요. 該当するキーワードがありません。 別のキーワードで検索してください。
131 라이브 시작하기 ライブを開始
132 오디오 올리기 オーディオを投稿
133 커뮤니티 글 올리기 コミュニティ投稿
134 이메일을 입력해 주세요 メールアドレスを入力してください
135 이메일 メールアドレス
136 이용약관 利用規約
137 개인정보수집 및 이용동의 個人情報の収集・利用への同意
138 올바른 이메일을 입력해 주세요 正しいメールアドレスを入力してください
139 다음으로 次へ
140 이미 가입된 이메일이에요 登録済みのメールアドレスです
141 비밀번호를 입력해 주세요 パスワードを入力してください
142 비밀번호 パスワード
143 8자 이상 (영문 대/소문자, 특수문자 포함) 8文字以上(英大文字・小文字・記号を含む)
144 완료 完了
145 8자 이상, 영문 대/소문자와 특수문자를 포함해 주세요 8文字以上、英大文字・小文字・記号を含めてください
146 이메일로 로그인하기 メールアドレスでログイン
147 로그인 ログイン
148 가입되지 않은 이메일이에요 登録されていないメールアドレスです
149 입력한 비밀번호를 다시 확인해 주세요 パスワードをもう一度確認してください
150 인증코드를 입력해 주세요 認証コードを入力してください
151 {email}로 인증코드를 보냈어요 {email}に認証コードを送信しました
152 인증코드 認証コード
153 0:00 후에 인증코드 다시 보내기 0:00後に認証コードを再送する
154 인증 가능한 시간을 초과했어요 認証可能時間を超過しました
155 인증코드 다시 보내기 認証コードを再送する
156 올바른 인증코드를 입력해 주세요 正しい認証コードを入力してください
157 새 비밀번호를 입력해 주세요 新しいパスワードを入力してください
158 기존 비밀번호와 다르게 설정해 주세요 現在のパスワードとは異なるものを設定してください
159 비밀번호 설정 완료! パスワード設定完了!
160 비밀번호 설정을 완료했어요. 다시 로그인해 주세요. パスワードを設定しました。 もう一度ログインしてください。
161 재설정 종료 再設定を終了
162 지금 나가면 현재 진행중인 재설정이 종료되고, 처음부터 다시 진행해야 해요. 終了すると、進行中の再設定が終了し、 最初からやり直す必要があります。
163 계속 재설정 再設定を続ける
164 AI 채팅 AIチャット
165 전체 크리에이터 すべてのクリエイター
166 필수 必須
167 가입한 이메일을 입력해 주세요 登録メールアドレスを 入力してください
168 존재하지 않는 이메일이에요 登録されていないメールアドレスです
169 모두 팔로우하기 すべてフォロー
170 대여중 レンタル中
171 데뷔 デビュー
172 라이브 총 진행 수 ライブ配信回数
173 라이브 누적 진행 시간 ライブ累計配信時間
174 라이브 누적 참여자 ライブ累計参加者数
175 고정 해제 固定を解除
176 수정하기 編集
177 삭제하기 削除
178 크리에이터에게만 보여요. クリエイターにのみ表示されます。
179 답글쓰기 返信する
180 신고하기 通報する
181 댓글을 입력하세요 コメントを入力
182 크리에이터에게 응원의 메세지를 보내주세요! クリエイターへファンレターを送りましょう!
183 답글을 삭제할까요? 返信を削除しますか?
184 답글 삭제 返信を削除
185 크리에이터 クリエイター
186 시리즈 자세히 보기 シリーズの詳細を見る
187 소개 紹介
188 장르 ジャンル
189 연령 제한 年齢制限
190 소장 購入
191 페이지 수 ページ数
192 발매일 発売日
193 크리에이터의 다른 화보 このクリエイターの他のフォト
194 {{화보이름 12자 ...}}와 비슷한 화보 「{{화보이름 12자 ...}}」に似たフォト
195 [Premium Photo]의 다른 화보 「Premium Photo」の他のフォト
196 소장하기 購入する
197 스크랩 クリップ
198 마음에 드는 페이지를 스크랩하여 감상해 보세요! お気に入りのページをクリップして 楽しみましょう!
199 마지막 페이지 最後のページ
200 {{메거진 이름 12자 초과시...}}은 어떠셨나요? 후기를 댓글로 남겨보세요. 「{{雑誌名...}}」はいかがでしたか 感想をコメントでお聞かせください。
201 댓글 쓰기 コメントを書く
202 첫 페이지에요. 最初のページです。
203 오래된순 古い順
204 보관함 ライブラリ
205 구매 購入
206 재생목록 プレイリスト
207 최근 最近
208 제목순 タイトル順
209 발매순 発売日順
210 대여 レンタル
211 업로드순 アップロード順
212 구매한 오디오가 없어요. 관심있는 오디오를 구매해 보세요! 購入したオーディオはありません。 気になるオーディオを購入してみましょう!
213 구매한 화보가 없어요. 관심있는 화보를 구매해 보세요! 購入したフォトはありません。 気になるフォトを購入してみましょう!
214 구매한 커뮤니티 글이 없어요. 좋아하는 크리에이터의 글을 구매해 보세요! 購入したコミュニティ投稿はありません。 お気に入りのクリエイターの投稿を購入してみましょう!
215 나중에 들을 오디오 あとで聴く
216 좋아요한 오디오가 없어요. 마음에 드는 오디오에 좋아요를 남겨 보세요! 「いいね」したオーディオはありません。 お気に入りのオーディオに「いいね」してみましょう!
217 좋아요한 화보가 없어요. 마음에 드는 화보에 좋아요를 남겨 보세요! 「いいね」したフォトはありません。 お気に入りのフォトに「いいね」してみましょう!
218 좋아요한 커뮤니티 글이 없어요. 마음에 드는 글에 좋아요를 남겨 보세요! 「いいね」した投稿はありません。 お気に入りの投稿に「いいね」してみましょう!
219 최근 본 콘텐츠가 없어요. 새로운 콘텐츠를 만나보세요! 最近見たコンテンツはありません。 新しいコンテンツを見つけましょう!
220 최근 본 오디오가 없어요. 새로운 오디오를 만나보세요! 最近聴いたオーディオはありません。 新しいオーディオを見つけましょう!
221 최근 본 시리즈가 없어요. 새로운 시리즈를 만나보세요! 最近見たシリーズはありません。 しいシリーズを見つけましょう!
222 최근 본 화보가 없어요. 새로운 화보를 만나보세요! 最近見たフォトはありません。 新しいフォトを見つけましょう!
223 충전하기 チャージ
224 현재 보유한 캔 現在のカン
225 사용할 캔 使用するカン
226 사용할 포인트 使用するポイント
227 *포인트 일부를 차감하여 대여합니다. *ポイントを使用してレンタルします。
228 캔이 부족해요! 충전 후 이용해 주세요. カンが不足しています。チャージしてご利用ください。
229 소장이 완료되었어요! 購入が完了しました!
230 대여가 완료되었어요! レンタルが完了しました!
231 구매에 실패했어요. 다시 시도해 주세요. 購入に失敗しました。もう一度お試しください。
232 오늘 하루 보지 않기 今日一日は表示しない
233 닫기 閉じる
234 콘텐츠 보호를 위해 캡처를 지원하지 않아요. コンテンツ保護のため、スクリーンショットはご利用いただけません。
235 답글을 입력하세요 返信を入力
236 전체 인기 人気ランキング
237 현재 보유 所持数
238 활동 アクティビティ
239 익명 匿名
240 DM 확인하기 DMを確認
241 예정 予定
242 대화 찾기 トークを探す
243 {요일}요 인기 시리즈 {요일}曜人気シリーズ

View File

@@ -0,0 +1,548 @@
# 일본어 string_resource 반영 Goal 실행형 구현 계획
| 문서 항목 | 내용 |
|---|---|
| 상태 | 구현 완료 |
| 작성일 | `2026-08-11` |
| 요구사항 기준 | `docs/20260811_일본어_string_resource_반영/prd.md` |
| API 기준 | 해당 없음 |
| 현재 Phase | Phase 2 일본어 리소스 반영 완료 |
| 현재 활성 Goal | 없음 |
## 목표
CSV의 KR/JP 문자열 리소스를 현재 iOS `I18n.swift` 구조에 맞춰 안전하게 반영하되, 기존 한국어 리소스가 없는 항목은 신규 리소스로 추가하지 않는다.
## 현재 상태
| Phase | 상태 | 완료 Task | 활성/다음 Goal | 차단 또는 남은 조건 |
|---:|---|---:|---|---|
| 1 | 완료 | `3/3` | `P1-GATE` 완료 | 없음 |
| 2 | 완료 | `3/3` | `P2-GATE` 완료 | 없음 |
- 동시에 하나의 미완료 goal만 운용한다.
- 완료된 Task와 검증 기록은 되돌리거나 삭제하지 않는다. 후속 수정은 회귀 수정 Task와 새 goal ID를 추가한다.
- 사용자가 명시적으로 요청하지 않으면 goal에 token budget을 설정하지 않는다.
## 범위
### 포함
- `docs/20260811_일본어_string_resource_반영/kr_jp_string_resource.csv`의 KR/JP 242개 데이터 행 분석.
- `SodaLive/Sources/I18n/I18n.swift`의 기존 `pick(ko:en:ja:)` 항목 중 CSV KR과 exact 또는 placeholder 정규화 기준으로 매칭되는 항목의 일본어 값 갱신 계획.
- CSV 셀 안의 실제 줄바꿈과 HTML br 표기를 Swift 문자열 줄바꿈 escape `\n`으로 변환하는 계획.
- placeholder 후보와 오탈자 후보의 확정 결정 기록.
- 구현 후 `SodaLive`, `SodaLive-dev` Debug 빌드와 일본어 대표 화면 수동 QA 계획.
### 제외
- 이 문서 작성 턴에서 코드 수정.
- `String Catalog` 신규 도입 또는 `I18n.swift` 구조 개편.
- CSV에 없는 영어 번역 작성.
- 기존 한국어 리소스가 없는 CSV 항목의 신규 리소스 추가.
- UI 레이아웃, 폰트, API, 결제 SDK 입력값 변경.
## 기술적 제약
- 기술 스택: Swift, SwiftUI, Xcode, CocoaPods, `SodaLive.xcworkspace`.
- 아키텍처: 기존 `I18n.Module.Domain.Role` 네임스페이스와 `pick(ko:en:ja:)` 헬퍼를 유지한다.
- 데이터·보안: 토큰, 인증 헤더, API path, SDK 고정값은 번역 대상으로 보지 않는다.
- 호환성: 기존 iOS 앱 스킴 `SodaLive`, `SodaLive-dev`를 기준으로 검증한다.
- 의존성: 신규 dependency를 추가하지 않는다.
- 계약: 제공되지 않은 영어 문구, enum, 서버 상태, 오류 키를 추정하지 않는다. 기존 한국어 리소스가 exact 또는 placeholder 정규화 기준으로 매칭되지 않는 항목은 신규 키를 만들지 않는다.
- 검증: focused 정적 점검에서 시작해 `xcodebuild` 빌드와 수동 QA로 확장한다.
- 테스트 제약: 현재 가이드 기준 앱 타깃 중심 구성이고 테스트 번들 타깃이 확인되지 않으므로, 테스트 액션 미구성은 코드 실패로 판정하지 않는다.
## Task TDD 작성 규칙
문자열 리소스 반영은 대부분 정적 데이터 변경이며 현재 테스트 타깃이 확인되지 않는다. 따라서 구현 Task는 TDD 예외 사유와 대체 검증 방법을 명시한다. 자동 테스트가 추가 가능한 구조가 확인되면 가장 작은 실패 test를 먼저 작성하고 `RED → GREEN → REFACTOR` 순서를 따른다.
## Phase 1 매핑 확정
**Phase 결과:** CSV 242행의 처리 방식을 `기존 키 갱신`, `placeholder 정규화 후 기존 키 갱신`, `오탈자 보정 후 기존 키 갱신`, `기존 리소스 없음으로 제외` 중 하나로 분류한다.
**선행조건:** PRD의 Open Questions 사용자 결정이 반영되어 있다.
**Phase 완료 조건:** `P1-T1`~`P1-T3``P1-GATE` 완료, Progress 기록 누적.
### 구현 항목
#### Task 1.1 CSV 파싱 기준 확정
**Goal 실행 `P1-T1`:** CSV 데이터 행 수, 누락, CSV 셀 안의 실제 줄바꿈, HTML br 표기, placeholder 후보를 재현 가능한 명령으로 확정한다.
- **시작 조건:** `kr_jp_string_resource.csv` 존재.
- **완료 증거:** CSV 파싱 결과가 Progress에 기록되고 PRD의 수치와 일치한다.
- **범위 밖:** 앱 코드 수정.
- **TDD 예외 사유:** production 동작을 변경하지 않는 read-only 데이터 점검 Task다.
- **대체 검증 방법:** Python `csv.reader`로 CSV를 파싱해 행 수와 후보 목록을 출력한다.
**Files:**
- Read: `docs/20260811_일본어_string_resource_반영/kr_jp_string_resource.csv`
- Modify: `docs/20260811_일본어_string_resource_반영/plan-task.md`
**Interfaces:**
- Consumes: CSV `KR`, `JP` 컬럼.
- Produces: Phase 1에서 사용할 행 수, CSV 실제 줄바꿈, HTML br 표기와 품질 후보 목록.
- [x] CSV를 정규 파서로 읽어 데이터 행 수를 확인한다.
```bash
python3 - <<'PY'
import csv
from pathlib import Path
p = Path('docs/20260811_일본어_string_resource_반영/kr_jp_string_resource.csv')
with p.open(newline='', encoding='utf-8') as f:
rows = list(csv.reader(f))
data = rows[1:]
print(len(data))
print(sum(1 for row in data if len(row) < 3 or not row[1].strip() or not row[2].strip()))
PY
```
**Expected:** 첫 줄 `242`, 둘째 줄 `0`.
- [x] CSV 셀 안의 실제 줄바꿈 포함 행과 placeholder 유사 행을 산출해 Progress에 기록한다.
```bash
python3 - <<'PY'
import csv
from pathlib import Path
p = Path('docs/20260811_일본어_string_resource_반영/kr_jp_string_resource.csv')
with p.open(newline='', encoding='utf-8') as f:
reader = csv.reader(f)
next(reader)
rows = [(i, row[1], row[2]) for i, row in enumerate(reader, start=2)]
print('multiline', sum('\n' in kr or '\n' in jp for _, kr, jp in rows))
print('placeholder_like', sum(any(t in kr + jp for t in ['{{', '}}', '{', '}', 'n%', 'n위', '0:00']) for _, kr, jp in rows))
PY
```
**Expected:** `multiline 33`, `placeholder_like 12`.
`multiline` 대상은 Swift 코드 반영 시 CSV 셀 안의 실제 줄바꿈을 그대로 붙여넣지 않고 문자열 escape `\n`으로 작성한다.
- [x] HTML br 표기 수를 산출해 Progress에 기록한다.
```bash
python3 - <<'PY'
import csv
from pathlib import Path
p = Path('docs/20260811_일본어_string_resource_반영/kr_jp_string_resource.csv')
tag = chr(60) + 'br' + chr(62)
with p.open(newline='', encoding='utf-8') as f:
reader = csv.reader(f)
next(reader)
rows = [(i, row[1], row[2]) for i, row in enumerate(reader, start=2)]
print('html_br_like', sum(tag.lower() in (kr + jp).lower() for _, kr, jp in rows))
PY
```
**Expected:** 현재 CSV 기준 `html_br_like 0`. 향후 값이 1 이상이면 해당 항목은 앱 문자열에 HTML br literal이 아니라 `\n`으로 반영한다.
#### Task 1.2 기존 `I18n.swift` 매칭 목록 확정
**Goal 실행 `P1-T2`:** CSV KR과 기존 `I18n.swift``ko:` literal 및 placeholder 정규화 매칭 수를 확정한다.
- **시작 조건:** `P1-T1` 완료.
- **완료 증거:** exact 매칭, placeholder 정규화 추가 매칭, 기존 리소스 없음 제외 대상과 중복 JP 상이 항목 수가 Progress에 기록된다.
- **범위 밖:** `ja` 값 수정.
- **TDD 예외 사유:** production 동작을 변경하지 않는 read-only 매핑 점검 Task다.
- **대체 검증 방법:** CSV KR literal과 placeholder 정규화 문자열을 Swift `ko:` literal 및 interpolation 정규화 문자열과 대조한다.
**Files:**
- Read: `docs/20260811_일본어_string_resource_반영/kr_jp_string_resource.csv`
- Read: `SodaLive/Sources/I18n/I18n.swift`
- Modify: `docs/20260811_일본어_string_resource_반영/plan-task.md`
**Interfaces:**
- Consumes: CSV 행 목록, `I18n.swift` source.
- Produces: exact 매칭 수, placeholder 정규화 추가 매칭 수, 기존 리소스 없음 제외 대상 수, 중복 JP 상이 항목 수.
- [x] 기존 `ko:` literal 매칭 수와 placeholder 정규화 매칭 수를 산출한다.
```bash
python3 - <<'PY'
import csv
from pathlib import Path
csv_path = Path('docs/20260811_일본어_string_resource_반영/kr_jp_string_resource.csv')
i18n = Path('SodaLive/Sources/I18n/I18n.swift').read_text(encoding='utf-8')
matched = 0
missing = 0
with csv_path.open(newline='', encoding='utf-8') as f:
reader = csv.reader(f)
next(reader)
for row in reader:
kr = row[1]
swift = kr.replace('\\', '\\\\').replace('"', '\\"').replace('\n', '\\n')
if f'ko: "{swift}"' in i18n:
matched += 1
else:
missing += 1
print('matched', matched)
print('missing', missing)
PY
```
**Expected:** 현재 기준 `matched 103`, `missing 139`. placeholder 정규화 스캔은 `direct 103`, `normalized_only 0`, `duplicate_different_ja 12`를 함께 기록한다.
- [x] `missing` 항목은 신규 키로 만들지 않고 `기존 리소스 없음으로 제외` 처리한다.
#### Task 1.3 질문 결정 반영
**Goal 실행 `P1-T3`:** PRD Open Questions에 반영된 사용자 결정을 기준으로 구현 가능 범위를 확정한다.
- **시작 조건:** `P1-T2` 완료.
- **완료 증거:** `OQ-001`~`OQ-005`가 확정으로 표시되고 구현 가능 범위가 정해진다.
- **범위 밖:** 기존 한국어 리소스가 없는 항목의 신규 리소스 추가.
- **TDD 예외 사유:** 제품·번역 의사결정 Task다.
- **대체 검증 방법:** PRD Open Questions와 회신 내용을 대조하고 Decision Log를 갱신한다.
**Files:**
- Modify: `docs/20260811_일본어_string_resource_반영/prd.md`
- Modify: `docs/20260811_일본어_string_resource_반영/plan-task.md`
**Interfaces:**
- Consumes: `OQ-001`~`OQ-005`.
- Produces: Phase 2에서 구현 가능한 기존 키 갱신 범위와 제외 목록.
- [x] `OQ-001`: `しいシリーズ``新しいシリーズ`로 보정 반영한다.
- [x] `OQ-002`: placeholder는 기존 한국어 리소스가 있는 항목만 Swift 함수 인자로 변환한다.
- [x] `OQ-006`: `{{...}}`, `{...}`, `n%`, `n위`, `0:00` placeholder는 Swift interpolation과 정규화 매칭한다.
- [x] `OQ-007`: 중복 KR 또는 중복 정규화 KR의 기존 JP가 서로 다르면 CSV JP를 우선한다.
- [x] `OQ-008`: HTML br 표기는 Swift 문자열 줄바꿈 `\n`으로 변환한다.
- [x] `OQ-009`: CSV 셀 안의 실제 줄바꿈은 Swift 문자열 줄바꿈 escape `\n`으로 변환한다.
- [x] `OQ-003`: KR 오탈자 후보는 보정하지 않고 JP만 반영한다.
- [x] `OQ-004`: 기존 `I18n.swift`에 없는 139개 항목은 신규 키로 추가하지 않는다.
- [x] `OQ-005`: 없는 리소스는 추가하지 않으므로 신규 `en`도 작성하지 않는다.
### 완료 조건
- [x] `P1-T1`, `P1-T2`, `P1-T3`의 체크박스와 완료 증거가 모두 충족됐다.
- [x] Phase 2 구현 범위가 exact 또는 placeholder 정규화 기준으로 기존 한국어 리소스가 있는 항목으로만 구성됐다.
- [x] CSV 실제 줄바꿈이 있는 항목은 Swift 문자열 `\n` 변환 대상으로 분류됐다.
- [x] HTML br 표기가 있는 항목은 `\n` 변환 대상으로 분류됐다.
- [x] 제외 항목은 추정 구현 없이 PRD Open Questions와 Decision Log에 남았다.
### 검증 방법
#### Phase 1 Gate
**Goal 실행 `P1-GATE`:** CSV 입력, 기존 키 매칭, 질문 결정 처리 상태를 최종 판정한다.
- **시작 조건:** Phase 1의 모든 활성 Task goal 완료.
- **완료 증거:** 아래 명령 결과와 PRD Decision Log 갱신.
- **범위 밖:** 앱 코드 수정.
```bash
python3 - <<'PY'
import csv
from pathlib import Path
p = Path('docs/20260811_일본어_string_resource_반영/kr_jp_string_resource.csv')
with p.open(newline='', encoding='utf-8') as f:
reader = csv.reader(f)
header = next(reader)
rows = list(reader)
assert header[1:3] == ['KR', 'JP']
assert len(rows) == 242
assert all(len(row) >= 3 and row[1].strip() and row[2].strip() for row in rows)
print('CSV gate passed')
PY
```
**Expected:** `CSV gate passed`.
수동 검증:
- [x] PRD `OQ-001`~`OQ-009`의 상태가 모두 확정이고 Decision Log가 최신 회신을 반영한다.
- [x] Phase 2 구현 대상에 기존 한국어 리소스가 없는 항목이 포함되지 않았다.
## Phase 2 일본어 리소스 반영
**Phase 결과:** exact 또는 placeholder 정규화 기준으로 기존 한국어 리소스가 있는 확정 CSV JP 문구가 `I18n.swift`에 반영되고, 일본어 환경 대표 화면에서 문구가 확인된다.
**선행조건:** `P1-GATE` 완료.
**Phase 완료 조건:** `P2-T1`~`P2-T3``P2-GATE` 완료, Progress 기록 누적.
### 구현 항목
#### Task 2.1 기존 키 `ja` 값 갱신
**Goal 실행 `P2-T1`:** CSV KR과 기존 `I18n.swift` `ko:`가 exact 또는 placeholder 정규화 기준으로 일치하는 확정 항목의 `ja` 값을 CSV JP로 갱신한다.
- **시작 조건:** `P1-GATE` 완료, 기존 리소스 없음 제외 목록 확정.
- **완료 증거:** 기존 `en` 값이 유지되고, 갱신 대상 `ja` 값이 CSV와 일치한다.
- **범위 밖:** 신규 키 추가, 호출부 변경, 영어 문구 변경.
- **TDD 예외 사유:** 기존 string map 값 갱신이며 테스트 타깃이 확인되지 않는다.
- **대체 검증 방법:** 갱신 전후 `ko/en/ja` tuple을 스크립트로 대조하고 `xcodebuild`로 컴파일을 확인한다.
**Files:**
- Modify: `SodaLive/Sources/I18n/I18n.swift`
- Modify: `docs/20260811_일본어_string_resource_반영/plan-task.md`
**Interfaces:**
- Consumes: Phase 1의 기존 키 갱신 대상 목록.
- Produces: CSV JP가 반영된 `I18n.swift`.
- [x] 갱신 대상만 수정하고 `en:` 값을 변경하지 않는다.
- [x] `OQ-001``しいシリーズ``新しいシリーズ`로 보정한 JP를 사용한다. 기존 리소스 미매칭 항목이므로 신규 키는 추가하지 않았다.
- [x] CSV 셀 안의 실제 줄바꿈은 Swift 문자열에 실제 개행으로 붙여넣지 않고 `\n` escape로 작성한다.
- [x] HTML br 표기는 앱 문자열에 그대로 두지 않고 `\n`으로 변환한다.
- [x] placeholder 정규화로 매칭된 항목은 Swift 함수 인자 순서를 유지하고 `ja` 문장 내 인자 위치만 CSV JP 기준으로 반영한다.
- [x] 기존 한국어 리소스가 exact 또는 placeholder 정규화 기준으로 없는 항목은 수정 대상에서 제외한다.
- [x] 동일 KR 또는 동일 정규화 KR이 여러 키에 존재하고 기존 JP가 서로 다르면 CSV JP를 우선 반영한다.
#### Task 2.2 기존 리소스 없음 항목 제외 처리
**Goal 실행 `P2-T2`:** 기존 `I18n.swift`에 exact 또는 placeholder 정규화 기준으로 없는 CSV 항목을 신규 키로 추가하지 않고 제외 목록으로 문서화한다.
- **시작 조건:** `P2-T1` 완료, `OQ-004`, `OQ-005` 확정.
- **완료 증거:** 제외 대상 수와 제외 사유가 Progress에 기록되고, 신규 `I18n` 키가 추가되지 않는다.
- **범위 밖:** 영어 문구 추정, 호출부 없는 키 추가, 공통 abstraction 확장.
- **TDD 예외 사유:** 문서화와 범위 제외 Task다.
- **대체 검증 방법:** `git diff`와 정적 검색으로 `I18n.swift` 신규 키 추가가 없고 기존 키 `ja` 값만 변경됐는지 확인한다.
**Files:**
- Read: `SodaLive/Sources/I18n/I18n.swift`
- Modify: `docs/20260811_일본어_string_resource_반영/plan-task.md`
**Interfaces:**
- Consumes: Phase 1 기존 리소스 없음 제외 목록.
- Produces: 제외 대상과 제외 사유 기록.
- [x] direct exact 미매칭 139개 중 분할 리소스 매핑 2개를 제외한 137개 항목은 신규 키로 추가하지 않는다.
- [x] CSV에만 있는 placeholder 문구도 정규화 후 기존 한국어 리소스가 없으면 제외한다.
- [x] 제외 대상은 Progress에 `기존 한국어 리소스 없음` 사유로 기록한다.
- [x] `SodaLive/Sources/**` 호출부를 신규 `I18n` 키로 바꾸지 않는다.
#### Task 2.3 정적 점검과 문서 동기화
**Goal 실행 `P2-T3`:** 반영 결과와 문서를 동기화하고 누락·오반영 후보를 제거한다.
- **시작 조건:** `P2-T1`, `P2-T2` 완료.
- **완료 증거:** 정적 검색, 문서 Progress, Decision Log가 최신 상태다.
- **범위 밖:** Gate 실패와 무관한 추가 번역.
- **TDD 예외 사유:** 정적 검증과 문서화 Task다.
- **대체 검증 방법:** `rg`와 Python 대조 스크립트로 CSV 반영 상태를 확인한다.
**Files:**
- Read: `SodaLive/Sources/I18n/I18n.swift`
- Modify: `docs/20260811_일본어_string_resource_반영/prd.md`
- Modify: `docs/20260811_일본어_string_resource_반영/plan-task.md`
**Interfaces:**
- Consumes: Phase 2 변경 diff.
- Produces: 최신 Progress, Decision Log, 발견된 문제 목록.
- [x] `rg -n 'pick\(ko:.*ja:' SodaLive/Sources/I18n/I18n.swift`와 diff로 변경 구간을 점검한다.
- [x] CSV 확정 항목과 `I18n.swift` `ja` 값을 exact/placeholder 정규화 기준으로 대조한다.
- [x] CSV 실제 줄바꿈 대상이 `I18n.swift`에서 Swift 문자열 `\n`으로 작성됐는지 대조한다.
- [x] HTML br 표기가 `I18n.swift`에 literal로 남지 않았는지 대조한다.
- [x] 중복 KR 또는 중복 정규화 KR의 `ja` 값이 CSV JP로 통일됐는지 대조한다.
- [x] 제외된 항목은 `발견된 문제` 또는 PRD Open Questions에 연결한다.
### 완료 조건
- [x] `P2-T1`, `P2-T2`, `P2-T3`의 체크박스와 완료 증거가 모두 충족됐다.
- [x] 확정 항목은 기존 키 갱신 또는 명시적 제외로 추적된다.
- [x] 기존 영어 문구와 기능 동작이 바뀌지 않았다.
### 검증 방법
#### Phase 2 Gate
**Goal 실행 `P2-GATE`:** 일본어 문자열 반영, 빌드, 대표 화면 수동 QA를 최종 판정한다.
- **시작 조건:** Phase 2의 모든 활성 Task goal 완료.
- **완료 증거:** 아래 명령과 수동 검증 결과를 Progress에 기록.
- **범위 밖:** Gate 통과를 위한 test 삭제·완화, 관련 없는 리팩터링.
```bash
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" test
xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" test
```
**Expected:** 두 Debug 빌드는 `** BUILD SUCCEEDED **`. 테스트 액션이 미구성되어 실패하면 `Scheme ... is not currently configured for the test action.`을 스킴 제약으로 기록한다.
수동 검증:
- [x] 앱 언어 `ja`에서 홈 탭 `ホーム`, `コンテンツ`, `トーク`, `マイページ` 표시를 확인한다.
- [x] 변경된 개행 문구는 실제 `I18n.swift` 런타임 드라이버에서 CSV 기준 줄바꿈으로 확인한다.
- [x] CSV 셀 안의 실제 줄바꿈이 런타임 문자열에서 줄바꿈으로 확인된다.
- [x] HTML br 표기 원문이 소스와 런타임 문자열에 남지 않았다.
- [x] 크리에이터명·랭킹·퍼센트 placeholder 문구가 실제 값과 함께 깨지지 않는다.
- [x] 구매/대여 완료 문자열이 일본어 런타임 값으로 확인된다. 기존 리소스가 없는 실패 문구는 제외 정책을 따른다.
- [x] 기존 리소스 없음으로 제외한 항목이 신규 키로 추가되지 않았다.
## 실행 순서와 의존성
| 순서 | Goal | 선행조건 | 병행 가능 | 차단 시 다음 행동 |
|---:|---|---|---|---|
| 1 | `P1-T1` | 없음 | 아니요 | CSV 형식 문제를 PRD에 기록 |
| 2 | `P1-T2` | `P1-T1` | 아니요 | 매칭 방식 보정 후 재실행 |
| 3 | `P1-T3` | `P1-T2` | 아니요 | 제외 항목을 Phase 2 범위에서 제거 |
| 4 | `P1-GATE` | Phase 1 Task 전체 | 아니요 | 실패 소유 Task 재실행 |
| 5 | `P2-T1` | `P1-GATE` | 아니요 | 기존 키 갱신 대상만 축소 |
| 6 | `P2-T2` | `P2-T1` | 아니요 | 제외 목록을 보정하고 신규 키 추가 여부를 재검증 |
| 7 | `P2-T3` | `P2-T1`, `P2-T2` | 아니요 | 누락 소유 Task로 되돌림 |
| 8 | `P2-GATE` | Phase 2 Task 전체 | 아니요 | 실패 소유 Task의 회귀 수정 goal 생성 |
```text
P1-T1 → P1-T2 → P1-T3 → P1-GATE → P2-T1 → P2-T2 → P2-T3 → P2-GATE
```
## 변경 금지 항목
- CSV에 없는 영어 문구를 임의 작성하지 않는다.
- 기존 한국어 리소스가 없는 CSV 항목을 신규 리소스로 추가하지 않는다.
- `I18n.pick` 구조를 개편하지 않는다.
- `Pods/**`, `generated/**`, `build/**`를 수정하지 않는다.
- 요청 범위 밖 UI 레이아웃, 폰트, API, 결제 SDK 입력값을 변경하지 않는다.
- test를 삭제·skip·완화하거나 타입 오류를 우회해 Gate를 통과시키지 않는다.
- 토큰, 이메일 실제값, signed URL 같은 민감정보를 log·fixture·문서에 기록하지 않는다.
## 의사결정 및 중단 규칙
- PRD와 CSV가 충돌하면 PRD Decision Log에 근거를 남긴 뒤 계획을 갱신한다.
- 기존 한국어 리소스가 없는 항목은 구현 대상에서 제외한다.
- 구현 범위가 바뀌면 PRD를 먼저 보강하고 이 문서 체크리스트를 갱신한 뒤 코드를 수정한다.
- 같은 차단 사유가 3회 연속 반복되고 독립 작업도 불가능할 때만 goal을 `blocked`로 갱신한다.
- 완료 증거와 Progress 기록까지 충족한 뒤에만 goal을 `complete`로 갱신한다.
## Progress
기존 기록을 삭제하거나 덮어쓰지 않고 실제 실행 결과를 차수별로 누적한다.
### P1-T1~P1-GATE 실행 — 2026-08-11
- 상태: 완료
- 무엇을: CSV 구조, 실제 줄바꿈, placeholder, exact/정규화 매핑, 중복 JP와 제외 대상을 확정했다.
- 왜: literal 매칭만으로는 런타임 값과 분할 문자열을 놓칠 수 있어 구현 전에 확정 분류가 필요했다.
- 어떻게:
- CSV Gate — 데이터 242행, 누락 0건, 실제 줄바꿈 33건, placeholder 12건, CSV KR 중복 0건.
- 매핑 스캔 — exact 103행, placeholder 정규화 추가 0행, 기존 리소스 없음 139행.
- 분할 리소스 확인 — 랭킹 문구와 전체 오디오 소장률 문구를 기존 함수/접두·접미 리소스 후보로 추가 확인.
- 중복 리소스 확인 — 같은 KR의 기존 JP 상이 항목 12건을 CSV JP 우선 대상으로 확정.
- RED `mapping-validator` — 현재 JP 불일치 64건을 검출하고 exit code 1 확인.
- 남은 항목: P2 일본어 JP 값 갱신과 GREEN 검증.
- 다음 행동: `P2-T1`에서 기존 `en`과 호출부를 유지하고 `ja`만 CSV 우선값으로 갱신한다.
### P2-T1~P2-GATE 실행 — 2026-08-11
- 상태: 완료
- 무엇을: 기존 `I18n.swift``ja` literal 64건을 CSV JP 우선값으로 갱신하고 정적·런타임·빌드·시뮬레이터 검증을 완료했다.
- 왜: exact 매핑, 중복 KR, 분할 placeholder 리소스에 CSV 승인 일본어를 일관되게 적용하기 위해서다.
- 어떻게:
- RED `mapping-validator` — 변경 전 JP 불일치 64건, exit code 1.
- GREEN `mapping-validator` — 변경 후 불일치 0건, `ko`/`en` literal 동일, `pick` literal 수 `1343 → 1343`.
- 변경 범위 — `I18n.swift` 64 insertions/64 deletions, 모두 기존 `ja` literal 교체. 신규 키·호출부 변경 0건.
- 분류 — exact CSV 103행, 분할 리소스 2행, 기존 리소스 없음 제외 137행.
- 줄바꿈 — 매핑된 multiline occurrence 4건 모두 Swift `\n` escape, HTML br literal 0건.
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive" -configuration Debug build` — 성공, `** BUILD SUCCEEDED **`.
- `xcodebuild -workspace "SodaLive.xcworkspace" -scheme "SodaLive-dev" -configuration Debug build` — 성공, `** BUILD SUCCEEDED **`.
- 두 스킴 `test``Scheme ... is not currently configured for the test action.` 확인. 테스트 액션 미구성 제약이며 빌드 실패가 아니다.
- 실제 `I18n.swift` Swift 런타임 드라이버 — 일본어 탭, 랭킹 interpolation, 소장률 interpolation, CSV `\n`, 구매/대여 완료 문자열 PASS.
- iPhone 15 Pro Simulator, 앱 설정 `ja` — 스플래시와 홈 화면 렌더링 성공. `ホーム`, `コンテンツ`, `トーク`, `マイページ`, `新着クリエイター` 표시 확인.
- 시각 QA Oracle 2건 — 기능/디자인 PASS, CJK 정밀도 PASS, blocking 0건.
- compiled app artifact — `SodaLive`, `SodaLive-dev` 바이너리에서 대표 일본어 문자열 포함 확인.
- 증거:
- `/var/folders/yh/8xsbvpsj5wg2qnxzxdp11_gm0000gn/T/opencode/sodalive-ja-evidence/launch-ja.png`
- `/var/folders/yh/8xsbvpsj5wg2qnxzxdp11_gm0000gn/T/opencode/sodalive-ja-evidence/launch-ja-settled.png`
- 남은 항목: 없음.
- 다음 행동: 최종 reviewer gate와 문서 체크박스 정합성을 확인한다.
### Phase 2 최종 리뷰 — 2026-08-11
- 상태: 판정 완료
- 무엇을: 구현 diff, CSV 매핑, PRD·계획 문서의 완료 근거를 독립 reviewer가 재검증했다.
- 왜: Phase 2 완료 판정 전에 요구사항 누락과 문서·코드 불일치를 차단하기 위해서다.
- 어떻게:
- Oracle 최종 판정 — `APPROVE`, blocker 0건, confidence High.
- 독립 확인 — `ja` literal 64건만 변경, exact 103행·분할 2행·제외 137행, 매핑 불일치 0건.
- 리뷰 보고서 — `reviews/phase2-japanese-string-resource.md`.
- 남은 항목: 없음.
- 다음 행동: 최종 diff와 working tree 상태를 확인하고 종료한다.
### 문서 생성 — 2026-08-11
- 상태: 완료
- 무엇을: CSV 기반 일본어 string_resource 반영 PRD와 Goal 실행형 계획 문서를 생성했다.
- 왜: 사용자 요청이 구현 전 PRD와 계획문서 생성으로 한정되어 있으며, 모호한 항목을 구현 전에 질문/보류해야 하기 때문이다.
- 어떻게:
- `docs/sample/sample-prd.md` 확인 — PRD 구조 기준 확인.
- `docs/sample/sample-plan-task.md` 확인 — Phase/Task/Goal/검증 기록 구조 확인.
- `docs/agent-guides/documentation-policy.md` 확인 — PRD와 계획문서 위치·작성 규칙 확인.
- `rg --files | rg 'I18n|String|strings|xcstrings|lproj|Localizable|resource'` — 문자열 리소스 관련 파일 위치 확인.
- `codegraph_node(file="SodaLive/Sources/I18n/I18n.swift")` — 현재 `I18n.swift` 구조 확인.
- `python3` CSV 파싱 — 데이터 242행, KR 누락 0건, JP 누락 0건, 개행 33행, placeholder 유사 12행 확인.
- `python3` KR literal 매칭 — 기존 `I18n.swift` 매칭 103건, 미매칭 139건 확인.
- 남은 항목: 사용자 결정 반영 전 기록이며, 최신 결정은 아래 `Open Questions 결정 반영` 기록을 따른다.
- 다음 행동: Phase 1의 `P1-T1`부터 실행하되, 기존 한국어 리소스가 없는 항목은 구현 범위에서 제외한다.
### Open Questions 결정 반영 — 2026-08-11
- 상태: 완료
- 무엇을: 사용자 회신에 따라 `OQ-001`~`OQ-005`를 모두 확정 상태로 갱신하고, 신규 리소스 추가 계획을 제외 처리로 바꿨다.
- 왜: 기존 한국어 리소스가 없는 항목은 반영하지 않는다는 결정이 내려졌으므로 신규 키 후보 처리와 신규 `en` 작성 계획을 제거해야 하기 때문이다.
- 어떻게:
- `OQ-001``しいシリーズ`는 오타로 확정하고 `新しいシリーズ`로 보정 반영하도록 기록.
- `OQ-002` — placeholder는 기존 한국어 리소스가 있는 항목만 Swift 함수 인자로 변환하도록 기록.
- `OQ-003` — 한국어 리소스는 보정하지 않고 JP만 반영하도록 기록.
- `OQ-004`, `OQ-005` — 기존 한국어 리소스가 없는 항목과 없는 리소스는 추가하지 않도록 기록.
- 남은 항목: 코드 반영은 아직 수행하지 않음.
- 다음 행동: 구현 요청이 들어오면 `P1-T1`부터 실행하고, `P2-T2`에서는 신규 키 추가가 없음을 검증한다.
## Decision Log
| 날짜 | ID | 상태 | 결정 | 근거 | 영향 Goal/문서 |
|---|---|---|---|---|---|
| `2026-08-11` | `DEC-001` | 확정 | 문서는 CSV가 있는 폴더에 `prd.md`, `plan-task.md`로 생성한다. | 사용자 직접 지시 | 전체 |
| `2026-08-11` | `DEC-002` | 확정 | 이번 턴에서는 코드 구현을 하지 않는다. | 사용자 직접 지시 | 전체 |
| `2026-08-11` | `DEC-003` | 폐기 | 기존 `I18n.swift` 매칭 항목은 `ja`만 갱신하고 신규 키는 호출부와 영어 기준이 있는 경우로 제한한다. | 사용자 결정으로 기존 한국어 리소스가 없는 항목은 추가하지 않기로 변경 | `P2-T1`, `P2-T2` |
| `2026-08-11` | `DEC-004` | 확정 | `しいシリーズ``新しいシリーズ`로 보정한다. | 사용자 확인 | `P2-T1` |
| `2026-08-11` | `DEC-005` | 확정 | placeholder 문구는 기존 한국어 리소스가 있는 항목만 Swift 함수 인자로 변환한다. | 사용자 결정 | `P2-T1` |
| `2026-08-11` | `DEC-006` | 확정 | 한국어 리소스 원문은 보정하지 않고 JP만 반영한다. | 사용자 결정 | `P2-T1` |
| `2026-08-11` | `DEC-007` | 확정 | 기존 한국어 리소스가 없는 CSV 항목은 신규 리소스로 추가하지 않는다. | 사용자 결정 | `P2-T2` |
| `2026-08-11` | `DEC-008` | 확정 | `{{...}}`, `{...}`, `n%`, `n위`, `0:00` placeholder는 Swift interpolation과 정규화해 매핑 후보를 판정한다. | 사용자 결정과 재스캔 결과 | `P1-T2`, `P2-T1` |
| `2026-08-11` | `DEC-009` | 확정 | 같은 KR 또는 같은 정규화 KR의 기존 JP가 여러 값이면 CSV JP를 우선 반영한다. | 사용자 결정과 중복 JP 재스캔 결과 | `P1-T2`, `P2-T1` |
| `2026-08-11` | `DEC-010` | 확정 | HTML br 표기는 앱 문자열에 그대로 반영하지 않고 줄바꿈 `\n`으로 변환한다. | 사용자 결정과 CSV 검색 결과 현재 0건 | `P1-T1`, `P2-T1` |
| `2026-08-11` | `DEC-011` | 확정 | CSV 셀 안의 실제 줄바꿈은 Swift 문자열 줄바꿈 escape `\n`으로 변환한다. | 사용자 결정과 CSV 파싱 결과 개행 33행 | `P1-T1`, `P2-T1` |
## 발견된 문제
| ID | 심각도 | 상태 | 발견 내용 | 영향 Goal | 처리 계획 |
|---|---|---|---|---|---|
| `ISSUE-001` | Medium | 해결 | CSV 물리 line 281~283의 JP가 `しいシリーズ`로 시작해 `新しいシリーズ` 오탈자 가능성이 있다. | `P1-T3`, `P2-T1` | 사용자 확인으로 `新しいシリーズ` 보정 반영 확정 |
| `ISSUE-002` | Medium | 해결 | placeholder 유사 문구 12건이 `{{...}}`, `{...}`, `n`, `0:00` 형식으로 섞여 있다. | `P1-T2`, `P2-T1` | Swift interpolation과 정규화 매칭하고, 현재 재스캔 기준 추가 매칭은 0건으로 기록 |
| `ISSUE-003` | Medium | 해결 | CSV KR 242행 중 현재 `I18n.swift` `ko:` literal과 직접 매칭되지 않는 항목이 139건이다. | `P1-T2`, `P2-T2` | 기존 한국어 리소스가 없는 항목은 신규 키로 추가하지 않음 |
| `ISSUE-004` | Medium | 해결 | CSV 매칭 KR 중 기존 `I18n.swift` JP가 중복 항목끼리 서로 다른 경우가 12건이다. | `P1-T2`, `P2-T1` | CSV JP 우선 반영 규칙 확정 |
| `ISSUE-005` | Low | 해결 | CSV와 기존 문서에서 HTML br 표기 검색 결과 현재 0건이다. | `P1-T1`, `P2-T1` | 향후 발견 시 literal 대신 `\n` 변환 반영 규칙 확정 |
| `ISSUE-006` | Medium | 해결 | CSV 셀 안의 실제 줄바꿈 포함 항목이 33건이다. | `P1-T1`, `P2-T1` | Swift 문자열에는 실제 개행 붙여넣기가 아니라 `\n` escape로 반영 |
## 최종 보고 형식
최종 보고에는 다음 항목을 실제 실행 결과로 채운다.
- 구현 결과: 완료한 Phase와 사용자가 확인할 수 있는 흐름.
- 변경: 주요 파일과 동작.
- 결정: 중요한 Decision Log ID와 내용.
- 검증: 실행 명령별 성공/실패, exit code, 핵심 수치, 수동 검증 결과.
- 남은 항목: 외부 의존, 후속 범위, 제외 항목 또는 후속 질문.
- 문서: 갱신한 PRD, plan, review 경로.
최종 보고는 성공을 추정하지 않는다. 실제 실행한 최신 검증 결과와 완료되지 않은 범위를 함께 전달한다.

View File

@@ -0,0 +1,218 @@
# 일본어 string_resource 반영 PRD
## 문서 정보
| 항목 | 내용 |
|---|---|
| 문서 상태 | 구현 기준 확정 |
| 작성일 | `2026-08-11` |
| 최종 수정일 | `2026-08-11` |
| 대상 제품 | SodaLive iOS 일본어 문자열 리소스 |
| 작성자·결정권자 | 작성자: Sisyphus / 결정권자: 제품·iOS 담당자 |
| 관련 API Contract | 해당 없음 |
| 관련 구현 계획 | `docs/20260811_일본어_string_resource_반영/plan-task.md` |
| 관련 원본 | `docs/20260811_일본어_string_resource_반영/kr_jp_string_resource.csv` |
| 관련 review | 없음 |
### 요구사항 상태
| 상태 | 의미 | 구현 처리 |
|---|---|---|
| 확정 | CSV와 현재 iOS 문자열 구조만으로 구현 기준을 정할 수 있음 | `plan-task.md`의 Task와 완료 증거로 추적 |
| 미결 | 제품·번역·키 매핑 결정이 더 필요함 | Open Questions에 기록하고 임의 구현 금지 |
| 제외 | 이번 작업에서 구현하지 않음 | Non-Goals와 Decision Log에 기록 |
### 문서 우선순위와 갱신 순서
1. CSV의 KR/JP 원문은 이 PRD의 입력 기준으로 사용한다.
2. `SodaLive/Sources/I18n/I18n.swift`의 기존 `pick(ko:en:ja:)` 구조를 우선 유지한다.
3. `{{키워드}}의 오디오`처럼 `{{...}}`, `{...}`, `n%`, `n위`, `0:00` 형태로 런타임 값이 들어가는 CSV 문구는 Swift interpolation 문구와 정규화 매칭한다.
4. CSV 셀 안의 실제 줄바꿈과 HTML br 표기는 문자열 그대로 반영하지 않고 Swift 문자열 줄바꿈 escape `\n`으로 변환한다.
5. CSV와 구현 구조가 충돌하면 Decision Log → 요구사항 → `plan-task.md` 순서로 갱신한다.
6. 확정된 결정 밖의 추정 번역, 추정 영어 문구, 추정 키는 구현하지 않는다.
## 1. Overview
`kr_jp_string_resource.csv`에 정리된 한국어-일본어 문구를 SodaLive iOS 앱의 문자열 리소스에 반영해 일본어 환경에서 사용자 노출 문구를 최신 번역으로 표시한다. 현재 앱은 `SodaLive/Sources/I18n/I18n.swift`의 하드코딩 맵과 `pick(ko:en:ja:)` 헬퍼를 통해 언어별 문자열을 선택한다. 이 작업은 코드 구현 전 PRD와 실행 계획만 작성하며, 실제 `I18n.swift` 수정은 후속 승인 후 진행한다.
## 2. Problem Statement
현재 사용자는 다음 문제를 겪는다.
- 일본어 번역 CSV가 앱 문자열 리소스에 아직 반영되지 않아 일본어 UI 문구가 최신 번역 기준과 다를 수 있다.
- CSV에는 개행 문구, placeholder 문구, 오탈자 후보가 섞여 있어 임의 치환 시 포맷 깨짐이나 잘못된 일본어 노출 위험이 있다.
- `I18n.swift``ko`, `en`, `ja`를 함께 요구하므로 CSV에 없는 영어 문구를 임의 생성하면 기존 영어 UX가 변할 수 있다.
문제를 해결했다는 판단은 CSV의 확정 가능한 JP 값이 `I18n.swift`에 반영되고, 일본어 선택 시 해당 문구가 표시되며, 빌드가 성공하는 것으로 한다.
## 3. Goals
### 3.1 제품 목표
- CSV 데이터 242행 중 기존 한국어 리소스가 확인된 KR/JP 문구만 iOS 일본어 문자열에 반영한다.
- 기존 `I18n.swift`에 동일 KR 문구가 있거나 placeholder 정규화 후 같은 문구로 판정되는 항목은 기존 `en` 값을 유지하고 `ja` 값만 CSV 기준으로 갱신한다.
- 동일 KR 문구가 없는 CSV 항목은 신규 리소스로 추가하지 않는다.
- 개행 33행과 placeholder 유사 12행은 기존 한국어 리소스가 있는 경우에만 CSV 셀 안의 실제 줄바꿈을 Swift 문자열 `\n`으로 변환하고 함수 인자 순서를 보존해 반영한다.
- CSV에 HTML br 표기가 있으면 literal이 아니라 Swift 문자열 `\n`으로 변환해 반영한다.
- 같은 KR 또는 같은 정규화 KR이 여러 `I18n` 항목에 중복되어 있고 기존 JP가 서로 다르면 CSV JP를 우선해 같은 값으로 반영한다.
### 3.2 UX 목표
- 일본어 환경에서 홈, 콘텐츠, 대화, 마이페이지, 인증, 구매, 보관함 등 CSV가 포함한 주요 화면 문구가 자연스럽게 표시된다.
- placeholder가 포함된 문구는 실제 값 삽입 후 일본어 문장 순서가 깨지지 않는다.
- CSV의 `しいシリーズ` 오탈자 후보는 `新しいシリーズ`로 보정해 반영한다.
## 4. Non-Goals
- 이번 요청에서는 코드, 리소스, Xcode 프로젝트 설정을 수정하지 않는다.
- String Catalog(`.xcstrings`) 도입이나 `I18n.swift` 구조 개편은 하지 않는다.
- CSV에 없는 영어 번역을 새로 작성하지 않는다.
- 기존 한국어 리소스가 없는 CSV 항목을 신규 리소스로 추가하지 않는다.
- 서버 API, CMS, 백엔드 번역 리소스는 변경하지 않는다.
- 일본어 폰트, 레이아웃, 줄바꿈 UI 디자인 조정은 이 작업의 범위가 아니다.
## 5. Target Users and Permissions
| 사용자 | 목표 | 주요 작업 | 사용 환경 |
|---|---|---|---|
| 일본어 앱 사용자 | 일본어 UI 문구를 최신 번역으로 확인 | 앱 탐색, 콘텐츠 소비, 대화, 구매, 인증 | iOS 앱, 언어 설정 `ja` 또는 시스템 일본어 |
| iOS 개발자 | CSV 기준으로 안전하게 문자열 반영 | 문자열 매핑, 빌드 검증, 수동 QA | Xcode, `SodaLive.xcworkspace` |
| 제품·번역 담당자 | 확정된 일본어 반영 범위 확인 | 오탈자 보정과 제외 기준 승인 | PRD/계획문서 리뷰 |
권한 요구사항은 해당 없음이다. 단, 인증/구매/성인 관련 문구는 실제 기능 동작을 바꾸지 않고 표시 문자열만 바꾼다.
## 6. 핵심 사용자 흐름
1. 사용자가 앱 언어를 일본어로 설정하거나 시스템 언어가 일본어인 상태에서 앱을 실행한다.
2. 앱은 `LanguageHeaderProvider.current` 결과가 `ja`일 때 `I18n.pick`의 일본어 문자열을 선택한다.
3. 사용자는 홈, 콘텐츠, 대화, 마이페이지, 인증/구매 화면에서 CSV 기준 일본어 문구를 본다.
4. placeholder 문구는 실제 크리에이터명, 이메일, 요일, 퍼센트 등 런타임 값과 함께 자연스럽게 표시된다.
## 7. 정보 구조와 라우팅
별도 route 변경은 없다. 문자열 반영 대상은 기존 화면과 모듈에 종속된다.
```text
SodaLive/Sources/I18n/I18n.swift
I18n.Module.ScreenOrDomain.Role
```
역할 중심 키 이름을 유지한다. 이번 작업에서는 기존 한국어 리소스가 없는 CSV 항목의 신규 키를 추가하지 않으며, 공통 네임스페이스 승격도 하지 않는다.
## 8. 기능 요구사항
### 8.1 CSV 입력과 매핑
| ID | 상태 | 요구사항 | 수용 기준 | 계약/Goal 연결 |
|---|---|---|---|---|
| `JSR-001` | 확정 | `kr_jp_string_resource.csv``KR`, `JP` 컬럼을 입력 기준으로 사용한다. | CSV가 242개 데이터 행, KR 누락 0건, JP 누락 0건으로 파싱된다. | `P1-T1` |
| `JSR-002` | 확정 | 기존 `I18n.swift`에 동일 KR literal이 있거나 placeholder 정규화 후 매칭되는 항목은 `ja` 값만 CSV 기준으로 갱신한다. | 기존 `en` 값과 호출부는 변경되지 않는다. 현재 스캔 기준 exact 103행, placeholder 정규화 추가 0행으로 총 103행이 매핑 후보다. | `P1-T2`, `P2-T1` |
| `JSR-003` | 제외 | 동일 KR literal 또는 placeholder 정규화 매칭이 없는 139개 CSV 항목은 신규 키로 추가하지 않는다. | 기존 한국어 리소스가 없는 항목은 `I18n.swift`와 호출부를 변경하지 않는다. | `P1-T3`, `P2-T2` |
| `JSR-004` | 확정 | CSV 셀 안의 실제 줄바꿈과 HTML br 표기는 Swift 문자열 줄바꿈 escape `\n`으로 변환한다. | 일본어 `\n` 위치가 CSV와 동일하거나 제품 승인된 위치로 반영되며, HTML br 표기가 앱 문자열에 그대로 남지 않는다. | `P2-T1` |
| `JSR-005` | 확정 | placeholder 유사 12개 문구는 앱 내에서 변경 가능한 리소스 후보로 보고 Swift interpolation과 정규화 매칭한다. | 정규화 매칭되는 기존 리소스는 Swift 함수 인자 순서를 보존해 반영하고, 정규화 후에도 기존 리소스가 없으면 신규 키를 추가하지 않고 제외한다. | `P1-T3`, `P2-T1` |
| `JSR-006` | 확정 | CSV의 `しいシリーズ` JP 오탈자는 `新しいシリーズ`로 보정한다. | 해당 KR이 기존 한국어 리소스와 매칭될 때만 보정 JP를 반영한다. | `P1-T3`, `P2-T1` |
| `JSR-007` | 확정 | 같은 KR 또는 같은 정규화 KR이 여러 `I18n` 항목에 중복되어 있고 기존 JP가 다르면 CSV JP를 우선한다. | 현재 스캔 기준 중복 KR의 기존 JP 상이 항목 12건은 CSV JP로 통일한다. | `P1-T2`, `P2-T1` |
### 8.2 품질과 검증
| ID | 상태 | 요구사항 | 수용 기준 | 계약/Goal 연결 |
|---|---|---|---|---|
| `QA-001` | 확정 | 문자열 변경 후 두 앱 스킴 Debug 빌드를 실행한다. | `SodaLive`, `SodaLive-dev` Debug 빌드가 `** BUILD SUCCEEDED **`로 끝난다. | `P2-GATE` |
| `QA-002` | 확정 | 테스트 스킴 제약을 확인한다. | 테스트 액션 미구성 상태면 실패가 코드 실패가 아님을 Progress에 기록한다. | `P2-GATE` |
| `QA-003` | 확정 | 일본어 언어 선택 상태에서 대표 화면 수동 QA를 수행한다. | CSV 대표 문구, 개행, placeholder 표시를 스크린별로 확인하고 결과를 Progress에 남긴다. | `P2-GATE` |
| `QA-004` | 확정 | 민감 정보나 SDK 입력값을 번역 대상으로 오인하지 않는다. | 인증 토큰, API path, Bootpay/SDK 고정값은 변경하지 않는다. | `P2-T1` |
## 9. UI/UX Expectations
- 기존 화면 레이아웃과 컴포넌트 구조를 유지한다.
- 일본어 번역이 길어져도 이번 작업에서는 레이아웃을 임의 조정하지 않는다. 잘림이 발견되면 후속 UI 이슈로 기록한다.
- 개행이 포함된 문구는 CSV 의도를 우선하고, 화면에서 부자연스러운 경우 제품·번역 담당자 확인 후 보정한다.
## 10. API 계약
해당 없음. 이 작업은 클라이언트 로컬 문자열 리소스 반영이다.
## 11. 보안과 데이터 취급
- 인증 헤더, 토큰 저장소, `UserDefaultsKey.token` 관련 로직은 변경하지 않는다.
- 이메일 placeholder 문구는 예시 이메일을 문서나 테스트 fixture에 하드코딩하지 않는다.
- 구매/결제 SDK에 전달되는 고정 문자열은 사용자 노출 문구가 아닌 경우 번역하지 않는다.
## 12. 성능과 품질 요구사항
- 런타임 성능 요구사항은 변경하지 않는다.
- 신규 dependency를 추가하지 않는다.
- 문자열 선택 방식은 기존 `I18n.pick` 구조를 유지한다.
- 검증은 정적 매핑 점검, Xcode 빌드, 일본어 대표 화면 수동 QA로 수행한다.
## 13. 성공 기준
### 13.1 기능 수용 기준
- [x] CSV 242행의 처리 상태가 `기존 키 갱신`, `placeholder 정규화 후 기존 키 갱신`, `오탈자 보정 후 기존 키 갱신`, `기존 리소스 없음으로 제외` 중 하나로 분류된다.
- [x] 확정 항목의 일본어 문구가 `I18n.swift`에 반영된다.
- [x] placeholder와 개행 문구가 깨지지 않는다.
- [x] CSV 셀 안의 실제 줄바꿈과 HTML br 표기는 문자열 그대로가 아니라 Swift 문자열 `\n`으로 반영된다.
- [x] 중복 KR 또는 중복 정규화 KR의 JP는 CSV JP 우선으로 정리된다.
- [x] 기존 한국어 리소스가 없는 항목은 구현하지 않고 제외 사유가 문서화된다.
### 13.2 품질 수용 기준
- [x] `SodaLive` Debug 빌드가 성공한다.
- [x] `SodaLive-dev` Debug 빌드가 성공한다.
- [x] 테스트 액션 실행 가능 여부와 결과가 기록된다.
- [x] 일본어 언어 설정에서 대표 화면 수동 QA가 완료된다.
### 13.3 추적성 완료 기준
- [x] 모든 확정 요구사항이 `plan-task.md`의 Goal과 연결된다.
- [x] 모든 제외 항목에 제외 근거와 영향 Goal이 있다.
- [x] 구현 결과와 검증 기록은 `plan-task.md` Progress에 누적된다.
## 14. Open Questions
| ID | 상태 | 결정 필요 사항 | 현재 권고 | 결정 주체 | 결정 기한/시점 | 영향 Goal |
|---|---|---|---|---|---|---|
| `OQ-001` | 확정 | CSV 물리 line 281~283의 JP `最近見たシリーズはありません。\nしいシリーズを見つけましょう`에서 `しいシリーズ`가 오탈자인지 확인이 필요했다. | `新しいシリーズを見つけましょう!`로 보정한다. | 사용자 | 확정 완료 | `P1-T3`, `P2-T1` |
| `OQ-002` | 확정 | `{{장르}}`, `{{크리에이터이름}}`, `{email}`, `{요일}`, `n%`, `n위`, `0:00` 토큰을 Swift 함수 인자로 변환할지 결정이 필요했다. | 기존 한국어 리소스가 있는 항목만 함수 인자로 변환하고, 기존 한국어 리소스가 없는 항목은 반영하지 않는다. | 사용자 | 확정 완료 | `P1-T3`, `P2-T1` |
| `OQ-003` | 확정 | CSV KR 원문 중 `메세지`, `메거진` 같은 한국어 오탈자 후보를 보정할지 결정이 필요했다. | 한국어 리소스는 보정하지 않고 JP만 반영한다. | 사용자 | 확정 완료 | `P1-T3`, `P2-T1` |
| `OQ-004` | 확정 | 기존 `I18n.swift`에 동일 KR literal이 없는 139개 항목을 신규 키로 추가할지 결정이 필요했다. | 기존 한국어 리소스가 없는 항목은 추가하지 않는다. | 사용자 | 확정 완료 | `P1-T3`, `P2-T2` |
| `OQ-005` | 확정 | 신규 키 추가 시 CSV에 없는 `en` 값을 어떻게 채울지 결정이 필요했다. | 없는 리소스는 추가하지 않으므로 신규 `en` 작성도 하지 않는다. | 사용자 | 확정 완료 | `P2-T2` |
| `OQ-006` | 확정 | `{{키워드}}의 오디오`처럼 `{{...}}` 형태로 들어간 CSV 문구를 기존 앱 리소스 매핑 후보로 볼지 결정이 필요했다. | 앱 내에서 변경 가능한 리소스이므로 Swift interpolation 문구와 정규화 매칭한다. | 사용자 | 확정 완료 | `P1-T2`, `P2-T1` |
| `OQ-007` | 확정 | 중복 KR 항목의 기존 JP가 서로 다를 때 어떤 값을 우선할지 결정이 필요했다. | CSV JP를 우선 반영한다. | 사용자 | 확정 완료 | `P1-T2`, `P2-T1` |
| `OQ-008` | 확정 | CSV에 HTML br 표기가 있을 때 앱 문자열에 그대로 반영할지 결정이 필요했다. | HTML br 표기는 literal이 아니라 Swift 문자열 줄바꿈 `\n`으로 변환한다. | 사용자 | 확정 완료 | `P1-T1`, `P2-T1` |
| `OQ-009` | 확정 | CSV 셀 안의 실제 줄바꿈을 앱 문자열에 어떤 형태로 반영할지 결정이 필요했다. | CSV 실제 줄바꿈은 Swift 문자열 줄바꿈 escape `\n`으로 변환한다. | 사용자 | 확정 완료 | `P1-T1`, `P2-T1` |
## 15. 요구사항 추적표
| 요구사항 범위 | API Contract | 계획 Phase | Goal | 자동 검증 | 수동 검증 |
|---|---|---:|---|---|---|
| `JSR-001` | 해당 없음 | 1 | `P1-T1` | CSV 파싱 명령 | CSV 행 수와 누락 확인 |
| `JSR-002` | 해당 없음 | 1, 2 | `P1-T2`, `P2-T1` | KR literal 매칭 스크립트, 빌드 | 일본어 대표 화면 확인 |
| `JSR-003~007` | 해당 없음 | 1, 2 | `P1-T2`, `P1-T3`, `P2-T1`, `P2-T2` | placeholder 정규화/개행/중복 JP 점검 스크립트 | 제외 목록과 보정 JP 리뷰 |
| `QA-001~004` | 해당 없음 | 2 | `P2-GATE` | `xcodebuild` | 언어 설정 `ja` 수동 QA |
## 16. Decision Log
| 날짜 | ID | 상태 | 결정 | 근거 | 영향 요구사항·계약·Goal |
|---|---|---|---|---|---|
| `2026-08-11` | `DEC-001` | 확정 | 이번 요청에서는 PRD와 `plan-task.md`만 생성하고 앱 코드는 수정하지 않는다. | 사용자 직접 지시 | 전체 |
| `2026-08-11` | `DEC-002` | 확정 | 일본어 문자열 반영의 기본 대상은 `SodaLive/Sources/I18n/I18n.swift`로 둔다. | 현재 코드의 `I18n.pick(ko:en:ja:)` 구조 확인 | `JSR-002`, `P2-T1` |
| `2026-08-11` | `DEC-003` | 폐기 | 신규 키 추가는 영어 기준과 호출부가 확인된 항목으로 제한한다. | 사용자 결정으로 기존 한국어 리소스가 없는 항목은 추가하지 않기로 변경 | `JSR-003`, `OQ-004`, `OQ-005` |
| `2026-08-11` | `DEC-004` | 확정 | `しいシリーズ``新しいシリーズ`로 보정한다. | 사용자 확인 | `JSR-006`, `OQ-001`, `P2-T1` |
| `2026-08-11` | `DEC-005` | 확정 | placeholder 문구는 기존 한국어 리소스가 있는 항목만 Swift 함수 인자로 변환한다. | 사용자 결정 | `JSR-005`, `OQ-002`, `P2-T1` |
| `2026-08-11` | `DEC-006` | 확정 | 한국어 리소스 원문은 보정하지 않고 JP만 반영한다. | 사용자 결정 | `OQ-003`, `P2-T1` |
| `2026-08-11` | `DEC-007` | 확정 | 기존 한국어 리소스가 없는 CSV 항목은 신규 리소스로 추가하지 않는다. | 사용자 결정 | `JSR-003`, `OQ-004`, `OQ-005`, `P2-T2` |
| `2026-08-11` | `DEC-008` | 확정 | `{{...}}`, `{...}`, `n%`, `n위`, `0:00` 형태 placeholder는 Swift interpolation과 정규화해 매핑 후보를 판정한다. | 사용자 결정과 재스캔 결과 | `JSR-002`, `JSR-005`, `OQ-006`, `P1-T2` |
| `2026-08-11` | `DEC-009` | 확정 | 같은 KR 또는 같은 정규화 KR의 기존 JP가 여러 값이면 CSV JP를 우선 반영한다. | 사용자 결정과 중복 JP 재스캔 결과 | `JSR-007`, `OQ-007`, `P2-T1` |
| `2026-08-11` | `DEC-010` | 확정 | HTML br 표기는 앱 문자열에 그대로 반영하지 않고 줄바꿈 `\n`으로 변환한다. | 사용자 결정 | `JSR-004`, `OQ-008`, `P2-T1` |
| `2026-08-11` | `DEC-011` | 확정 | CSV 셀 안의 실제 줄바꿈은 Swift 문자열 줄바꿈 escape `\n`으로 변환한다. | 사용자 결정 | `JSR-004`, `OQ-009`, `P2-T1` |
## 17. 변경 관리
요구사항 변경 시 다음을 확인한다.
- [x] Decision Log에 변경 이유와 날짜를 기록했다.
- [x] 관련 요구사항 상태·본문·수용 기준을 갱신했다.
- [x] `plan-task.md`의 범위·Files·Interfaces·체크박스·완료 증거를 코드 변경 전에 갱신했다.
- [x] 기존 Progress와 검증 기록을 삭제하거나 덮어쓰지 않았다.

View File

@@ -0,0 +1,99 @@
# Phase 2 일본어 String Resource 코드 리뷰
## 1. 리뷰 정보
| 항목 | 내용 |
|---|---|
| 리뷰 대상 | Phase 2 / P2-T1~P2-GATE |
| 기준 commit 또는 working tree | `HEAD` 기준 working tree 변경 |
| 리뷰 일자 | 2026-08-11 |
| 리뷰어 | Oracle (`openai/gpt-5.6-sol`) |
| 기준 문서 | `prd.md`, `plan-task.md`, `kr_jp_string_resource.csv` |
| 리뷰 상태 | 판정 완료 |
## 2. 리뷰 목적과 범위
### 목적
- CSV JP 우선값이 기존 일본어 리소스에만 정확히 반영되었는지 확인한다.
- 완료 체크박스와 코드·빌드·런타임·수동 검증 기록이 일치하는지 확인한다.
### 포함 범위
- 코드: `SodaLive/Sources/I18n/I18n.swift`
- 문서: `docs/20260811_일본어_string_resource_반영/**`
- 검증: 정적 매핑, 두 스킴 빌드, Swift 런타임 드라이버, 일본어 Simulator 화면
### 제외 범위
- 사용자 선행 변경인 `SodaLive.xcodeproj/project.pbxproj`
- 기존 리소스가 없는 CSV 137행의 신규 키 생성
- test action이 구성되지 않은 두 스킴의 자동 테스트
## 3. 판정 기준
| 심각도 | 기준 |
|---|---|
| Blocker | 데이터 손실 위험, 핵심 흐름 불능, 완료 판정을 무효화하는 문제 |
| High | 확정 요구사항 위반 또는 주요 회귀 |
| Medium | 제한된 조건의 기능·표시 문제 |
| Low | 문서 정합성 또는 비핵심 유지보수 문제 |
## 4. 검토한 근거
### 문서와 코드
- 요구사항: `JSR-001~JSR-005`, PRD 수용 기준
- 계획: `P2-T1~P2-GATE`
- 코드: `SodaLive/Sources/I18n/I18n.swift`
- 원본: `kr_jp_string_resource.csv` 242행
### 실행 환경
```text
OS: macOS
Build: Xcode command line build
Simulator: iPhone 15 Pro, app language ja
```
### 실행한 검증
| 명령 또는 수동 검증 | 결과 | 핵심 증거 |
|---|---|---|
| RED/GREEN mapping validator | 성공 | 변경 전 불일치 64건, 변경 후 0건 |
| `SodaLive` Debug build | 성공 | `** BUILD SUCCEEDED **` |
| `SodaLive-dev` Debug build | 성공 | `** BUILD SUCCEEDED **` |
| 두 스킴 test action 확인 | 불가 | `Scheme ... is not currently configured for the test action.` |
| 실제 `I18n.swift` 런타임 드라이버 | 성공 | 탭·interpolation·줄바꿈·구매/대여 문자열 PASS |
| 일본어 Simulator 수동 QA | 성공 | 홈 탭과 `新着クリエイター` 표시 확인 |
| 독립 diff·CSV 재검증 | 성공 | `ja` literal 64건만 변경, exact 103·분할 2·제외 137 |
## 5. 발견 사항 요약
확정 발견 사항 없음.
## 6. 발견 사항 상세
해당 없음.
## 7. 확정 항목의 plan·goal 전환
전환 항목 없음.
## 8. 리뷰 종료 판정
| 판정 항목 | 결과 | 근거 |
|---|---|---|
| 리뷰 범위 전체 확인 | 충족 | 코드, CSV, PRD, 계획 문서 독립 재검증 |
| 후보 항목 판정 완료 | 충족 | 후보 및 확정 발견 사항 없음 |
| 확정 항목 plan 반영 | 해당 없음 | 확정 발견 사항 없음 |
| 보류 항목의 담당·재개 조건 기록 | 해당 없음 | 보류 항목 없음 |
| 검증 명령과 결과 기록 | 충족 | 본 문서 §4 및 `plan-task.md` Progress |
**최종 결론:** 확정 발견 사항 없음
**남은 항목:** 없음
## 9. 수정 후 검증 기록
해당 없음.