diff --git a/apps/mobile/modules/t3-voice-transcription/android/src/main/java/expo/modules/t3voicetranscription/GoogleVoiceTranscriber.kt b/apps/mobile/modules/t3-voice-transcription/android/src/main/java/expo/modules/t3voicetranscription/GoogleVoiceTranscriber.kt index 95423844c1d2c..99a0b58936cb3 100644 --- a/apps/mobile/modules/t3-voice-transcription/android/src/main/java/expo/modules/t3voicetranscription/GoogleVoiceTranscriber.kt +++ b/apps/mobile/modules/t3-voice-transcription/android/src/main/java/expo/modules/t3voicetranscription/GoogleVoiceTranscriber.kt @@ -22,6 +22,10 @@ internal class VoiceTranscriptionException( cause: Throwable? = null ) : Exception(message, cause) +// ML Kit reports every mode UNAVAILABLE for tags with Unicode extensions, which Android adds +// for regional preferences such as the temperature unit (en-US-u-mu-celsius). +internal fun speechLocale(systemLocale: Locale): Locale = systemLocale.stripExtensions() + private val recognitionModes = listOf( SpeechRecognizerOptions.Mode.MODE_ADVANCED, SpeechRecognizerOptions.Mode.MODE_BASIC diff --git a/apps/mobile/modules/t3-voice-transcription/android/src/main/java/expo/modules/t3voicetranscription/T3VoiceTranscriptionModule.kt b/apps/mobile/modules/t3-voice-transcription/android/src/main/java/expo/modules/t3voicetranscription/T3VoiceTranscriptionModule.kt index b49791bea2b9b..008406b006d18 100644 --- a/apps/mobile/modules/t3-voice-transcription/android/src/main/java/expo/modules/t3voicetranscription/T3VoiceTranscriptionModule.kt +++ b/apps/mobile/modules/t3-voice-transcription/android/src/main/java/expo/modules/t3voicetranscription/T3VoiceTranscriptionModule.kt @@ -32,7 +32,7 @@ class T3VoiceTranscriptionModule : Module() { } else { withContext(Dispatchers.IO) { val context = requireNotNull(appContext.reactContext) - val locale = Resources.getSystem().configuration.locales[0] + val locale = speechLocale(Resources.getSystem().configuration.locales[0]) isGoogleVoiceTranscriptionSupported { MlKitSpeechClient(context, locale, it) } } } @@ -47,7 +47,7 @@ class T3VoiceTranscriptionModule : Module() { ) } val context = requireNotNull(appContext.reactContext) - val locale = Resources.getSystem().configuration.locales[0] + val locale = speechLocale(Resources.getSystem().configuration.locales[0]) val mode = prepareGoogleVoiceTranscription { MlKitSpeechClient(context, locale, it) } mapOf("locale" to locale.toLanguageTag(), "mode" to mode) } diff --git a/apps/mobile/modules/t3-voice-transcription/android/src/test/java/expo/modules/t3voicetranscription/GoogleVoiceTranscriberTest.kt b/apps/mobile/modules/t3-voice-transcription/android/src/test/java/expo/modules/t3voicetranscription/GoogleVoiceTranscriberTest.kt index aaa76dfbf07e2..445411bbb6957 100644 --- a/apps/mobile/modules/t3-voice-transcription/android/src/test/java/expo/modules/t3voicetranscription/GoogleVoiceTranscriberTest.kt +++ b/apps/mobile/modules/t3-voice-transcription/android/src/test/java/expo/modules/t3voicetranscription/GoogleVoiceTranscriberTest.kt @@ -4,6 +4,7 @@ import com.google.mlkit.genai.common.FeatureStatus import com.google.mlkit.genai.common.GenAiException import com.google.mlkit.genai.speechrecognition.SpeechRecognizerOptions import com.google.mlkit.genai.speechrecognition.SpeechRecognizerResponse +import java.util.Locale import kotlinx.coroutines.CompletableDeferred import kotlinx.coroutines.cancelAndJoin import kotlinx.coroutines.flow.flow @@ -14,6 +15,18 @@ import org.junit.Assert.assertTrue import org.junit.Test class GoogleVoiceTranscriberTest { + @Test + fun dropsRegionalPreferenceExtensionsFromTheSpeechLocale() { + for ((system, expected) in listOf( + "en-US-u-mu-celsius" to "en-US", + "en-GB-u-fw-mon-mu-celsius" to "en-GB", + "ar-EG-u-nu-latn" to "ar-EG", + "zh-Hant-TW" to "zh-Hant-TW" + )) { + assertEquals(expected, speechLocale(Locale.forLanguageTag(system)).toLanguageTag()) + } + } + @Test fun preservesUtterancesAndTheirSpacingWithoutDuplicatingHypotheses() = runBlocking { for ((finals, trailing, expected) in listOf(