Skip to content

Commit 9293946

Browse files
committed
Add Korean (ko) localization
Introduce Korean localization: add 'ko' to the Xcode project and AppLanguage enum (locale, display key and raw value), include Korean Localizable.strings and PrivacyPolicy.html in ko.lproj, add Korean entries to en/fil/ja string tables, and update unit tests to cover the new language and resources.
1 parent 3aa8fe5 commit 9293946

9 files changed

Lines changed: 365 additions & 0 deletions

File tree

CycleOne.xcodeproj/project.pbxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@
208208
fil,
209209
ja,
210210
Base,
211+
ko,
211212
);
212213
mainGroup = 35B9FFB82F7136200074EB22;
213214
minimizedProjectReferenceProxies = 1;

CycleOne/Core/Localization/AppLanguage.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ enum AppLanguage: String, CaseIterable, Identifiable {
1111
case english = "en"
1212
case filipino = "fil"
1313
case japanese = "ja"
14+
case korean = "ko"
1415

1516
static let storageKey = "selected_app_language"
1617

@@ -28,6 +29,8 @@ enum AppLanguage: String, CaseIterable, Identifiable {
2829
Locale(identifier: "fil")
2930
case .japanese:
3031
Locale(identifier: "ja")
32+
case .korean:
33+
Locale(identifier: "ko")
3134
}
3235
}
3336

@@ -41,6 +44,8 @@ enum AppLanguage: String, CaseIterable, Identifiable {
4144
"settings.language.filipino"
4245
case .japanese:
4346
"settings.language.japanese"
47+
case .korean:
48+
"settings.language.korean"
4449
}
4550
}
4651

@@ -66,6 +71,8 @@ enum AppLanguage: String, CaseIterable, Identifiable {
6671
"fil"
6772
case .japanese:
6873
"ja"
74+
case .korean:
75+
"ko"
6976
}
7077
}
7178

CycleOne/LocalizationResources/en.lproj/Localizable.strings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"settings.language.english" = "English";
5858
"settings.language.filipino" = "Filipino";
5959
"settings.language.japanese" = "Japanese";
60+
"settings.language.korean" = "Korean";
6061
"settings.accent_color" = "Accent Color";
6162
"settings.accent.rose" = "Rose";
6263
"settings.accent.lavender" = "Lavender";

CycleOne/LocalizationResources/fil.lproj/Localizable.strings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"settings.language.english" = "Ingles";
5858
"settings.language.filipino" = "Filipino";
5959
"settings.language.japanese" = "Hapones";
60+
"settings.language.korean" = "Koreano";
6061
"settings.accent_color" = "Kulay ng Accent";
6162
"settings.accent.rose" = "Rosas";
6263
"settings.accent.lavender" = "Lavender";

