fix(l10n): complete ko/en/ja coverage — sync catalogs, translate 123 strings, localize stats titles and filter sheet
- 카탈로그 4종 xcstringstool sync + stale 키 64개 제거 - 버블 메뉴·위젯 5종·이미지 내보내기 신규 문자열 en/ja 전량 번역 - StatsTabView 카드 제목·RecordFilterSheet 제목이 String 파라미터라 미현지화되던 것을 LocalizedStringKey로 수정 - HistoryView 필터 칩 문자열 String(localized:) 누락 수정 - 위젯 익스텐션 InfoPlist.xcstrings 신설(표시 이름 현지화), iOS에 사진 권한 문구 ko/en/ja 추가, 워치 ja 앱 이름 'Haru Danim'으로 통일 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013yKDMhuF39GVYy3FMcGHh7
This commit is contained in:
parent
cde4c4001b
commit
5c3017aeaa
@ -106,6 +106,7 @@
|
||||
membershipExceptions = (
|
||||
HaruDanimWidgets.swift,
|
||||
Info.plist,
|
||||
InfoPlist.xcstrings,
|
||||
Localizable.xcstrings,
|
||||
);
|
||||
target = 725A9E832FFCC65000846FFB /* Haru_Danim */;
|
||||
|
||||
@ -1,42 +1,43 @@
|
||||
{
|
||||
"sourceLanguage" : "ko",
|
||||
"strings" : {
|
||||
"CFBundleDisplayName" : {
|
||||
"comment" : "Bundle display name",
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Haru Danim"
|
||||
"sourceLanguage": "ko",
|
||||
"strings": {
|
||||
"CFBundleDisplayName": {
|
||||
"comment": "Bundle display name",
|
||||
"extractionState": "manual",
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Haru Danim"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "ハルダニム"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Haru Danim"
|
||||
}
|
||||
},
|
||||
"ko" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "하루 다님"
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "하루 다님"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"CFBundleName" : {
|
||||
"comment" : "Bundle name",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"ko" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Haru_DanimWatch Watch App"
|
||||
"CFBundleName": {
|
||||
"comment": "Bundle name",
|
||||
"extractionState": "extracted_with_value",
|
||||
"localizations": {
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "new",
|
||||
"value": "Haru_DanimWatch Watch App"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"shouldTranslate": false
|
||||
}
|
||||
},
|
||||
"version" : "1.0"
|
||||
"version": "1.0"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,54 +1,56 @@
|
||||
{
|
||||
"sourceLanguage" : "ko",
|
||||
"strings" : {
|
||||
"CFBundleDisplayName" : {
|
||||
"comment" : "Bundle display name",
|
||||
"extractionState" : "manual",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Haru Danim"
|
||||
"sourceLanguage": "ko",
|
||||
"strings": {
|
||||
"CFBundleDisplayName": {
|
||||
"comment": "Bundle display name",
|
||||
"extractionState": "manual",
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Haru Danim"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "ハルダニム"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Haru Danim"
|
||||
}
|
||||
},
|
||||
"ko" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "하루 다님"
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "하루 다님"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"CFBundleName" : {
|
||||
"comment" : "Bundle name",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"ko" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Haru_DanimWatchWidgetsExtension"
|
||||
"CFBundleName": {
|
||||
"comment": "Bundle name",
|
||||
"extractionState": "extracted_with_value",
|
||||
"localizations": {
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "new",
|
||||
"value": "Haru_DanimWatchWidgetsExtension"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"shouldTranslate": false
|
||||
},
|
||||
"NSHumanReadableCopyright" : {
|
||||
"comment" : "Copyright (human-readable)",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"ko" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : ""
|
||||
"NSHumanReadableCopyright": {
|
||||
"comment": "Copyright (human-readable)",
|
||||
"extractionState": "extracted_with_value",
|
||||
"localizations": {
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "new",
|
||||
"value": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"shouldTranslate": false
|
||||
}
|
||||
},
|
||||
"version" : "1.0"
|
||||
"version": "1.0"
|
||||
}
|
||||
@ -1,538 +1,504 @@
|
||||
{
|
||||
"sourceLanguage" : "ko",
|
||||
"strings" : {
|
||||
"%@" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@"
|
||||
"sourceLanguage": "ko",
|
||||
"strings": {
|
||||
"%@": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "%@"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "%@"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"%@ %@" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ %@"
|
||||
"%@ %@": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "%@ %@"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ %@"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "%@ %@"
|
||||
}
|
||||
},
|
||||
"ko" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "%1$@ %2$@"
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "new",
|
||||
"value": "%1$@ %2$@"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"%@ %lld%%" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ %lld%%"
|
||||
"%@ %lld%%": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "%@ %lld%%"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ %lld%%"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "%@ %lld%%"
|
||||
}
|
||||
},
|
||||
"ko" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "%1$@ %2$lld%%"
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "new",
|
||||
"value": "%1$@ %2$lld%%"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"%@ +%lld" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ +%lld"
|
||||
"%@ +%lld": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "%@ +%lld"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%@ +%lld"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "%@ +%lld"
|
||||
}
|
||||
},
|
||||
"ko" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "%1$@ +%2$lld"
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "new",
|
||||
"value": "%1$@ +%2$lld"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"%lld" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%lld"
|
||||
"%lld": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "%lld"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%lld"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "%lld"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"%lld%%" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%lld%%"
|
||||
"%lld%%": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "%lld%%"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "%lld%%"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "%lld%%"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"+%lld" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "+%lld"
|
||||
"+%lld": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "+%lld"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "+%lld"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "+%lld"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"기간" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Period"
|
||||
"기간": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Period"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "期間"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "期間"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"다짐" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Quest"
|
||||
"다짐": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Quest"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "クエスト"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "クエスト"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"다짐 달성률" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Quest Progress"
|
||||
"다짐 달성률": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Quest Progress"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "クエスト達成率"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "クエスト達成率"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"다짐 달성률 (%@)" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Quest progress (%@)"
|
||||
"목표": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Goals"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "クエスト達成率(%@)"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "目標"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"목표" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Goals"
|
||||
"목표 달성률": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Goal Progress"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "目標"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "目標達成率"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"목표 달성률" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Goal Progress"
|
||||
"선택한 다짐의 달성률을 표시해요. 한도형 다짐은 상태로 표시돼요. (프리미엄)": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Shows the selected quest's progress. Limit quests show their status. (Premium)"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "目標達成率"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "選択したクエストの達成率を表示します。上限型はステータス表示になります。(プレミアム)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"목표 달성률 (%@)" : {
|
||||
"extractionState" : "stale",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Goal progress (%@)"
|
||||
"선택한 목표의 하루/주간/월간 달성률을 표시해요. (프리미엄)": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Shows the selected goal's daily/weekly/monthly progress. (Premium)"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "目標達成率(%@)"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "選択した目標の日/週/月の達成率を表示します。(プレミアム)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"선택한 다짐의 달성률을 표시해요. 한도형 다짐은 상태로 표시돼요. (프리미엄)" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Shows the selected quest's progress. Limit quests show their status. (Premium)"
|
||||
"실행 중 아님": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Not running"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "選択したクエストの達成率を表示します。上限型はステータス表示になります。(プレミアム)"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "実行中なし"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"선택한 목표의 하루/주간/월간 달성률을 표시해요. (프리미엄)" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Shows the selected goal's daily/weekly/monthly progress. (Premium)"
|
||||
"없음": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "None"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "選択した目標の日/週/月の達成率を表示します。(プレミアム)"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "なし"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"실행 중 아님" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Not running"
|
||||
"월간": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Monthly"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "実行中なし"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "月間"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"없음" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "None"
|
||||
"주간": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Weekly"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "なし"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "週間"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"월간" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Monthly"
|
||||
"초과": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Over"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "月間"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "超過"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"주간" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Weekly"
|
||||
"측정 중": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Tracking"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "週間"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "計測中"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"초과" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Over"
|
||||
"측정 중인 행동과 경과 시간을 표시해요. (프리미엄)": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Shows the running action and elapsed time. (Premium)"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "超過"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "計測中のアクションと経過時間を表示します。(プレミアム)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"측정 중" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Tracking"
|
||||
"표시할 다짐과 기간을 선택하세요.": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Choose a quest and period to display."
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "計測中"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "表示するクエストと期間を選んでください。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"측정 중인 행동과 경과 시간을 표시해요. (프리미엄)" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Shows the running action and elapsed time. (Premium)"
|
||||
"표시할 목표와 기간을 선택하세요.": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Choose a goal and period to display."
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "計測中のアクションと経過時間を表示します。(プレミアム)"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "表示する目標と期間を選んでください。"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"표시할 다짐과 기간을 선택하세요." : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Choose a quest and period to display."
|
||||
"프리미엄": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Premium"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "表示するクエストと期間を選んでください。"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "プレミアム"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"표시할 목표와 기간을 선택하세요." : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Choose a goal and period to display."
|
||||
"하루": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Daily"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "表示する目標と期間を選んでください。"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "1日"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"프리미엄" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Premium"
|
||||
"하루 다님": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Haru Danim"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "プレミアム"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "ハルダニム"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"하루" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Daily"
|
||||
"한도": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Limit"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "1日"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "上限"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"하루 다님" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Haru Danim"
|
||||
"한도 안": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Within"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "ハルダニム"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "上限内"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"한도" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Limit"
|
||||
"한도 초과": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Over limit"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "上限"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "上限超過"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"한도 안" : {
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Within"
|
||||
"현재 현황": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Current Status"
|
||||
}
|
||||
},
|
||||
"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" : "現在の状況"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "現在の状況"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"version" : "1.0"
|
||||
"version": "1.0"
|
||||
}
|
||||
@ -1,41 +1,66 @@
|
||||
{
|
||||
"sourceLanguage" : "ko",
|
||||
"strings" : {
|
||||
"CFBundleDisplayName" : {
|
||||
"comment" : "홈 화면에 표시되는 앱 이름",
|
||||
"localizations" : {
|
||||
"en" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Haru Danim"
|
||||
"sourceLanguage": "ko",
|
||||
"strings": {
|
||||
"CFBundleDisplayName": {
|
||||
"comment": "홈 화면에 표시되는 앱 이름",
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Haru Danim"
|
||||
}
|
||||
},
|
||||
"ja" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "Haru Danim"
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Haru Danim"
|
||||
}
|
||||
},
|
||||
"ko" : {
|
||||
"stringUnit" : {
|
||||
"state" : "translated",
|
||||
"value" : "하루 다님"
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "하루 다님"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"CFBundleName" : {
|
||||
"comment" : "Bundle name",
|
||||
"extractionState" : "extracted_with_value",
|
||||
"localizations" : {
|
||||
"ko" : {
|
||||
"stringUnit" : {
|
||||
"state" : "new",
|
||||
"value" : "Haru_Danim"
|
||||
"CFBundleName": {
|
||||
"comment": "Bundle name",
|
||||
"extractionState": "extracted_with_value",
|
||||
"localizations": {
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "new",
|
||||
"value": "Haru_Danim"
|
||||
}
|
||||
}
|
||||
},
|
||||
"shouldTranslate": false
|
||||
},
|
||||
"NSPhotoLibraryAddUsageDescription": {
|
||||
"comment": "이미지 내보내기 → 사진에 저장 권한 문구",
|
||||
"extractionState": "manual",
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Needed to save exported report images to your photo library."
|
||||
}
|
||||
},
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "書き出したレポート画像を写真アルバムに保存するために必要です。"
|
||||
}
|
||||
},
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "내보낸 리포트 이미지를 사진 앨범에 저장하기 위해 필요해요."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"version" : "1.0"
|
||||
"version": "1.0"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1038,8 +1038,8 @@ private struct ExportTimetableView: View {
|
||||
HStack(alignment: .top, spacing: spacing) {
|
||||
VStack(spacing: 3) {
|
||||
if weekly {
|
||||
// 요일 라벨 줄 높이만큼 시간축을 내려 컬럼과 정렬
|
||||
Text(" ")
|
||||
// 요일 라벨 줄 높이만큼 시간축을 내려 컬럼과 정렬 (verbatim: 추출 방지)
|
||||
Text(verbatim: " ")
|
||||
.font(.caption2)
|
||||
}
|
||||
hourLabels
|
||||
|
||||
@ -214,7 +214,7 @@ struct HistoryView: View {
|
||||
if names.isEmpty { return String(localized: "표시할 행동 없음") }
|
||||
return names.count <= 2
|
||||
? names.joined(separator: ", ")
|
||||
: "행동 \(names.count)/\(allActions.count)개 표시 중"
|
||||
: String(localized: "행동 \(names.count)/\(allActions.count)개 표시 중")
|
||||
}
|
||||
|
||||
private var filterChip: some View {
|
||||
|
||||
@ -12,7 +12,8 @@ import SwiftData
|
||||
|
||||
struct RecordFilterSheet: View {
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
let title: String
|
||||
// 리터럴 호출부('기록 필터'/'통계 필터')가 카탈로그로 추출되도록 LocalizedStringKey 사용
|
||||
let title: LocalizedStringKey
|
||||
let tags: [Tag]
|
||||
let actions: [Action]
|
||||
@Binding var excludedActionIDs: Set<PersistentIdentifier>
|
||||
|
||||
@ -571,7 +571,7 @@ struct StatsTabView: View {
|
||||
// MARK: 꺾은선 카드 (선 색 = 행동/태그 색, 범례 표시)
|
||||
|
||||
@ViewBuilder
|
||||
private func dailyLineCard(_ title: String, type: TrackingType, weekdayAxis: Bool) -> some View {
|
||||
private func dailyLineCard(_ title: LocalizedStringKey, type: TrackingType, weekdayAxis: Bool) -> some View {
|
||||
let actions = activeActions(for: type)
|
||||
let names = actions.map(\.name)
|
||||
let colors = actions.map(\.color)
|
||||
@ -613,7 +613,7 @@ struct StatsTabView: View {
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func weeklyLineCard(_ title: String, type: TrackingType) -> some View {
|
||||
private func weeklyLineCard(_ title: LocalizedStringKey, type: TrackingType) -> some View {
|
||||
let actions = activeActions(for: type)
|
||||
let names = actions.map(\.name)
|
||||
let colors = actions.map(\.color)
|
||||
@ -640,7 +640,7 @@ struct StatsTabView: View {
|
||||
// MARK: 합계 막대 카드 (기간 누적 비율 비교)
|
||||
|
||||
@ViewBuilder
|
||||
private func totalsBarCard(_ title: String, type: TrackingType) -> some View {
|
||||
private func totalsBarCard(_ title: LocalizedStringKey, type: TrackingType) -> some View {
|
||||
let items = totals(for: type)
|
||||
chartCard(title) {
|
||||
if items.isEmpty {
|
||||
@ -717,7 +717,7 @@ struct StatsTabView: View {
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func summaryTableCard(_ title: String, timeRows: [SummaryRowItem], countRows: [SummaryRowItem]) -> some View {
|
||||
private func summaryTableCard(_ title: LocalizedStringKey, timeRows: [SummaryRowItem], countRows: [SummaryRowItem]) -> some View {
|
||||
chartCard(title) {
|
||||
if timeRows.isEmpty && countRows.isEmpty {
|
||||
emptyChartText
|
||||
@ -737,7 +737,7 @@ struct StatsTabView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private func summaryGrid(sectionLabel: String, rows: [SummaryRowItem]) -> some View {
|
||||
private func summaryGrid(sectionLabel: LocalizedStringKey, rows: [SummaryRowItem]) -> some View {
|
||||
Grid(alignment: .leading, horizontalSpacing: 10, verticalSpacing: 12) {
|
||||
GridRow {
|
||||
Text(sectionLabel)
|
||||
@ -784,7 +784,7 @@ struct StatsTabView: View {
|
||||
|
||||
// MARK: 공통
|
||||
|
||||
private func chartCard(_ title: String, @ViewBuilder content: () -> some View) -> some View {
|
||||
private func chartCard(_ title: LocalizedStringKey, @ViewBuilder content: () -> some View) -> some View {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
Text(title)
|
||||
.font(.subheadline.weight(.semibold))
|
||||
|
||||
30
myApp/HaruDanim/Widgets/InfoPlist.xcstrings
Normal file
30
myApp/HaruDanim/Widgets/InfoPlist.xcstrings
Normal file
@ -0,0 +1,30 @@
|
||||
{
|
||||
"sourceLanguage": "ko",
|
||||
"strings": {
|
||||
"CFBundleDisplayName": {
|
||||
"comment": "위젯 익스텐션 표시 이름",
|
||||
"extractionState": "manual",
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Haru Danim"
|
||||
}
|
||||
},
|
||||
"ja": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Haru Danim"
|
||||
}
|
||||
},
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "하루 다님"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"version": "1.0"
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user