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:
songyc macbook 2026-07-13 02:24:28 +09:00
parent cde4c4001b
commit 5c3017aeaa
13 changed files with 7869 additions and 6886 deletions

View File

@ -106,6 +106,7 @@
membershipExceptions = (
HaruDanimWidgets.swift,
Info.plist,
InfoPlist.xcstrings,
Localizable.xcstrings,
);
target = 725A9E832FFCC65000846FFB /* Haru_Danim */;

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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>

View File

@ -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))

View 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