CycleOne/LocalizationResources/ja.lproj/Localizable.strings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
"settings.language.english" = "英語";
5858
"settings.language.filipino" = "フィリピン語";
5959
"settings.language.japanese" = "日本語";
60+
"settings.language.korean" = "韓国語";
6061
"settings.accent_color" = "アクセントカラー";
6162
"settings.accent.rose" = "ローズ";
6263
"settings.accent.lavender" = "ラベンダー";
Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
"tab.calendar" = "캘린더";
2+
"tab.insights" = "인사이트";
3+
"tab.settings" = "설정";
4+
5+
"common.vs" = "대";
6+
"common.na" = "해당 없음";
7+
"common.same" = "같음";
8+
"common.days_format" = "%d일";
9+
"common.days_short_format" = "%d일";
10+
"common.unknown" = "알 수 없음";
11+
"common.unit.days" = "일";
12+
13+
"flow.none" = "없음";
14+
"flow.light" = "가벼움";
15+
"flow.medium" = "보통";
16+
"flow.heavy" = "많음";
17+
18+
"mood.happy" = "행복";
19+
"mood.neutral" = "보통";
20+
"mood.sad" = "슬픔";
21+
"mood.anxious" = "불안";
22+
"mood.angry" = "화남";
23+
24+
"energy.low" = "낮음";
25+
"energy.medium" = "보통";
26+
"energy.high" = "높음";
27+
28+
"symptom.category.physical" = "신체";
29+
"symptom.category.mood" = "기분 및 정신";
30+
"symptom.category.digestion" = "소화";
31+
"symptom.category.other" = "기타";
32+
33+
"symptom.cramps" = "복통";
34+
"symptom.bloating" = "복부 팽만";
35+
"symptom.headache" = "두통";
36+
"symptom.acne" = "여드름";
37+
"symptom.breast_tenderness" = "유방 통증";
38+
"symptom.back_pain" = "허리 통증";
39+
"symptom.dizziness" = "어지러움";
40+
"symptom.nausea" = "메스꺼움";
41+
"symptom.mood_swings" = "기분 변화";
42+
"symptom.irritability" = "예민함";
43+
"symptom.fatigue" = "피로";
44+
"symptom.cravings" = "식욕 증가";
45+
"symptom.insomnia" = "불면";
46+
47+
"settings.section.preferences" = "환경설정";
48+
"settings.enable_predictions" = "예측 사용";
49+
"settings.notifications" = "알림";
50+
"settings.section.appearance" = "화면";
51+
"settings.theme" = "테마";
52+
"settings.theme.system" = "시스템";
53+
"settings.theme.light" = "라이트";
54+
"settings.theme.dark" = "다크";
55+
"settings.language" = "언어";
56+
"settings.language.system" = "시스템 기본값";
57+
"settings.language.english" = "영어";
58+
"settings.language.filipino" = "필리핀어";
59+
"settings.language.japanese" = "일본어";
60+
"settings.language.korean" = "한국어";
61+
"settings.accent_color" = "강조 색상";
62+
"settings.accent.rose" = "로즈";
63+
"settings.accent.lavender" = "라벤더";
64+
"settings.accent.ocean" = "오션";
65+
"settings.accent.sage" = "세이지";
66+
"settings.accent.sunset" = "선셋";
67+
"settings.section.data" = "데이터";
68+
"settings.export_csv" = "데이터 내보내기 (CSV)";
69+
"settings.delete_all_data" = "모든 데이터 삭제";
70+
"settings.section.app" = "앱";
71+
"settings.help_guide" = "도움말 및 가이드";
72+
"settings.support_feedback" = "지원 및 피드백";
73+
"settings.privacy_policy" = "개인정보 처리방침";
74+
"settings.rate_cycleone" = "CycleOne 평가하기";
75+
"settings.about" = "정보";
76+
"settings.footer.byline" = "VoxDroid의 CycleOne";
77+
"settings.footer.copyright" = "© 2026 VoxDroid. All rights reserved.";
78+
"settings.navigation_title" = "설정";
79+
"settings.alert.delete_title" = "모든 데이터를 삭제하시겠습니까?";
80+
"settings.alert.delete_action" = "삭제";
81+
"settings.alert.cancel_action" = "취소";
82+
"settings.alert.delete_message" = "이 작업은 되돌릴 수 없습니다. 기록된 모든 주기와 증상이 영구적으로 삭제됩니다.";
83+
84+
"settings.notifications.title" = "알림";
85+
"settings.notifications.section.period" = "생리 알림";
86+
"settings.notifications.toggle.period" = "생리 전 알림 받기";
87+
"settings.notifications.section.fertile" = "가임기";
88+
"settings.notifications.toggle.fertile" = "가임기 알림";
89+
"settings.notifications.footer" = "알림은 기기에서 오전 8:00에 로컬로 예약됩니다.";
90+
"settings.notifications.days_before" = "며칠 전";
91+
"settings.notifications.days.1" = "1일";
92+
"settings.notifications.days.2" = "2일";
93+
"settings.notifications.days.3" = "3일";
94+
"settings.notifications.days.5" = "5일";
95+
"settings.notifications.days.format" = "%d일";
96+
97+
"notifications.content.title" = "CycleOne";
98+
"notifications.content.period.body" = "내일 생리가 시작될 것으로 예상됩니다.";
99+
"notifications.content.fertile.body" = "내일부터 가임기가 시작됩니다.";
100+
101+
"calendar.legend.title" = "캘린더 범례";
102+
"calendar.legend.period" = "생리";
103+
"calendar.legend.predicted" = "예측";
104+
"calendar.legend.ovulation" = "배란";
105+
"calendar.legend.fertile" = "가임기";
106+
"calendar.legend.logged" = "기록됨";
107+
108+
"calendar.day.no_period_logged" = "생리 기록 없음";
109+
"calendar.day.log_day" = "기록하기";
110+
"calendar.day.edit_log" = "기록 수정";
111+
"calendar.day.tap_to_log" = "주기, 증상 또는 기분을 기록하려면 탭하세요.";
112+
"calendar.day.flow_fallback" = "생리량";
113+
114+
"calendar.header.irregular" = "불규칙";
115+
"calendar.header.disclaimer" = "예측은 참고용이며 의학적 조언이 아닙니다.";
116+
"calendar.header.log_first" = "첫 생리를 기록해보세요";
117+
"calendar.header.overdue" = "생리가 지연되고 있어요";
118+
"calendar.header.starts_today" = "오늘 생리가 시작됩니다";
119+
"calendar.header.next_period" = "다음 생리";
120+
"calendar.header.expected_today" = "오늘 예정";
121+
"calendar.header.overdue_by_days" = "%d일 지연";
122+
"calendar.header.in_days" = "%d일 후";
123+
"calendar.header.ovulation_starts_today" = "오늘 배란이 시작됩니다";
124+
"calendar.header.ovulation_in_days" = "배란까지 %d일";
125+
126+
"insights.avg_cycle" = "평균 주기";
127+
"insights.avg_period" = "평균 생리 기간";
128+
"insights.shortest" = "최단";
129+
"insights.longest" = "최장";
130+
"insights.total" = "총합";
131+
"insights.avg_pain" = "평균 통증";
132+
"insights.logged" = "기록 수";
133+
"insights.symptoms" = "증상";
134+
135+
"insights.history.empty_title" = "아직 데이터가 없어요";
136+
"insights.history.empty_message" = "첫 생리를 기록하면 주기 기록이 여기에 표시됩니다.";
137+
"insights.history.past_cycles" = "이전 주기";
138+
"insights.history.title" = "기록";
139+
"insights.history.period_days_format" = "생리 %d일";
140+
141+
"insights.compare.title" = "주기 비교";
142+
"insights.compare.current" = "현재";
143+
"insights.compare.previous" = "이전";
144+
"insights.compare.start_date" = "시작일";
145+
"insights.compare.cycle_length" = "주기 길이";
146+
"insights.compare.period_length" = "생리 기간";
147+
"insights.compare.length_comparison" = "길이 비교";
148+
"insights.compare.navigation_title" = "주기 비교";
149+
"insights.compare.empty_title" = "데이터가 부족합니다";
150+
"insights.compare.empty_message" = "비교하려면 최소 두 번의 주기를 기록하세요.";
151+
152+
"onboarding.page1.title" = "CycleOne에 오신 것을 환영합니다";
153+
"onboarding.page1.subtitle" = "개인정보를 최우선으로 하는 생리 추적기입니다.\n구독 없음. 클라우드 없음. 계정 없음.";
154+
"onboarding.page2.title" = "주기 기록하기";
155+
"onboarding.page2.subtitle" = "캘린더에서 원하는 날짜를 눌러 생리, 증상, 기분, 에너지를 기록하세요.";
156+
"onboarding.page3.title" = "패턴 파악하기";
157+
"onboarding.page3.subtitle" = "주기 길이, 주요 증상, 예측 정보를 확인하세요.";
158+
"onboarding.page4.title" = "데이터는 안전하게 보관됩니다";
159+
"onboarding.page4.subtitle" = "모든 데이터는 기기에만 저장됩니다.\n서버 없음. 추적 없음. 영원히.";
160+
"onboarding.next" = "다음";
161+
"onboarding.get_started" = "시작하기";
162+
"onboarding.skip" = "건너뛰기";
163+
164+
"log.pain_level_format" = "통증 수준: %d";
165+
"privacy_policy.not_found" = "개인정보 처리방침을 찾을 수 없습니다.";
166+
"export.csv.header" = "날짜,생리량,통증,기분,에너지,증상,메모";
167+
168+
"Log your day" = "오늘을 기록하세요";
169+
"Flow" = "생리량";
170+
"Mood & Energy" = "기분 및 에너지";
171+
"Symptoms" = "증상";
172+
"Add notes..." = "메모 추가...";
173+
"Notes" = "메모";
174+
"Delete This Log" = "이 기록 삭제";
175+
"Log Day" = "기록하기";
176+
"Dismiss" = "닫기";
177+
"Delete Log?" = "기록을 삭제할까요?";
178+
"Delete" = "삭제";
179+
"Cancel" = "취소";
180+
"This will permanently remove this day's log and all associated symptoms." = "이 날짜의 기록과 모든 관련 증상이 영구적으로 삭제됩니다.";
181+
182+
"Cycle Length Trend" = "주기 길이 추세";
183+
"Mood Distribution" = "기분 분포";
184+
"Top Symptoms" = "주요 증상";
185+
"Compare Cycles" = "주기 비교";
186+
"View Full History" = "전체 기록 보기";
187+
"Insights" = "인사이트";
188+
189+
"User Guide" = "사용자 가이드";
190+
"Calendar" = "캘린더";
191+
"Logging" = "기록";
192+
"Reminders" = "알림";
193+
"The main screen shows your cycle. Tap any date to view details or log data." = "메인 화면에서 주기를 확인할 수 있습니다. 날짜를 탭해 상세 보기 또는 기록을 남기세요.";
194+
"Log your flow, symptoms, mood, and energy. Auto-saved when you navigate away." = "생리량, 증상, 기분, 에너지를 기록하세요. 화면을 벗어나면 자동 저장됩니다.";
195+
"View your average cycle length, period duration, and top symptoms." = "평균 주기 길이, 생리 기간, 주요 증상을 확인하세요.";
196+
"Enable notifications in Settings for alerts before period or fertile window." = "설정에서 생리 전 또는 가임기 알림을 활성화하세요.";
197+
"Quick Tips" = "빠른 팁";
198+
"Swipe left or right to change months." = "좌우로 스와이프해 월을 변경하세요.";
199+
"Tap the detail card to log or edit." = "상세 카드에서 기록하거나 수정할 수 있습니다.";
200+
"Check Insights to understand patterns." = "인사이트에서 패턴을 확인하세요.";
201+
"Export your data anytime — you own it." = "데이터는 언제든 내보낼 수 있으며, 소유권은 사용자에게 있습니다.";
202+
"App Philosophy" = "앱 철학";
203+
"Privacy First" = "개인정보 우선";
204+
"Zero cloud sync and zero tracking. Data stays on your device." = "클라우드 동기화와 추적이 전혀 없습니다. 데이터는 기기에만 저장됩니다.";
205+
"No Subscriptions" = "구독 없음";
206+
"Don't pay monthly for your own health data. One purchase, forever." = "내 건강 데이터에 월 구독료를 내지 마세요. 한 번 구매로 계속 사용하세요.";
207+
"Manual & Support" = "매뉴얼 및 지원";
208+
"View Project on GitHub" = "GitHub에서 프로젝트 보기";
209+
"Privacy Policy" = "개인정보 처리방침";
210+
"Help & Guide" = "도움말 및 가이드";
211+
212+
"Export Your Data" = "데이터 내보내기";
213+
"Get a CSV file of all your logged cycles and symptoms. Your data stays private." = "기록한 모든 주기와 증상을 CSV 파일로 내보낼 수 있습니다. 데이터는 비공개로 유지됩니다.";
214+
"Generating CSV..." = "CSV 생성 중...";
215+
"Share CSV File" = "CSV 파일 공유";
216+
"Regenerate" = "다시 생성";
217+
"Generate CSV" = "CSV 생성";
218+
"Export is plaintext only. No proprietary format." = "내보내기는 일반 텍스트 형식만 지원합니다. 독점 형식은 사용하지 않습니다.";
219+
"Export" = "내보내기";
220+
221+
"A privacy-first, open-source period tracker for iOS." = "개인정보 보호를 최우선으로 하는 iOS용 오픈소스 생리 추적기입니다.";
222+
"Developer" = "개발자";
223+
"VoxDroid" = "VoxDroid";
224+
"Lead Developer" = "리드 개발자";
225+
"izeno.contact@gmail.com" = "izeno.contact@gmail.com";
226+
"Direct Support" = "직접 지원";
227+
"github.com/VoxDroid" = "github.com/VoxDroid";
228+
"Follow on GitHub" = "GitHub에서 팔로우";
229+
"Project" = "프로젝트";
230+
"Source Code" = "소스 코드";
231+
"GPL-3.0 Licensed" = "GPL-3.0 Licensed";
232+
"Privacy Commitment" = "개인정보 보호 약속";
233+
"100% local, zero tracking" = "100% local, zero tracking";
234+
"Built with Swift" = "Swift로 제작";
235+
"SwiftUI + Core Data" = "SwiftUI + Core Data";
236+
"CycleOne by VoxDroid" = "CycleOne by VoxDroid";
237+
"© 2026 VoxDroid. All rights reserved." = "© 2026 VoxDroid. All rights reserved.";
238+
"About" = "정보";
239+
240+
"CycleOne" = "CycleOne";
241+
"Version 1.0.0" = "Version 1.0.0";
242+
"Privacy-first period tracking" = "개인정보 우선 생리 추적";

0 commit comments

Comments
 (0)