import { ParseHTML } from '@components/Parse' import CustomText from '@components/Text' import detectLanguage from '@helpers/detectLanguage' import getLanguage from '@helpers/getLanguage' import { useTranslateQuery } from '@utils/queryHooks/translate' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import * as Localization from 'expo-localization' import React, { useContext, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { Platform, Pressable } from 'react-native' import { Circle } from 'react-native-animated-spinkit' import StatusContext from './Context' const TimelineTranslate = () => { const { status, highlighted, copiableContent, detectedLanguage } = useContext(StatusContext) if (!status || !highlighted) return null const { t } = useTranslation('componentTimeline') const { colors } = useTheme() const backupTextProcessing = (): string[] => { const text = status.spoiler_text ? [status.spoiler_text, status.content] : [status.content] for (const i in text) { for (const emoji of status.emojis) { text[i] = text[i].replaceAll(`:${emoji.shortcode}:`, ' ') } text[i] = text[i] .replace(/(<([^>]+)>)/gi, ' ') .replace(/@.*? /gi, ' ') .replace(/#.*? /gi, ' ') .replace(/http(s):\/\/.*? /gi, ' ') } return text } const text = copiableContent?.current.content ? [copiableContent?.current.content] : backupTextProcessing() const [detected, setDetected] = useState<{ language: string confidence: number }>({ language: status.language || '', confidence: 0 }) useEffect(() => { const detect = async () => { const result = await detectLanguage(text.join('\n\n')) if (result) { setDetected(result) if (detectedLanguage) { detectedLanguage.current = result.language } } } detect() }, []) const settingsLanguage = getLanguage() const targetLanguage = settingsLanguage?.startsWith('en') ? Localization.locale || settingsLanguage || 'en' : settingsLanguage || Localization.locale || 'en' const [enabled, setEnabled] = useState(false) const { refetch, data, isFetching, isSuccess, isError } = useTranslateQuery({ source: detected.language, target: targetLanguage, text, options: { enabled } }) const devView = () => { return __DEV__ ? ( {` Source: ${ detected?.language }; Confidence: ${ detected?.confidence.toString().slice(0, 5) || 'null' }; Target: ${targetLanguage}`} ) : null } if (!detectedLanguage) { return devView() } if ( Platform.OS === 'ios' && Localization.locale.slice(0, 2).includes(detected.language.slice(0, 2)) ) { return devView() } if ( Platform.OS === 'android' && settingsLanguage?.slice(0, 2).includes(detected.language.slice(0, 2)) ) { return devView() } return ( <> { if (enabled) { if (!isSuccess) { refetch() } } else { setEnabled(true) } }} > {isError ? t('shared.translate.failed') : isSuccess ? typeof data?.error === 'string' ? t(`shared.translate.${data.error}`) : t('shared.translate.succeed', { provider: data?.provider, source: data?.sourceLanguage }) : t('shared.translate.default')} {isFetching ? ( ) : null} {devView()} {data && data.error === undefined ? data.text.map((d, i) => ) : null} ) } export default TimelineTranslate