diff --git a/Resources/Info.plist b/Resources/Info.plist index 3f0cc6b569..6f92332f82 100644 --- a/Resources/Info.plist +++ b/Resources/Info.plist @@ -69,6 +69,8 @@ NSMicrophoneUsageDescription A program running within cmux would like to use your microphone. + NSSpeechRecognitionUsageDescription + A program running within cmux would like to use speech recognition. NSCameraUsageDescription A program running within cmux would like to use your camera. NSBluetoothAlwaysUsageDescription diff --git a/Resources/InfoPlist.xcstrings b/Resources/InfoPlist.xcstrings index 9e50f7d4b9..937eb953db 100644 --- a/Resources/InfoPlist.xcstrings +++ b/Resources/InfoPlist.xcstrings @@ -149,6 +149,119 @@ } } }, + "NSSpeechRecognitionUsageDescription": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "A program running within cmux would like to use speech recognition." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "cmux 内で実行中のプログラムが音声認識の使用を求めています。" + } + }, + "zh-Hans": { + "stringUnit": { + "state": "translated", + "value": "在 cmux 中运行的程序想要使用语音识别。" + } + }, + "zh-Hant": { + "stringUnit": { + "state": "translated", + "value": "在 cmux 中執行的程式想要使用語音辨識。" + } + }, + "ko": { + "stringUnit": { + "state": "translated", + "value": "cmux 내에서 실행 중인 프로그램이 음성 인식을 사용하려고 합니다." + } + }, + "de": { + "stringUnit": { + "state": "translated", + "value": "Ein in cmux ausgeführtes Programm möchte Spracherkennung verwenden." + } + }, + "es": { + "stringUnit": { + "state": "translated", + "value": "Un programa en ejecución dentro de cmux desea usar el reconocimiento de voz." + } + }, + "fr": { + "stringUnit": { + "state": "translated", + "value": "Un programme s'exécutant dans cmux souhaite utiliser la reconnaissance vocale." + } + }, + "it": { + "stringUnit": { + "state": "translated", + "value": "Un programma in esecuzione in cmux desidera utilizzare il riconoscimento vocale." + } + }, + "da": { + "stringUnit": { + "state": "translated", + "value": "Et program, der kører i cmux, vil gerne bruge talegenkendelse." + } + }, + "pl": { + "stringUnit": { + "state": "translated", + "value": "Program działający w cmux chciałby użyć rozpoznawania mowy." + } + }, + "ru": { + "stringUnit": { + "state": "translated", + "value": "Программа, запущенная в cmux, хотела бы использовать распознавание речи." + } + }, + "bs": { + "stringUnit": { + "state": "translated", + "value": "Program koji se izvršava unutar cmux želi koristiti prepoznavanje govora." + } + }, + "ar": { + "stringUnit": { + "state": "translated", + "value": "يرغب برنامج يعمل داخل cmux في استخدام التعرف على الكلام." + } + }, + "nb": { + "stringUnit": { + "state": "translated", + "value": "Et program som kjører i cmux ønsker å bruke talegjenkjenning." + } + }, + "pt-BR": { + "stringUnit": { + "state": "translated", + "value": "Um programa em execução no cmux gostaria de usar reconhecimento de fala." + } + }, + "th": { + "stringUnit": { + "state": "translated", + "value": "โปรแกรมที่ทำงานภายใน cmux ต้องการใช้การรู้จำเสียงพูด" + } + }, + "tr": { + "stringUnit": { + "state": "translated", + "value": "cmux içinde çalışan bir program konuşma tanımayı kullanmak istiyor." + } + } + } + }, "New $(PRODUCT_NAME) Workspace Here": { "extractionState": "manual", "localizations": { diff --git a/cmux.xcodeproj/project.pbxproj b/cmux.xcodeproj/project.pbxproj index 29e65084c7..c0e19b6162 100644 --- a/cmux.xcodeproj/project.pbxproj +++ b/cmux.xcodeproj/project.pbxproj @@ -341,6 +341,7 @@ F4100000A1B2C3D4E5F60718 /* PortScannerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4100001A1B2C3D4E5F60718 /* PortScannerTests.swift */; }; A5001270 /* PostHog in Frameworks */ = {isa = PBXBuildFile; productRef = A5001271 /* PostHog */; }; A5001521 /* PostHogAnalytics.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5001520 /* PostHogAnalytics.swift */; }; + C0DEF5000000000000000001 /* PrivacyUsageDescriptionBundleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C0DEF5000000000000000002 /* PrivacyUsageDescriptionBundleTests.swift */; }; C47110010000000000000001 /* ProcessPipeReadCrashRegressionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C47110010000000000000002 /* ProcessPipeReadCrashRegressionTests.swift */; }; C47110020000000000000001 /* ProcessPipeReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C47110020000000000000002 /* ProcessPipeReader.swift */; }; C47110020000000000000003 /* ProcessPipeReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = C47110020000000000000002 /* ProcessPipeReader.swift */; }; @@ -977,6 +978,7 @@ A5001541 /* PortScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortScanner.swift; sourceTree = ""; }; F4100001A1B2C3D4E5F60718 /* PortScannerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PortScannerTests.swift; sourceTree = ""; }; A5001520 /* PostHogAnalytics.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostHogAnalytics.swift; sourceTree = ""; }; + C0DEF5000000000000000002 /* PrivacyUsageDescriptionBundleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacyUsageDescriptionBundleTests.swift; sourceTree = ""; }; C47110010000000000000002 /* ProcessPipeReadCrashRegressionTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessPipeReadCrashRegressionTests.swift; sourceTree = ""; }; C47110020000000000000002 /* ProcessPipeReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProcessPipeReader.swift; sourceTree = ""; }; A5C0DE0000000000000000B9 /* ProjectBuildSettingsTabView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Panels/ProjectBuildSettingsTabView.swift; sourceTree = ""; }; @@ -1815,6 +1817,7 @@ D7AB00000000000000000012 /* WorkspaceAdjacentPaneMoveTests.swift */, D7AB3605C10DEF0000000002 /* WorkspaceCloseTabsContextMenuTests.swift */, D0B10009A1B2C3D4E5F60001 /* PortalTabDragRoutingTests.swift */, + C0DEF5000000000000000002 /* PrivacyUsageDescriptionBundleTests.swift */, 71F8ED91A4B55D34BE6A0668 /* WorkspaceUnitTests.swift */, 71F8ED92A4B55D34BE6A0668 /* WorkspaceSplitStartupCommandTests.swift */, EF7347934AB1BD387686EE43 /* WorkspaceActionDispatcherTests.swift */, @@ -2699,6 +2702,7 @@ B3575000000000000000000A /* PiVaultAgentPersistenceTests.swift in Sources */, D0B10008A1B2C3D4E5F60001 /* PortalTabDragRoutingTests.swift in Sources */, F4100000A1B2C3D4E5F60718 /* PortScannerTests.swift in Sources */, + C0DEF5000000000000000001 /* PrivacyUsageDescriptionBundleTests.swift in Sources */, C47110010000000000000001 /* ProcessPipeReadCrashRegressionTests.swift in Sources */, F5410004A1B2C3D4E5F60718 /* RestorableAgentHookProviderHermesTests.swift in Sources */, F5410000A1B2C3D4E5F60718 /* RestorableAgentHookProviderResumeTests.swift in Sources */, diff --git a/cmuxTests/PrivacyUsageDescriptionBundleTests.swift b/cmuxTests/PrivacyUsageDescriptionBundleTests.swift new file mode 100644 index 0000000000..3ea72892e3 --- /dev/null +++ b/cmuxTests/PrivacyUsageDescriptionBundleTests.swift @@ -0,0 +1,21 @@ +import Foundation +import Testing + +#if canImport(cmux_DEV) +@testable import cmux_DEV +#elseif canImport(cmux) +@testable import cmux +#endif + +@MainActor +@Suite +struct PrivacyUsageDescriptionBundleTests { + @Test + func appBundleDeclaresSpeechRecognitionUsageDescription() throws { + let usageDescription = try #require(Bundle(for: AppDelegate.self) + .infoDictionary?["NSSpeechRecognitionUsageDescription"] as? String + ) + + #expect(usageDescription == "A program running within cmux would like to use speech recognition.") + } +}