Explorar o código

Add Korean localization and language picker support.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 hai 1 mes
pai
achega
e4ac0f116d

+ 1 - 0
Info.plist

@@ -15,6 +15,7 @@
 		<string>fr-CA</string>
 		<string>de</string>
 		<string>sv</string>
+		<string>ko</string>
 		<string>zh-Hans</string>
 		<string>zh-Hant</string>
 	</array>

+ 1 - 0
meetings_app.xcodeproj/project.pbxproj

@@ -101,6 +101,7 @@
 				"fr-CA",
 				de,
 				sv,
+				ko,
 				"zh-Hans",
 				"zh-Hant",
 			);

+ 3 - 1
meetings_app/Localization/AppLanguageManager.swift

@@ -8,7 +8,7 @@ enum AppLanguageManager {
     private static let defaultsKey = "settings.appLanguageCode"
 
     /// UI languages shown in Settings → Language (order preserved).
-    private static let supportedLanguageCodes = ["en", "fr", "fr-CA", "de", "sv", "zh-Hans", "zh-Hant"]
+    private static let supportedLanguageCodes = ["en", "fr", "fr-CA", "de", "sv", "ko", "zh-Hans", "zh-Hant"]
 
     /// `nil` follows the system language; otherwise uses the selected `.lproj` code.
     static var selectedLanguageCode: String? {
@@ -65,6 +65,8 @@ enum AppLanguageManager {
             return "Deutsch"
         case "sv":
             return "Svenska"
+        case "ko":
+            return "한국어"
         case "zh-Hans":
             return "简体中文"
         case "zh-Hant":

+ 4 - 0
meetings_app/ko.lproj/InfoPlist.strings

@@ -0,0 +1,4 @@
+"CFBundleDisplayName" = "미트 인공지능 어시스턴트";
+"CFBundleName" = "미트 인공지능 어시스턴트";
+"NSMicrophoneUsageDescription" = "귀하의 동의 하에 앱은 이 Mac에서 회의 오디오를 녹화하고 회의 종료 후 인공지능 어시스턴트에 표시합니다.";
+"NSSpeechRecognitionUsageDescription" = "이 앱은 저장된 회의 오디오를 인공지능 어시스턴트용 텍스트 전사로 변환합니다.";

+ 452 - 0
meetings_app/ko.lproj/Localizable.strings

@@ -0,0 +1,452 @@
+/* AppBrand.name ("Meetings") 의도적으로 생략 — 앱 이름은 코드에서 변경되지 않습니다. */
+"AI Companion for Meet" = "미트 인공지능 어시스턴트";
+
+/* MARK: - 일반 */
+"OK" = "확인";
+"Cancel" = "취소";
+"Continue" = "계속";
+"Apply" = "적용";
+"Reset" = "재설정";
+"Save" = "저장";
+"Copy" = "복사";
+"Copied" = "복사됨";
+"Close" = "닫기";
+"Join" = "참가";
+"None" = "없음";
+"Link" = "링크";
+"Stop" = "중지";
+"Address" = "주소";
+"Title" = "제목";
+"Notes" = "메모";
+"Start" = "시작";
+"Premium" = "프리미엄";
+"Popular" = "인기";
+"Browser" = "브라우저";
+"Meeting" = "회의";
+"Error" = "오류";
+"Success" = "성공";
+
+/* MARK: - 상태 표시줄 */
+"Meetings status menu" = "회의 상태 메뉴";
+"Open App" = "앱 열기";
+"Join Meetings" = "회의 참가";
+"Schedule" = "일정";
+"Calendar" = "달력";
+"Widgets" = "위젯";
+"AI Companion" = "인공지능 어시스턴트";
+"Settings" = "설정";
+"Top meetings" = "상단 고정 회의";
+"No upcoming meetings" = "예정된 회의 없음";
+"Sign Out" = "로그아웃";
+"Sign In" = "로그인";
+"Quit" = "종료";
+
+/* MARK: - 시작 스플래시 */
+"Preparing your meetings workspace" = "회의 작업 공간을 준비하는 중";
+"CONNECTING SERVICES" = "서비스 연결 중";
+"READY" = "준비됨";
+"Plan smart, achieve more" = "스마트하게 계획하고 더 많이 달성하세요";
+
+/* MARK: - 위젯 */
+"Add Widget to Desktop" = "데스크탑에 위젯 추가";
+"Choose a size and add your Google Meet widget." = "크기를 선택하고 구글 미트 위젯을 추가하세요.";
+"Tip: Right-click a desktop widget to remove it." = "팁: 데스크탑 위젯을 마우스 오른쪽 버튼으로 클릭하여 제거할 수 있습니다.";
+"Removed %@ widget from desktop." = "데스크탑에서 %@ 위젯을 제거했습니다.";
+"Added %@ widget from desktop." = "데스크탑에서 %@ 위젯을 추가했습니다.";
+"Widgets are Premium only. Upgrade to add widgets." = "위젯은 프리미엄 전용입니다. 업그레이드하여 위젯을 추가하세요.";
+"Remove Widget" = "위젯 제거";
+"Small" = "작게";
+"Medium" = "중간";
+"Quick actions" = "빠른 작업";
+"Open Meet" = "미트 열기";
+"Upcoming meetings" = "예정된 회의";
+"Sign in to see upcoming meetings" = "로그인하여 예정된 회의 보기";
+"Sign in with Google" = "구글로 로그인";
+"Google Meet" = "구글 미트";
+"Open and join quickly" = "빠르게 열고 참가하기";
+"Refresh" = "새로고침";
+
+/* MARK: - 사이드바 및 탐색 */
+"Planning" = "계획";
+"Additional" = "추가";
+"Get Premium" = "프리미엄 받기";
+"Manage Subscription" = "구독 관리";
+"App for Google Meet" = "구글 미트 앱";
+
+/* MARK: - Join meetings */
+"New Instant Meet" = "새로운 즉시 미트";
+"Start instant Meet in more section with\nGoogle Meet meet." = "더보기 섹션에서\n구글 미트로 즉시 미트를 시작하세요.";
+"Join with Link" = "링크로 참가";
+"Code or meet.google.com/…" = "코드 또는 meet.google.com/…";
+"Join with ID" = "ID로 참가";
+"Join with URL" = "URL로 참가";
+"Meeting URL" = "회의 URL";
+"Enter meeting URL..." = "회의 URL 입력...";
+"Quick Join Meeting" = "빠른 회의 참가";
+"Invalid Meet link" = "잘못된 미트 링크";
+"Enter a valid Google Meet link or meeting code (for example nkd-grps-duv, meet.google.com/nkd-grps-duv, or https://meet.google.com/nkd-grps-duv)." = "유효한 구글 미트 링크 또는 회의 코드를 입력하세요 (예: nkd-grps-duv, meet.google.com/nkd-grps-duv, 또는 https://meet.google.com/nkd-grps-duv).";
+"Instant Meeting" = "즉시 회의";
+"Connect Google to start Instant Meeting" = "즉시 회의를 시작하려면 구글에 연결하세요";
+"To auto-stop recording when the meeting ends, connect your Google account first." = "회의 종료 시 녹화를 자동으로 중지하려면 먼저 구글 계정을 연결하세요.";
+"Could not create Instant Meeting" = "즉시 회의를 만들 수 없음";
+"Free trial used. Upgrade to continue." = "무료 평가판 사용됨. 계속하려면 업그레이드하세요.";
+
+/* MARK: - Browse web */
+"Browse the web" = "웹 브라우징";
+"Enter a web address (for example meet.google.com)." = "웹 주소를 입력하세요 (예: meet.google.com).";
+"Invalid address" = "잘못된 주소";
+"Enter a valid http or https URL." = "유효한 http 또는 https URL을 입력하세요.";
+"Browse" = "브라우징";
+"Quick links" = "빠른 링크";
+"Zoom help" = "Zoom 도움말";
+"https://example.com or example.com" = "https://example.com 또는 example.com";
+"Enter a valid web address, for example https://example.com" = "유효한 웹 주소를 입력하세요, 예: https://example.com";
+"Address not allowed" = "허용되지 않는 주소";
+"This URL is not permitted with the current in-app browser policy (whitelist)." = "현재 앱 내 브라우저 정책(허용 목록)에서 이 URL이 허용되지 않습니다.";
+"Unable to load page" = "페이지를 로드할 수 없음";
+"Could not load this page in the in-app browser.\n\n%@" = "앱 내 브라우저에서 이 페이지를 로드할 수 없습니다.\n\n%@";
+"Page stopped loading" = "페이지 로딩이 중지됨";
+"Unable to open browser" = "브라우저를 열 수 없음";
+"Unable to Open Safari" = "Safari를 열 수 없음";
+
+/* MARK: - 일정 및 달력 */
+"All" = "전체";
+"Today" = "오늘";
+"This week" = "이번 주";
+"This month" = "이번 달";
+"Previous week" = "이전 주";
+"Previous month" = "이전 달";
+"Custom range" = "사용자 지정 범위";
+"No meetings match the selected filters." = "선택한 필터와 일치하는 회의가 없습니다.";
+"Adjust the date range and tap Apply." = "날짜 범위를 조정하고 적용을 탭하세요.";
+"Premium required. Get Premium now to unlock Calendar." = "프리미엄 필요합니다. 지금 프리미엄을 받아 달력을 잠금 해제하세요.";
+"Premium required. Click to open paywall." = "프리미엄 필요합니다. 클릭하여 결제 페이지를 여세요.";
+"Get Premium to see events" = "이벤트를 보려면 프리미엄을 받으세요";
+"Connect Google" = "구글 연결";
+"Sign in with Google first to schedule a meeting from Calendar." = "달력에서 회의 일정을 잡으려면 먼저 구글로 로그인하세요.";
+"Select date" = "날짜 선택";
+"Choose a date to schedule your meeting." = "회의 일정을 잡을 날짜를 선택하세요.";
+"Google schedule" = "구글 일정";
+"To show scheduled meetings, connect your Google account. You’ll need a Google OAuth client ID (Desktop) and a redirect URI matching the app’s callback scheme." = "예정된 회의를 표시하려면 구글 계정을 연결하세요. 구글 OAuth 클라이언트 ID(데스크탑)와 앱의 콜백 체계와 일치하는 리디렉션 URI가 필요합니다.";
+"Actions" = "작업";
+"Schedule meeting" = "회의 예약";
+"Team sync" = "팀 동기화";
+"Duration (min)" = "시간(분)";
+"Refresh saved meetings" = "저장된 회의 새로고침";
+
+/* MARK: - 설정 */
+"Manage appearance, account, and app options." = "외모, 계정 및 앱 옵션을 관리하세요.";
+"Appearance" = "외모";
+"Account" = "계정";
+"App" = "앱";
+"Notifications" = "알림";
+"Help & Legal" = "도움말 및 법적 정보";
+"Dark Mode" = "다크 모드";
+"Language" = "언어";
+"System Language" = "시스템 언어";
+"Rate Us" = "평가하기";
+"Share App" = "앱 공유";
+"Upgrade" = "업그레이드";
+"Privacy Policy" = "개인정보처리방침";
+"Support" = "지원";
+"Terms of Services" = "서비스 약관";
+"AI Language 1" = "인공지능 언어 1";
+"AI Language 2" = "인공지능 언어 2";
+"Google account connected" = "구글 계정 연결됨";
+"Google account not connected" = "구글 계정 연결되지 않음";
+"Signed in" = "로그인됨";
+"Sign in to sync your meetings and calendar." = "로그인하여 회의 및 달력을 동기화하세요.";
+"Log out" = "로그아웃";
+"Check out %@ for managing and joining meetings." = "%@(을)를 통해 회의를 관리하고 참가해보세요.";
+"Meetings App" = "회의 앱";
+
+/* MARK: - 녹화 동의 */
+"Record this meeting locally?" = "이 회의를 로컬에 녹화하시겠습니까?";
+"With your consent, the app will record meeting audio on this Mac and show it in AI Companion after the meeting." = "귀하의 동의 하에 앱은 이 Mac에서 회의 오디오를 녹화하고 회의 종료 후 인공지능 어시스턴트에 표시합니다.";
+"Allow and Continue" = "허용 및 계속";
+"Continue Without Recording" = "녹화 없이 계속";
+"Transcription Languages" = "전사 언어";
+"Preferred Language 1" = "선호 언어 1";
+"Preferred Language 2" = "선호 언어 2";
+"Microphone permission denied" = "마이크 권한 거부됨";
+"Microphone permission required" = "마이크 권한 필요";
+"Enable microphone access in System Settings to record meetings locally." = "로컬에 회의를 녹화하려면 시스템 설정에서 마이크 접근을 활성화하세요.";
+"Could not start recording" = "녹화를 시작할 수 없음";
+"Recording will start when the meeting starts" = "회의 시작 시 녹화가 시작됩니다";
+"Meeting recording started (meeting + microphone)" = "회의 녹화 시작됨 (회의 + 마이크)";
+"System audio unavailable. Recording microphone only." = "시스템 오디오를 사용할 수 없음. 마이크만 녹화합니다.";
+"Meeting recording started (microphone only)" = "회의 녹화 시작됨 (마이크만)";
+"Meeting recording saved" = "회의 녹화 저장됨";
+
+/* MARK: - 인공지능 어시스턴트 */
+"Get notes from your previous meetings" = "이전 회의에서 메모 가져오기";
+"Connect your Google account to see your AI Companion meeting history." = "구글 계정을 연결하여 인공지능 어시스턴트 회의 기록을 확인하세요.";
+"No previous meetings yet for %@. End a meeting to save it here and generate notes." = "%@(으)에 대한 이전 회의가 아직 없습니다. 회의를 종료하여 여기에 저장하고 메모를 생성하세요.";
+"this account" = "이 계정";
+"Previous meetings" = "이전 회의";
+"Recording in progress: %@" = "녹화 중: %@";
+"Started: %@" = "시작됨: %@";
+"Stop Recording" = "녹화 중지";
+"Date: %@" = "날짜: %@";
+"Saved time: %@" = "저장 시간: %@";
+"Get Notes" = "메모 가져오기";
+"Premium required. Click to unlock AI Companion notes." = "프리미엄 필요합니다. 클릭하여 인공지능 어시스턴트 메모 잠금 해제.";
+"Play Audio" = "오디오 재생";
+"Pause Audio" = "오디오 일시정지";
+"Stopped" = "중지됨";
+"Speaking..." = "말하는 중...";
+"Paused" = "일시정지됨";
+"Playing..." = "재생 중...";
+"Not playing" = "재생 중 아님";
+"Checking audio..." = "오디오 확인 중...";
+"Audio file missing" = "오디오 파일 누락";
+"Could not play recording" = "녹화를 재생할 수 없음";
+"Failed: %@" = "실패: %@";
+"Failed to play audio" = "오디오 재생 실패";
+"decode error" = "디코딩 오류";
+"Loading..." = "로딩 중...";
+"Buffering..." = "버퍼링 중...";
+"Finished" = "완료됨";
+"Transcript not requested" = "전사 요청되지 않음";
+"Transcript processing..." = "전사 처리 중...";
+"Transcript ready" = "전사 준비됨";
+"Transcript unavailable (tap to retry)" = "전사를 사용할 수 없음 (다시 시도하려면 탭)";
+"Notes not requested" = "메모 요청되지 않음";
+"Preparing notes, please wait..." = "메모 준비 중, 잠시만 기다려주세요...";
+"Notes ready" = "메모 준비됨";
+"Notes unavailable (tap to retry)" = "메모를 사용할 수 없음 (다시 시도하려면 탭)";
+"Transcript unavailable" = "전사를 사용할 수 없음";
+"Notes unavailable" = "메모를 사용할 수 없음";
+"Could not find recording details for this meeting." = "이 회의에 대한 녹화 세부정보를 찾을 수 없습니다.";
+"Transcript - %@" = "전사 - %@";
+"Notes - %@" = "메모 - %@";
+"Meeting Notes" = "회의 메모";
+"Transcript processing..." = "전사 처리 중...";
+
+/* MARK: - 결제 및 StoreKit */
+"Meetings Pro" = "회의 전문판";
+"PREMIUM EXPERIENCE" = "프리미엄 경험";
+"Elevate your meetings workflow" = "회의 작업 흐름을 한 단계 업그레이드하세요";
+"Unlock automation, premium meeting tools, and priority support for every session." = "자동화, 프리미엄 회의 도구 및 모든 세션에 대한 우선 지원을 잠금 해제하세요.";
+"Manage meetings" = "회의 관리";
+"Smart scheduling" = "스마트 일정";
+"Faster workflow" = "더 빠른 작업 흐름";
+"Reminder notifications" = "알림 알림";
+"Monthly" = "월간";
+"Bi Yearly" = "6개월";
+"Yearly" = "연간";
+"Most Popular" = "가장 인기 있음";
+"%@ • Most Popular" = "%@ • 가장 인기 있음";
+"3 days free trial" = "3일 무료 평가판";
+"Cancel anytime" = "언제든지 취소 가능";
+"No lock-in" = "약정 없음";
+"Instant access" = "즉시 접근";
+"Unlock all tools" = "모든 도구 잠금 해제";
+"Secure billing" = "안전한 결제";
+"Handled by Apple" = "애플에서 처리";
+"Secured by Apple. Cancel anytime." = "애플의 보안. 언제든지 취소 가능.";
+"Restore Purchase" = "구매 복원";
+"Continue with free plan" = "무료 플랜으로 계속";
+"Already Premium" = "이미 프리미엄";
+"You are already premium. Do you want to continue with this purchase?" = "이미 프리미엄 회원입니다. 이 구매를 계속하시겠습니까?";
+"Current plan: %@. Choose a different package to switch." = "현재 플랜: %@. 전환하려면 다른 패키지를 선택하세요.";
+"Premium is active on this Apple ID." = "이 애플 ID에 프리미엄이 활성화되어 있습니다.";
+"Free for %@, then %@" = "%@ 무료, 이후 %@";
+"Billed via App Store" = "App Store를 통해 청구";
+"%@  •  %@" = "%@  •  %@";
+"Save 0%" = "0% 절약";
+"Save %@%%" = "%@%% 절약";
+"month" = "월";
+"year" = "년";
+"%@ free trial" = "%@ 무료 평가판";
+"Processing..." = "처리 중...";
+"Premium Active" = "프리미엄 활성화됨";
+"Continue with 3 day trail" = "3일 평가판 계속";
+"Please Wait" = "잠시만 기다려주세요";
+"A purchase is already being processed." = "이미 구매가 처리 중입니다.";
+"This Apple ID already has premium access." = "이 애플 ID에는 이미 프리미엄 접근 권한이 있습니다.";
+"Purchase Complete" = "구매 완료";
+"Premium has been unlocked successfully." = "프리미엄이 성공적으로 잠금 해제되었습니다.";
+"Purchase Pending" = "구매 보류 중";
+"Your purchase is pending approval. You can continue once it completes." = "구매 승인이 보류 중입니다. 완료되면 계속할 수 있습니다.";
+"Product Not Available" = "제품을 사용할 수 없음";
+"Unable to load this product. Check your StoreKit configuration and product IDs." = "이 제품을 로드할 수 없습니다. StoreKit 구성 및 제품 ID를 확인하세요.";
+"Already Purchased" = "이미 구매함";
+"This plan is already active on your Apple ID." = "이 플랜은 이미 애플 ID에 활성화되어 있습니다.";
+"Purchase Failed" = "구매 실패";
+"Restore Purchases" = "구매 복원";
+"Purchases restored successfully." = "구매가 성공적으로 복원되었습니다.";
+"No previous premium purchase was found for this Apple ID." = "이 애플 ID에 대한 이전 프리미엄 구매 내역이 없습니다.";
+"Restore failed: %@" = "복원 실패: %@";
+"Unable to Open Subscriptions" = "구독을 열 수 없음";
+"The subscriptions URL is invalid." = "구독 URL이 유효하지 않습니다.";
+"%@ tapped." = "%@(이)가 탭됨.";
+
+/* MARK: - Auth */
+"Google Sign-In" = "구글 로그인";
+
+/* MARK: - Speech / transcript errors */
+"Speech recognition permission denied. Enable it in System Settings and try again." = "음성 인식 권한이 거부되었습니다. 시스템 설정에서 활성화하고 다시 시도하세요.";
+"Speech recognition is restricted on this Mac." = "이 Mac에서는 음성 인식이 제한되어 있습니다.";
+"Speech recognition authorization is unavailable." = "음성 인식 권한을 사용할 수 없습니다.";
+"Speech recognizer is unavailable for the current locale." = "현지 언어 환경에서는 음성 인식기를 사용할 수 없습니다.";
+"Speech recognizer is unavailable for %@." = "%@(으)로는 음성 인식기를 사용할 수 없습니다.";
+"No audio was available to transcribe." = "전사할 수 있는 오디오가 없습니다.";
+
+/* MARK: - StoreKit 거래 오류 */
+"Unable to load products: %@" = "제품을 로드할 수 없음: %@";
+"Product ID not found in StoreKit response. Requested: %@. Loaded IDs: %@" = "StoreKit 응답에서 제품 ID를 찾을 수 없음. 요청됨: %@. 로드된 ID: %@";
+"Purchase verification failed." = "구매 확인 실패.";
+"Unknown purchase state." = "알 수 없는 구매 상태.";
+"none" = "없음";
+
+/* MARK: - Paywall pricing copy */
+"%@ one-time purchase" = "%@ 일회성 구매";
+"%@/month" = "%@/월";
+"%@/6 months" = "%@/6개월";
+"%@/year (3 days free trial)" = "%@/년 (3일 무료 평가판)";
+"day" = "일";
+"week" = "주";
+"period" = "기간";
+"1 %@" = "1 %@";
+"%d %@s" = "%d %@";
+
+/* MARK: - 토스트 및 빠른 피드백 */
+"Meeting added successfully." = "회의가 성공적으로 추가되었습니다.";
+"An issue occurred. Please try again." = "문제가 발생했습니다. 다시 시도하세요.";
+"Failed to load transcript." = "전사 로드 실패.";
+"Failed to generate notes." = "메모 생성 실패.";
+
+/* MARK: - 브라우저 알림 */
+"Try Again" = "다시 시도";
+"The in-app browser closed this page unexpectedly. You can try loading it again in this same window." = "앱 내 브라우저가 예기치 않게 이 페이지를 닫았습니다. 동일한 창에서 다시 로드해 볼 수 있습니다.";
+
+/* MARK: - 일정 및 달력 오류 */
+"Couldn't load schedule." = "일정을 로드할 수 없습니다.";
+"Couldn't refresh schedule." = "일정을 새로고침할 수 없습니다.";
+"Couldn't connect Google account." = "구글 계정을 연결할 수 없습니다.";
+"Couldn't logout Google account." = "구글 계정을 로그아웃할 수 없습니다.";
+"Couldn't load schedule" = "일정을 로드할 수 없음";
+"Couldn't determine Meet meeting code from URL." = "URL에서 미트 회의 코드를 확인할 수 없습니다.";
+"Refreshing…" = "새로고침 중…";
+"Connect Google to see meetings" = "회의를 보려면 구글 연결";
+"Connect to load schedule" = "일정을 로드하려면 연결";
+"Loading…" = "로딩 중…";
+"Loading schedule…" = "일정 로딩 중…";
+"Start date must be on or before end date." = "시작 날짜는 종료 날짜보다 빠르거나 같아야 합니다.";
+"Invalid custom date range" = "잘못된 사용자 지정 날짜 범위";
+"No meetings" = "회의 없음";
+"No meetings for selected filters" = "선택한 필터에 대한 회의 없음";
+"No meetings on %@" = "%@에 회의 없음";
+"1 meeting on %@" = "%@에 회의 1개";
+"%d meetings on %@" = "%@에 회의 %d개";
+"All day" = "하루 종일";
+"Duration: all day" = "시간: 하루 종일";
+"Duration: %dh %dm" = "시간: %dh %dm";
+"Duration: %dh" = "시간: %dh";
+"Duration: %dm" = "시간: %dm";
+"%@ - %@" = "%@ - %@";
+"Scheduled Meeting" = "예정된 회의";
+
+/* MARK: - Create meeting popover */
+"Please enter a title." = "제목을 입력하세요.";
+"Duration must be a positive number of minutes." = "시간은 양수 분 단위여야 합니다.";
+"Invalid start time." = "잘못된 시작 시간.";
+
+/* MARK: - 알림 및 알림 */
+"Reminders" = "미리 알림";
+"1 Day Before" = "1일 전";
+"12 Hours Before" = "12시간 전";
+"1 Hour Before" = "1시간 전";
+"Starts in 1 day" = "1일 후 시작";
+"Starts in 12 hours" = "12시간 후 시작";
+"Starts in 1 hour" = "1시간 후 시작";
+
+/* MARK: - 구글 OAuth 오류 */
+"Missing Google OAuth Client ID." = "구글 OAuth 클라이언트 ID가 없습니다.";
+"Missing Google OAuth Client Secret." = "구글 OAuth 클라이언트 시크릿이 없습니다.";
+"Invalid OAuth callback URL." = "잘못된 OAuth 콜백 URL입니다.";
+"Google did not return an authorization code." = "구글이 인증 코드를 반환하지 않았습니다.";
+"Token exchange failed: %@" = "토큰 교환 실패: %@";
+"Could not open browser for Google sign-in." = "구글 로그인을 위한 브라우저를 열 수 없습니다.";
+"Google sign-in timed out." = "구글 로그인 시간이 초과되었습니다.";
+"No stored Google tokens found." = "저장된 구글 토큰이 없습니다.";
+
+/* MARK: - 인공지능 어시스턴트 / transcript errors */
+"Recording not found." = "녹화를 찾을 수 없습니다.";
+"Local meeting audio is missing." = "로컬 회의 오디오가 없습니다.";
+"Generated transcript was empty." = "생성된 전사가 비어 있습니다.";
+"(No transcript entries found.)" = "(전사 항목을 찾을 수 없습니다.)";
+"No conference record found for this meeting." = "이 회의에 대한 회의 기록을 찾을 수 없습니다.";
+"No transcript found for this meeting." = "이 회의에 대한 전사를 찾을 수 없습니다.";
+"Unable to create audio composition tracks." = "오디오 합성 트랙을 만들 수 없습니다.";
+"Unable to create audio export session." = "오디오보내기 세션을 만들 수 없습니다.";
+"Audio mix export failed." = "오디오 믹스보내기 실패.";
+"No display available for system audio capture." = "시스템 오디오 캡처에 사용할 수 있는 디스플레이가 없습니다.";
+"Cannot add audio writer input." = "오디오 작성기 입력을 추가할 수 없습니다.";
+
+/* MARK: - 구글 API 오류 */
+"Google Meet returned an invalid response." = "구글 미트가 잘못된 응답을 반환했습니다.";
+"Google Meet API error (%d): %@" = "구글 미트 API 오류 (%d): %@";
+"Failed to parse Google Meet response: %@" = "구글 미트 응답 구문 분석 실패: %@";
+"Google Calendar returned an invalid response." = "구글 달력이 잘못된 응답을 반환했습니다.";
+"Google Calendar API error (%d): %@" = "구글 달력 API 오류 (%d): %@";
+"Failed to parse Google Calendar events: %@" = "구글 달력 이벤트 구문 분석 실패: %@";
+
+/* MARK: - OpenAI 오류 */
+"OpenAI API key is missing. Set OPENAI_API_KEY in the environment or app key vault." = "OpenAI API 키가 없습니다. 환경 또는 앱 키 보관소에 OPENAI_API_KEY를 설정하세요.";
+"Notes generation returned an invalid response." = "메모 생성이 잘못된 응답을 반환했습니다.";
+"Notes generation failed (%d): %@" = "메모 생성 실패 (%d): %@";
+"Notes generation returned empty text." = "메모 생성이 빈 텍스트를 반환했습니다.";
+"OpenAI transcription returned an invalid response." = "OpenAI 전사가 잘못된 응답을 반환했습니다.";
+"OpenAI transcription failed (%d): %@" = "OpenAI 전사 실패 (%d): %@";
+"OpenAI transcription returned no text." = "OpenAI 전사가 텍스트를 반환하지 않았습니다.";
+
+/* MARK: - Browse & in-app browser */
+"Open sites in the in-app browser (back, forward, reload, address bar). OAuth and “Continue in browser” flows stay inside the app." = "앱 내 브라우저에서 사이트 열기 (뒤로, 앞으로, 새로고침, 주소 표시줄). OAuth 및 '브라우저에서 계속' 흐름은 앱 내에 유지됩니다.";
+"Open in app browser" = "앱 브라우저에서 열기";
+"Meet help" = "미트 도움말";
+"Go" = "이동";
+"Back" = "뒤로";
+"Forward" = "앞으로";
+"Reload" = "새로고침";
+
+/* MARK: - 일정 및 달력 레이블 */
+"Google Calendar" = "구글 달력";
+"Untitled meeting" = "제목 없는 회의";
+"Created event missing start/end." = "생성된 이벤트에 시작/종료가 없습니다.";
+"Created event missing Meet/HTML link." = "생성된 이벤트에 미트/HTML 링크가 없습니다.";
+
+/* MARK: - 구글 계정 */
+"Google account" = "구글 계정";
+"%@, Google account" = "%@, 구글 계정";
+"Google User" = "구글 사용자";
+
+/* MARK: - Zoom join (unused section) */
+"Meeting ID" = "회의 ID";
+"Enter meeting ID..." = "회의 ID 입력...";
+"Meeting Passcode" = "회의 암호";
+"Enter meeting passcode..." = "회의 암호 입력...";
+
+/* MARK: - 결제 (대체 혜택) */
+"Virtual backgrounds" = "가상 배경";
+"Tools for productivity" = "생산성 도구";
+"24/7 support" = "연중무휴 지원";
+
+/* MARK: - Transcription speakers */
+"You" = "당신";
+
+/* MARK: - 키체인 오류 */
+"Failed to read OAuth tokens from Keychain." = "키체인에서 OAuth 토큰을 읽지 못했습니다.";
+"Keychain returned an invalid token payload." = "키체인이 잘못된 토큰 페이로드를 반환했습니다.";
+"Failed to update OAuth tokens in Keychain." = "키체인의 OAuth 토큰을 업데이트하지 못했습니다.";
+"Failed to save OAuth tokens to Keychain." = "OAuth 토큰을 키체인에 저장하지 못했습니다.";
+"Failed to delete OAuth tokens from Keychain." = "키체인에서 OAuth 토큰을 삭제하지 못했습니다.";
+"Unable to allocate audio buffer." = "오디오 버퍼를 할당할 수 없습니다.";
+"Invalid revoke response." = "잘못된 취소 응답입니다.";
+"Token revoke failed with status %d." = "토큰 취소 실패, 상태 %d.";
+
+/* MARK: - Error alert diagnostics */
+"Keychain: %d (%@)" = "키체인: %d (%@)";
+"OSStatus: %d" = "OSStatus: %d";
+"Item: service=%@, account=%@" = "항목: 서비스=%@, 계정=%@";

+ 17 - 0
meetings_app/ko.lproj/Main.strings

@@ -0,0 +1,17 @@
+/* Class = "NSMenuItem"; title = "AI Companion for Meet"; ObjectID = "1Xt-HY-uBw"; */
+"1Xt-HY-uBw.title" = "미트 인공지능 어시스턴트";
+
+/* Class = "NSMenu"; title = "AI Companion for Meet"; ObjectID = "uQy-DD-JDr"; */
+"uQy-DD-JDr.title" = "미트 인공지능 어시스턴트";
+
+/* Class = "NSMenuItem"; title = "About AI Companion for Meet"; ObjectID = "5kV-Vb-QxS"; */
+"5kV-Vb-QxS.title" = "미트 인공지능 어시스턴트 정보";
+
+/* Class = "NSMenuItem"; title = "Hide AI Companion for Meet"; ObjectID = "Olw-nP-bQN"; */
+"Olw-nP-bQN.title" = "미트 인공지능 어시스턴트 숨기기";
+
+/* Class = "NSMenuItem"; title = "Quit AI Companion for Meet"; ObjectID = "4sb-4s-VLi"; */
+"4sb-4s-VLi.title" = "미트 인공지능 어시스턴트 종료";
+
+/* Class = "NSMenuItem"; title = "AI Companion for Meet Help"; ObjectID = "FKE-Sm-Kum"; */
+"FKE-Sm-Kum.title" = "미트 인공지능 어시스턴트 도움말";