전체 재분석에서 확정한 4건 + 양식 개선 2건:
1) 목표 자동 판정 기준 시점 (핵심 수정)
기존에는 판정이 "실행되는 시점의 현재 주기" 기준이라, 종료일
며칠 뒤에 앱을 열면 목표 기간 밖의 데이터로 달성/미달성이
갈렸다. 이제 자동 판정(evaluateIfEnded)은 **종료일이 속한
논리적 하루의 마지막 순간**(judgmentReference) 기준 — 늦게
실행해도, 종료일을 과거로 고쳐도 종료일까지의 기록으로 판정.
(하루 시작 시간 설정으로 기준이 미래가 되는 경우 now로 상한)
수동 종료는 종료일 없는 목표 전용이므로 기존대로 "지금" 기준.
목표 편집 시 종료일 변경 처리: 진행 중 목표는 저장 즉시 판정,
완료된 목표의 종료일을 바꾸면 '진행 중'으로 재개 후 재판정
(미래/없음 → 진행 중 복귀, 다른 과거 날짜 → 그 시점 기준 재판정).
검증: -endGoalYesterday로 어제 종료 → 종료일 기준 '달성' 판정 확인.
2) 워치 컴플리케이션 지역화 2건
- 다짐 달성률 rectangular의 기간 라벨("하루/주간/월간")이 String
파라미터라 미추출 → en/ja에서 한국어 노출 → String(localized:)
- 빈 상태 문구("목표 없음"/"다짐 없음") 동일 문제 → 추출 + 워치
앱/워치 위젯 카탈로그에 en/ja 번역 추가 (타깃별 stringsdata로
sync — 카탈로그 오염 없음, 전 카탈로그 missing 0)
3) 배포 체크리스트: CloudKit 프로덕션 스키마 배포 항목을 CLAUDE.md
§1에 추가 (DiaryTemplate 등 새 레코드 타입은 출시 전 대시보드
Deploy Schema to Production 필수)
4) 일기 양식 렌더 개선
- 첫 렌더 비동기화: 저장된 썸네일을 플레이스홀더로 즉시 깔고
본 렌더(2×)를 백그라운드로 — 복잡한 벡터 PDF도 페이지 넘김이
걸리지 않음
- 비활성 페이지 고해상도 강등: 화면 밖 페이지는 래스터를 2×로
상한(allowsHighResolution) — TabView가 이웃 페이지를 유지해도
양식 여러 장의 메모리 사용을 절약, 활성 복귀 시 원래 배율 복원
검증: 양식 페이지 2× 프로그램 줌에서 점 노트 선명(회귀 없음),
시드 필기 페이지 획 유지 확인.
빌드: Debug·Store·워치 스킴 모두 성공. 도움말(목표 판정 문구
갱신 — 종료일 기준·재판정 규칙 안내)과 CLAUDE.md §4.3 갱신,
문구 수정 stale 1건 삭제 및 ko/en/ja 번역 완료.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
798 lines
17 KiB
Plaintext
798 lines
17 KiB
Plaintext
{
|
|
"sourceLanguage": "ko",
|
|
"strings": {
|
|
"%@": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%@"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%@"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"%@ %@": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%@ %@"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%@ %@"
|
|
}
|
|
},
|
|
"ko": {
|
|
"stringUnit": {
|
|
"state": "new",
|
|
"value": "%1$@ %2$@"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"%@ %lld%%": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%@ %lld%%"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%@ %lld%%"
|
|
}
|
|
},
|
|
"ko": {
|
|
"stringUnit": {
|
|
"state": "new",
|
|
"value": "%1$@ %2$lld%%"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"%@ +%lld": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%@ +%lld"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%@ +%lld"
|
|
}
|
|
},
|
|
"ko": {
|
|
"stringUnit": {
|
|
"state": "new",
|
|
"value": "%1$@ +%2$lld"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"%lld": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%lld"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%lld"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"%lld%%": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%lld%%"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%lld%%"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"%lld분": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%lldm"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%lld分"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"%lld시간": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%lldh"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%lld時間"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"%lld시간 %lld분": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%lldh %lldm"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%lld時間%lld分"
|
|
}
|
|
},
|
|
"ko": {
|
|
"stringUnit": {
|
|
"state": "new",
|
|
"value": "%1$lld시간 %2$lld분"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"%lld초": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%llds"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "%lld秒"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"+%lld": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "+%lld"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "+%lld"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"iPhone 앱의 설정 → 프리미엄에서 잠금 해제해 주세요": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Unlock in the iPhone app: Settings → Premium"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "iPhoneアプリの設定→プレミアムでロックを解除してください"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"iPhone과 연결 중...": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Connecting to iPhone..."
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "iPhoneに接続中..."
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"iPhone에 연결할 수 없어요. 근처에 있는지 확인해 주세요.": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Can't reach your iPhone. Make sure it's nearby."
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "iPhoneに接続できません。近くにあるか確認してください。"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"기간": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Period"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "期間"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"꼬리표 없음": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "No tag"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "タグなし"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"다짐": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Quest"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "クエスト"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"다짐 달성률": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Quest Progress"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "クエスト達成率"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"다짐 없음": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "No quest"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "クエストなし"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"목표": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Goals"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "目標"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"목표 달성률": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Goal Progress"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "目標達成率"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"목표 없음": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "No goal"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "目標なし"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"새로고침": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Refresh"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "更新"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"선택한 다짐의 달성률을 표시해요. 한도형 다짐은 상태로 표시돼요. (프리미엄)": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Shows the selected quest's progress. Limit quests show their status. (Premium)"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "選択したクエストの達成率を表示します。上限型はステータス表示になります。(プレミアム)"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"선택한 목표의 하루/주간/월간 달성률을 표시해요. (프리미엄)": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Shows the selected goal's daily/weekly/monthly progress. (Premium)"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "選択した目標の日/週/月の達成率を表示します。(プレミアム)"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"실행 중 아님": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Not running"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "実行中なし"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"앱을 열면 새로고침돼요": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Open the app to refresh"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "アプリを開くと更新されます"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"없음": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "None"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "なし"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"오늘 %@": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Today %@"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "今日 %@"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"오늘 %lld회": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Today %lld times"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "今日%lld回"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"월간": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Monthly"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "月間"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"주간": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Weekly"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "週間"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"즐겨찾기": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Favorites"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "お気に入り"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"초과": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Over"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "超過"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"측정 중": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Tracking"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "計測中"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"측정 중인 행동과 경과 시간을 표시해요. (프리미엄)": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Shows the running action and elapsed time. (Premium)"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "計測中のアクションと経過時間を表示します。(プレミアム)"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"측정 표시 새로고침 필요": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Timer display needs a refresh"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "計測表示の更新が必要"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"측정 표시가 오래됐어요": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Timer display is out of date"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "計測表示が古くなっています"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"표시할 다짐과 기간을 선택하세요.": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Choose a quest and period to display."
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "表示するクエストと期間を選んでください。"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"표시할 목표와 기간을 선택하세요.": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Choose a goal and period to display."
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "表示する目標と期間を選んでください。"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"프리미엄": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Premium"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "プレミアム"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"프리미엄 기능": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Premium Features"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "プレミアム機能"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"하루": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Daily"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "1日"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"하루 다님": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Haru Danim"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "ハルダニム"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"한도": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Limit"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "上限"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"한도 안": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Within"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "上限内"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"한도 초과": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Over limit"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "上限超過"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"현재 현황": {
|
|
"localizations": {
|
|
"en": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "Current Status"
|
|
}
|
|
},
|
|
"ja": {
|
|
"stringUnit": {
|
|
"state": "translated",
|
|
"value": "現在の状況"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"version": "1.0"
|
|
} |