From bb949e4f44c4ed1e19c7bddc5779515b419a7022 Mon Sep 17 00:00:00 2001 From: Samuel Newman Date: Mon, 11 Aug 2025 18:37:39 +0300 Subject: Fix translations on Android using PROCESS_TEXT intent (#8486) * use intents to translate text on android * clean up config plugins * restore day night plugin just to be safe * leave a comment for why we can't open translate directly * add todo * fix lockfile lint --- src/lib/hooks/useTranslate.ts | 54 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/lib/hooks/useTranslate.ts (limited to 'src/lib/hooks') diff --git a/src/lib/hooks/useTranslate.ts b/src/lib/hooks/useTranslate.ts new file mode 100644 index 000000000..7824a682c --- /dev/null +++ b/src/lib/hooks/useTranslate.ts @@ -0,0 +1,54 @@ +import {useCallback} from 'react' +import * as IntentLauncher from 'expo-intent-launcher' + +import {getTranslatorLink} from '#/locale/helpers' +import {isAndroid} from '#/platform/detection' +import {useOpenLink} from './useOpenLink' + +export function useTranslate() { + const openLink = useOpenLink() + + return useCallback( + async (text: string, language: string) => { + const translateUrl = getTranslatorLink(text, language) + if (isAndroid) { + try { + // use getApplicationIconAsync to determine if the translate app is installed + if ( + !(await IntentLauncher.getApplicationIconAsync( + 'com.google.android.apps.translate', + )) + ) { + throw new Error('Translate app not installed') + } + + // TODO: this should only be called one at a time, use something like + // RQ's `scope` - otherwise can trigger the browser to open unexpectedly when the call throws -sfn + await IntentLauncher.startActivityAsync( + 'android.intent.action.PROCESS_TEXT', + { + type: 'text/plain', + extra: { + 'android.intent.extra.PROCESS_TEXT': text, + 'android.intent.extra.PROCESS_TEXT_READONLY': true, + }, + // note: to skip the intermediate app select, we need to specify a + // `className`. however, this isn't safe to hardcode, we'd need to query the + // package manager for the correct activity. this requires native code, so + // skip for now -sfn + // packageName: 'com.google.android.apps.translate', + // className: 'com.google.android.apps.translate.TranslateActivity', + }, + ) + } catch (err) { + if (__DEV__) console.error(err) + // most likely means they don't have the translate app + await openLink(translateUrl) + } + } else { + await openLink(translateUrl) + } + }, + [openLink], + ) +} -- cgit 1.4.1