Rename translation properties for clarity (#10061)
This commit is contained in:
@@ -708,24 +708,83 @@ export type Events = {
|
||||
|
||||
translate: {
|
||||
os: Platform['OS']
|
||||
sourceLanguages: string[]
|
||||
targetLanguage: string
|
||||
/**
|
||||
* The languages the content might be in, such as the user-supplied
|
||||
* language codes on posts. Currently only available on posts.
|
||||
*/
|
||||
possibleSourceLanguages: string[] | undefined
|
||||
/**
|
||||
* This is the user's configured primary language, which is always defined.
|
||||
*/
|
||||
expectedTargetLanguage: string
|
||||
/**
|
||||
* The length of the text being translated. We assume shorter texts are
|
||||
* more likely to have inaccurate translations.
|
||||
*/
|
||||
textLength: number
|
||||
googleTranslate: boolean
|
||||
}
|
||||
'translate:result': {
|
||||
method: 'on-device' | 'fallback-alert'
|
||||
success: boolean
|
||||
os: Platform['OS']
|
||||
sourceSelection: 'automatic' | 'manual'
|
||||
sourceLanguage: string | null
|
||||
targetLanguage: string
|
||||
|
||||
/* Only relevant to posts */
|
||||
postLanguages?: string[]
|
||||
/**
|
||||
* The languages the content might be in, such as the user-supplied
|
||||
* language codes on posts. Currently only available on posts.
|
||||
*/
|
||||
possibleSourceLanguages: string[] | undefined
|
||||
/**
|
||||
* The language we expected the content to be in. This could be based on
|
||||
* user selection or on our confidence in the detected language. This is
|
||||
* nullable because we may not always have an expected source language.
|
||||
*/
|
||||
expectedSourceLanguage: string | null
|
||||
/**
|
||||
* This is the user's configured primary language, which is always defined.
|
||||
*/
|
||||
expectedTargetLanguage: string
|
||||
/**
|
||||
* The language the translation result was actually in. This is nullable
|
||||
* because the translation could have failed, in which case we won't have a
|
||||
* result source language.
|
||||
*/
|
||||
resultSourceLanguage: string | null
|
||||
/**
|
||||
* The language the translation result was translated into. This should be
|
||||
* the same as `expectedTargetLanguage`, but we include it for completeness
|
||||
* and in case there are any edge cases where they differ. This is nullable
|
||||
* because if the translation failed, we won't have a result target
|
||||
* language.
|
||||
*/
|
||||
resultTargetLanguage: string | null
|
||||
/**
|
||||
* The length of the text being translated. We assume shorter texts are
|
||||
* more likely to have inaccurate translations.
|
||||
*/
|
||||
textLength: number
|
||||
}
|
||||
'translate:override': {
|
||||
os: Platform['OS']
|
||||
sourceLanguage: string
|
||||
targetLanguage: string
|
||||
/**
|
||||
* The languages the content might be in, such as the user-supplied
|
||||
* language codes on posts. Currently only available on posts.
|
||||
*/
|
||||
possibleSourceLanguages: string[] | undefined
|
||||
/**
|
||||
* The language the user has indicated the content is actually in, which
|
||||
* may be different from the expected source language if the user is
|
||||
* overriding the auto-detected language. This is the language the user
|
||||
* wants to translate from after overriding.
|
||||
*/
|
||||
expectedSourceLanguage: string
|
||||
/**
|
||||
* This is the user's configured primary language, which is always defined.
|
||||
*/
|
||||
expectedTargetLanguage: string
|
||||
/**
|
||||
* The language the translation result was actually in, which the user now
|
||||
* wishes to override.
|
||||
*/
|
||||
resultSourceLanguage: string
|
||||
}
|
||||
|
||||
'postMenu:openMuteWordsDialog': {
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import {useCallback, useMemo} from 'react'
|
||||
import {Platform, type StyleProp, type TextStyle, View} from 'react-native'
|
||||
import {type AppBskyFeedDefs} from '@atproto/api'
|
||||
import {type AppBskyFeedDefs, AppBskyFeedPost} from '@atproto/api'
|
||||
import {Trans, useLingui} from '@lingui/react/macro'
|
||||
|
||||
import {HITSLOP_30} from '#/lib/constants'
|
||||
import {useGoogleTranslate} from '#/lib/hooks/useGoogleTranslate'
|
||||
import {useTranslate} from '#/lib/translation'
|
||||
import {type TranslationFunction} from '#/lib/translation'
|
||||
import {
|
||||
type TranslationFunction,
|
||||
type TranslationFunctionParams,
|
||||
} from '#/lib/translation'
|
||||
import {
|
||||
codeToLanguageName,
|
||||
getPostLanguageTags,
|
||||
@@ -26,26 +28,39 @@ import * as Select from '#/components/Select'
|
||||
import {Text} from '#/components/Typography'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_WEB} from '#/env'
|
||||
import * as bsky from '#/types/bsky'
|
||||
|
||||
const X_ICON_OFFSET = 16
|
||||
|
||||
export function TranslatedPost({
|
||||
hideTranslateLink = false,
|
||||
post,
|
||||
postText,
|
||||
postTextStyle = a.text_md,
|
||||
}: {
|
||||
hideTranslateLink?: boolean
|
||||
post: AppBskyFeedDefs.PostView
|
||||
postText: string
|
||||
postTextStyle?: StyleProp<TextStyle>
|
||||
}) {
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const {clearTranslation, translate, translationState} = useTranslate({
|
||||
key: post.uri,
|
||||
postLangCodes: getPostLanguageTags(post),
|
||||
})
|
||||
|
||||
const record = useMemo<AppBskyFeedPost.Record | undefined>(() => {
|
||||
return bsky.dangerousIsType<AppBskyFeedPost.Record>(
|
||||
post.record,
|
||||
AppBskyFeedPost.isRecord,
|
||||
)
|
||||
? post.record
|
||||
: undefined
|
||||
}, [post])
|
||||
const initialTranslationParams = useMemo<TranslationFunctionParams>(() => {
|
||||
return {
|
||||
text: record?.text || '',
|
||||
expectedTargetLanguage: langPrefs.primaryLanguage,
|
||||
possibleSourceLanguages: getPostLanguageTags(post),
|
||||
}
|
||||
}, [post, record, langPrefs])
|
||||
const needsTranslation = useMemo(() => {
|
||||
if (hideTranslateLink) return false
|
||||
return !isPostInLanguage(post, [langPrefs.primaryLanguage])
|
||||
@@ -57,11 +72,11 @@ export function TranslatedPost({
|
||||
case 'success':
|
||||
return (
|
||||
<TranslationResult
|
||||
clearTranslation={clearTranslation}
|
||||
translate={translate}
|
||||
postText={postText}
|
||||
clearTranslation={clearTranslation}
|
||||
initialTranslationParams={initialTranslationParams}
|
||||
postTextStyle={postTextStyle}
|
||||
sourceLanguage={
|
||||
resultSourceLanguage={
|
||||
translationState.sourceLanguage ?? null // Fallback primarily for iOS
|
||||
}
|
||||
translatedText={translationState.translatedText}
|
||||
@@ -70,19 +85,18 @@ export function TranslatedPost({
|
||||
case 'error':
|
||||
return (
|
||||
<TranslationError
|
||||
translate={translate}
|
||||
clearTranslation={clearTranslation}
|
||||
message={translationState.message}
|
||||
postText={postText}
|
||||
primaryLanguage={langPrefs.primaryLanguage}
|
||||
initialTranslationParams={initialTranslationParams}
|
||||
/>
|
||||
)
|
||||
default:
|
||||
return (
|
||||
needsTranslation && (
|
||||
<TranslationLink
|
||||
postText={postText}
|
||||
primaryLanguage={langPrefs.primaryLanguage}
|
||||
translate={translate}
|
||||
initialTranslationParams={initialTranslationParams}
|
||||
/>
|
||||
)
|
||||
)
|
||||
@@ -105,31 +119,18 @@ function TranslationLoading() {
|
||||
}
|
||||
|
||||
function TranslationLink({
|
||||
postText,
|
||||
primaryLanguage,
|
||||
translate,
|
||||
initialTranslationParams,
|
||||
}: {
|
||||
postText: string
|
||||
primaryLanguage: string
|
||||
translate: TranslationFunction
|
||||
initialTranslationParams: TranslationFunctionParams
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {t: l} = useLingui()
|
||||
const ax = useAnalytics()
|
||||
|
||||
const handleTranslate = useCallback(() => {
|
||||
void translate({
|
||||
text: postText,
|
||||
targetLangCode: primaryLanguage,
|
||||
})
|
||||
|
||||
ax.metric('translate', {
|
||||
os: Platform.OS,
|
||||
sourceLanguages: [], // todo: get from post maybe?
|
||||
targetLanguage: primaryLanguage,
|
||||
textLength: postText.length,
|
||||
})
|
||||
}, [ax, postText, primaryLanguage, translate])
|
||||
void translate(initialTranslationParams)
|
||||
}, [initialTranslationParams, translate])
|
||||
|
||||
return (
|
||||
<View
|
||||
@@ -161,22 +162,24 @@ function TranslationLink({
|
||||
}
|
||||
|
||||
function TranslationError({
|
||||
translate,
|
||||
clearTranslation,
|
||||
message,
|
||||
postText,
|
||||
primaryLanguage,
|
||||
initialTranslationParams,
|
||||
}: {
|
||||
translate: TranslationFunction
|
||||
clearTranslation: () => void
|
||||
message: string
|
||||
postText: string
|
||||
primaryLanguage: string
|
||||
initialTranslationParams: TranslationFunctionParams
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const {t: l} = useLingui()
|
||||
const translate = useGoogleTranslate()
|
||||
|
||||
const handleFallback = () => {
|
||||
void translate(postText, primaryLanguage)
|
||||
void translate({
|
||||
...initialTranslationParams,
|
||||
forceGoogleTranslate: true,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -247,24 +250,24 @@ function TranslationError({
|
||||
function TranslationResult({
|
||||
clearTranslation,
|
||||
translate,
|
||||
postText,
|
||||
postTextStyle,
|
||||
sourceLanguage,
|
||||
resultSourceLanguage,
|
||||
translatedText,
|
||||
initialTranslationParams,
|
||||
}: {
|
||||
clearTranslation: () => void
|
||||
translate: TranslationFunction
|
||||
postText: string
|
||||
postTextStyle?: StyleProp<TextStyle>
|
||||
sourceLanguage: string | null
|
||||
resultSourceLanguage: string | null
|
||||
translatedText: string
|
||||
initialTranslationParams: TranslationFunctionParams
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const langPrefs = useLanguagePrefs()
|
||||
const {i18n, t: l} = useLingui()
|
||||
|
||||
const langName = sourceLanguage
|
||||
? codeToLanguageName(sourceLanguage, i18n.locale)
|
||||
const langName = resultSourceLanguage
|
||||
? codeToLanguageName(resultSourceLanguage, i18n.locale)
|
||||
: undefined
|
||||
|
||||
const flattenedStyle = flatten(postTextStyle) ?? {}
|
||||
@@ -323,7 +326,7 @@ function TranslationResult({
|
||||
<Trans>Translated</Trans>
|
||||
</Text>
|
||||
)}
|
||||
{sourceLanguage != null && (
|
||||
{resultSourceLanguage != null && (
|
||||
<>
|
||||
<Text
|
||||
style={[
|
||||
@@ -336,9 +339,9 @@ function TranslationResult({
|
||||
·{' '}
|
||||
</Text>
|
||||
<TranslationLanguageSelect
|
||||
sourceLanguage={sourceLanguage}
|
||||
resultSourceLanguage={resultSourceLanguage}
|
||||
translate={translate}
|
||||
postText={postText}
|
||||
initialTranslationParams={initialTranslationParams}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
@@ -362,12 +365,12 @@ function TranslationResult({
|
||||
|
||||
function TranslationLanguageSelect({
|
||||
translate,
|
||||
postText,
|
||||
sourceLanguage,
|
||||
resultSourceLanguage,
|
||||
initialTranslationParams,
|
||||
}: {
|
||||
translate: TranslationFunction
|
||||
postText: string
|
||||
sourceLanguage: string
|
||||
resultSourceLanguage: string
|
||||
initialTranslationParams: TranslationFunctionParams
|
||||
}) {
|
||||
const t = useTheme()
|
||||
const ax = useAnalytics()
|
||||
@@ -383,8 +386,8 @@ function TranslationLanguageSelect({
|
||||
)
|
||||
.sort((a, b) => {
|
||||
// Prioritize sourceLanguage at the top
|
||||
if (a.code2 === sourceLanguage) return -1
|
||||
if (b.code2 === sourceLanguage) return 1
|
||||
if (a.code2 === resultSourceLanguage) return -1
|
||||
if (b.code2 === resultSourceLanguage) return 1
|
||||
// Localized sort
|
||||
return languageName(a, langPrefs.appLanguage).localeCompare(
|
||||
languageName(b, langPrefs.appLanguage),
|
||||
@@ -395,26 +398,28 @@ function TranslationLanguageSelect({
|
||||
label: languageName(l, langPrefs.appLanguage), // The viewer may not be familiar with the source language, so localize the name
|
||||
value: l.code2,
|
||||
})),
|
||||
[langPrefs, sourceLanguage],
|
||||
[langPrefs, resultSourceLanguage],
|
||||
)
|
||||
|
||||
const handleChangeTranslationLanguage = (sourceLangCode: string) => {
|
||||
ax.metric('translate:override', {
|
||||
os: Platform.OS,
|
||||
sourceLanguage: sourceLangCode,
|
||||
targetLanguage: langPrefs.primaryLanguage,
|
||||
possibleSourceLanguages: initialTranslationParams.possibleSourceLanguages,
|
||||
expectedSourceLanguage: sourceLangCode,
|
||||
expectedTargetLanguage: initialTranslationParams.expectedTargetLanguage,
|
||||
resultSourceLanguage,
|
||||
})
|
||||
void translate({
|
||||
text: postText,
|
||||
targetLangCode: langPrefs.primaryLanguage,
|
||||
sourceLangCode,
|
||||
sourceSelection: 'manual',
|
||||
text: initialTranslationParams.text,
|
||||
expectedTargetLanguage: initialTranslationParams.expectedTargetLanguage,
|
||||
expectedSourceLanguage: sourceLangCode,
|
||||
possibleSourceLanguages: initialTranslationParams.possibleSourceLanguages,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<Select.Root
|
||||
value={sourceLanguage}
|
||||
value={resultSourceLanguage}
|
||||
onValueChange={handleChangeTranslationLanguage}>
|
||||
<Select.Trigger label={l`Change the source language`}>
|
||||
{({props}) => {
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
import * as Clipboard from 'expo-clipboard'
|
||||
import {
|
||||
type AppBskyFeedDefs,
|
||||
AppBskyFeedPost,
|
||||
type AppBskyFeedPost,
|
||||
type AppBskyFeedThreadgate,
|
||||
AtUri,
|
||||
type RichText as RichTextAPI,
|
||||
@@ -96,7 +96,6 @@ import * as Prompt from '#/components/Prompt'
|
||||
import * as Toast from '#/components/Toast'
|
||||
import {useAnalytics} from '#/analytics'
|
||||
import {IS_INTERNAL} from '#/env'
|
||||
import * as bsky from '#/types/bsky'
|
||||
|
||||
let PostMenuItems = ({
|
||||
post,
|
||||
@@ -138,7 +137,6 @@ let PostMenuItems = ({
|
||||
const openLink = useOpenLink()
|
||||
const {clearTranslation, translate, translationState} = useTranslate({
|
||||
key: post.uri,
|
||||
postLangCodes: getPostLanguageTags(post),
|
||||
forceGoogleTranslate,
|
||||
})
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
@@ -279,22 +277,9 @@ let PostMenuItems = ({
|
||||
const onPressTranslate = () => {
|
||||
void translate({
|
||||
text: record.text,
|
||||
targetLangCode: langPrefs.primaryLanguage,
|
||||
expectedTargetLanguage: langPrefs.primaryLanguage,
|
||||
possibleSourceLanguages: getPostLanguageTags(post),
|
||||
})
|
||||
|
||||
if (
|
||||
bsky.dangerousIsType<AppBskyFeedPost.Record>(
|
||||
post.record,
|
||||
AppBskyFeedPost.isRecord,
|
||||
)
|
||||
) {
|
||||
ax.metric('translate', {
|
||||
os: Platform.OS,
|
||||
sourceLanguages: post.record.langs ?? [],
|
||||
targetLanguage: langPrefs.primaryLanguage,
|
||||
textLength: post.record.text.length,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const onHidePost = () => {
|
||||
|
||||
@@ -68,9 +68,10 @@ export let MessageContextMenu = ({
|
||||
|
||||
ax.metric('translate', {
|
||||
os: Platform.OS,
|
||||
sourceLanguages: [],
|
||||
targetLanguage: langPrefs.primaryLanguage,
|
||||
possibleSourceLanguages: [], // N/A for chats
|
||||
expectedTargetLanguage: langPrefs.primaryLanguage,
|
||||
textLength: message.text.length,
|
||||
googleTranslate: true,
|
||||
})
|
||||
}, [ax, langPrefs.primaryLanguage, message.text, translate])
|
||||
|
||||
|
||||
@@ -103,7 +103,6 @@ async function attemptTranslation(
|
||||
export function useTranslate({
|
||||
key,
|
||||
forceGoogleTranslate = false,
|
||||
postLangCodes,
|
||||
}: TranslationOptions) {
|
||||
const context = useContext(Context)
|
||||
if (!context) {
|
||||
@@ -121,14 +120,17 @@ export function useTranslate({
|
||||
|
||||
const translate = useCallback(
|
||||
async (params: TranslationFunctionParams) => {
|
||||
return context.translate({
|
||||
...params,
|
||||
key,
|
||||
forceGoogleTranslate,
|
||||
postLangCodes,
|
||||
})
|
||||
return context.translate(
|
||||
{
|
||||
...params,
|
||||
},
|
||||
{
|
||||
key,
|
||||
forceGoogleTranslate,
|
||||
},
|
||||
)
|
||||
},
|
||||
[context, forceGoogleTranslate, key, postLangCodes],
|
||||
[context, forceGoogleTranslate, key],
|
||||
)
|
||||
|
||||
const clearTranslation = useCallback(
|
||||
@@ -208,17 +210,34 @@ export function Provider({children}: React.PropsWithChildren<unknown>) {
|
||||
}, [])
|
||||
|
||||
const translate = useCallback<ContextType['translate']>(
|
||||
async ({
|
||||
key,
|
||||
text,
|
||||
targetLangCode,
|
||||
sourceLangCode,
|
||||
sourceSelection = 'automatic',
|
||||
postLangCodes,
|
||||
...options
|
||||
}) => {
|
||||
if (options?.forceGoogleTranslate || !HAS_ON_DEVICE_TRANSLATION) {
|
||||
await googleTranslate(text, targetLangCode, sourceLangCode)
|
||||
async (
|
||||
{
|
||||
text,
|
||||
expectedTargetLanguage,
|
||||
expectedSourceLanguage,
|
||||
possibleSourceLanguages,
|
||||
forceGoogleTranslate: forceGoogleTranslateOverride,
|
||||
},
|
||||
{key, forceGoogleTranslate},
|
||||
) => {
|
||||
const shouldForceGoogleTranslate = Boolean(
|
||||
forceGoogleTranslateOverride ?? forceGoogleTranslate,
|
||||
)
|
||||
|
||||
ax.metric('translate', {
|
||||
os: Platform.OS,
|
||||
possibleSourceLanguages,
|
||||
expectedTargetLanguage: expectedTargetLanguage,
|
||||
textLength: text.length,
|
||||
googleTranslate: shouldForceGoogleTranslate,
|
||||
})
|
||||
|
||||
if (shouldForceGoogleTranslate || !HAS_ON_DEVICE_TRANSLATION) {
|
||||
await googleTranslate(
|
||||
text,
|
||||
expectedTargetLanguage,
|
||||
expectedSourceLanguage,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -232,16 +251,18 @@ export function Provider({children}: React.PropsWithChildren<unknown>) {
|
||||
try {
|
||||
const result = await attemptTranslation(
|
||||
text,
|
||||
targetLangCode,
|
||||
sourceLangCode,
|
||||
expectedTargetLanguage,
|
||||
expectedSourceLanguage,
|
||||
)
|
||||
ax.metric('translate:result', {
|
||||
method: 'on-device',
|
||||
success: true,
|
||||
os: Platform.OS,
|
||||
sourceSelection,
|
||||
sourceLanguage: result.sourceLanguage,
|
||||
targetLanguage: result.targetLanguage,
|
||||
postLanguages: postLangCodes,
|
||||
possibleSourceLanguages,
|
||||
expectedSourceLanguage: expectedSourceLanguage ?? null,
|
||||
expectedTargetLanguage,
|
||||
resultSourceLanguage: result.sourceLanguage,
|
||||
resultTargetLanguage: result.targetLanguage,
|
||||
textLength: text.length,
|
||||
})
|
||||
if (!IS_ANDROID) {
|
||||
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
|
||||
@@ -253,7 +274,7 @@ export function Provider({children}: React.PropsWithChildren<unknown>) {
|
||||
translatedText: result.translatedText,
|
||||
sourceLanguage: result.sourceLanguage,
|
||||
targetLanguage: result.targetLanguage,
|
||||
postLanguages: postLangCodes,
|
||||
postLanguages: possibleSourceLanguages,
|
||||
},
|
||||
}))
|
||||
} catch (e) {
|
||||
@@ -261,12 +282,14 @@ export function Provider({children}: React.PropsWithChildren<unknown>) {
|
||||
// On-device translation failed (language pack missing or user
|
||||
// dismissed the download prompt).
|
||||
ax.metric('translate:result', {
|
||||
method: 'fallback-alert',
|
||||
success: false,
|
||||
os: Platform.OS,
|
||||
sourceSelection,
|
||||
sourceLanguage: sourceLangCode ?? null,
|
||||
targetLanguage: targetLangCode,
|
||||
postLanguages: postLangCodes,
|
||||
possibleSourceLanguages,
|
||||
expectedSourceLanguage: expectedSourceLanguage ?? null,
|
||||
expectedTargetLanguage,
|
||||
resultSourceLanguage: null,
|
||||
resultTargetLanguage: null,
|
||||
textLength: text.length,
|
||||
})
|
||||
let errorMessage = l`Device failed to translate :(`
|
||||
if (!IS_ANDROID) {
|
||||
|
||||
@@ -22,7 +22,7 @@ const clearTranslation = (_key: string) => {}
|
||||
/**
|
||||
* Web always opens Google Translate.
|
||||
*/
|
||||
export function useTranslate({key, postLangCodes}: TranslationOptions) {
|
||||
export function useTranslate({key}: TranslationOptions) {
|
||||
const context = useContext(Context)
|
||||
if (!context) {
|
||||
throw new Error(
|
||||
@@ -33,14 +33,17 @@ export function useTranslate({key, postLangCodes}: TranslationOptions) {
|
||||
// Always call hooks in consistent order
|
||||
const translate = useCallback(
|
||||
async (params: TranslationFunctionParams) => {
|
||||
return context.translate({
|
||||
...params,
|
||||
key,
|
||||
forceGoogleTranslate: true,
|
||||
postLangCodes,
|
||||
})
|
||||
return context.translate(
|
||||
{
|
||||
...params,
|
||||
},
|
||||
{
|
||||
key,
|
||||
forceGoogleTranslate: true,
|
||||
},
|
||||
)
|
||||
},
|
||||
[key, context, postLangCodes],
|
||||
[key, context],
|
||||
)
|
||||
|
||||
const clearTranslation = useCallback(() => {
|
||||
@@ -61,8 +64,24 @@ export function Provider({children}: React.PropsWithChildren<unknown>) {
|
||||
const googleTranslate = useGoogleTranslate()
|
||||
|
||||
const translate = useCallback<ContextType['translate']>(
|
||||
async ({text, targetLangCode, sourceLangCode}) => {
|
||||
await googleTranslate(text, targetLangCode, sourceLangCode)
|
||||
async ({
|
||||
text,
|
||||
expectedTargetLanguage,
|
||||
expectedSourceLanguage,
|
||||
possibleSourceLanguages,
|
||||
}) => {
|
||||
ax.metric('translate', {
|
||||
os: 'web',
|
||||
possibleSourceLanguages,
|
||||
expectedTargetLanguage,
|
||||
textLength: text.length,
|
||||
googleTranslate: true,
|
||||
})
|
||||
await googleTranslate(
|
||||
text,
|
||||
expectedTargetLanguage,
|
||||
expectedSourceLanguage,
|
||||
)
|
||||
},
|
||||
[ax, googleTranslate],
|
||||
)
|
||||
|
||||
@@ -22,38 +22,45 @@ export type TranslationFunctionParams = {
|
||||
/**
|
||||
* The language to translate the text into.
|
||||
*/
|
||||
targetLangCode: string
|
||||
expectedTargetLanguage: string
|
||||
/**
|
||||
* The source language of the text. Will auto-detect if not provided.
|
||||
* We auto-detect the source language by default, but the user has the option
|
||||
* to specify a source language if they want to. If this value is present, it
|
||||
* means the user selected a source language, or we were certain of the
|
||||
* source language and want to specify it explicitly.
|
||||
*/
|
||||
sourceLangCode?: string
|
||||
expectedSourceLanguage?: string
|
||||
/**
|
||||
* Whether we auto-detected the language or it was selected manually. Defaults to 'automatic'.
|
||||
* The languages the content might be in, such as the user-supplied
|
||||
* language codes on posts. Currently only available on posts.
|
||||
*/
|
||||
sourceSelection?: 'automatic' | 'manual'
|
||||
possibleSourceLanguages?: string[]
|
||||
/**
|
||||
* Override the default behavior and always use Google Translate.
|
||||
*/
|
||||
forceGoogleTranslate?: boolean
|
||||
}
|
||||
|
||||
export type TranslationOptions = {
|
||||
key: string
|
||||
forceGoogleTranslate?: boolean
|
||||
/**
|
||||
* The language(s) of the post being translated. Used for analytics purposes
|
||||
* to understand translation usage patterns better. Optional because it may
|
||||
* not always be available (e.g. if the post text is empty or if the
|
||||
* translation is triggered from a non-post
|
||||
* context).
|
||||
* A unique key to identify this translation instance e.g. the post URI
|
||||
*/
|
||||
postLangCodes?: string[]
|
||||
key: string
|
||||
/**
|
||||
* Override the default behavior and always use Google Translate.
|
||||
*/
|
||||
forceGoogleTranslate?: boolean
|
||||
}
|
||||
|
||||
export type TranslationFunction = (
|
||||
parameters: TranslationFunctionParams,
|
||||
params: TranslationFunctionParams,
|
||||
) => Promise<void>
|
||||
|
||||
export type ContextType = {
|
||||
translationState: Record<string, TranslationState>
|
||||
translate: (
|
||||
parameters: TranslationFunctionParams & TranslationOptions,
|
||||
params: TranslationFunctionParams,
|
||||
options: TranslationOptions,
|
||||
) => Promise<void>
|
||||
clearTranslation: (key: string) => void
|
||||
acquireTranslation: (key: string) => () => void
|
||||
|
||||
@@ -411,11 +411,7 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({
|
||||
shouldProxyLinks={true}
|
||||
/>
|
||||
) : undefined}
|
||||
<TranslatedPost
|
||||
post={post}
|
||||
postText={record.text}
|
||||
postTextStyle={[a.text_lg]}
|
||||
/>
|
||||
<TranslatedPost post={post} postTextStyle={[a.text_lg]} />
|
||||
{post.embed && (
|
||||
<View style={[a.py_xs]}>
|
||||
<Embed
|
||||
|
||||
@@ -321,11 +321,7 @@ const ThreadItemPostInner = memo(function ThreadItemPostInner({
|
||||
)}
|
||||
</View>
|
||||
) : undefined}
|
||||
<TranslatedPost
|
||||
hideTranslateLink={true}
|
||||
post={post}
|
||||
postText={record.text}
|
||||
/>
|
||||
<TranslatedPost hideTranslateLink post={post} />
|
||||
{post.embed && (
|
||||
<View style={[a.pb_xs]}>
|
||||
<Embed
|
||||
|
||||
@@ -361,11 +361,7 @@ const ThreadItemTreePostInner = memo(function ThreadItemTreePostInner({
|
||||
)}
|
||||
</View>
|
||||
) : null}
|
||||
<TranslatedPost
|
||||
hideTranslateLink={true}
|
||||
post={post}
|
||||
postText={record.text}
|
||||
/>
|
||||
<TranslatedPost hideTranslateLink post={post} />
|
||||
{post.embed && (
|
||||
<View style={[a.pb_xs]}>
|
||||
<Embed
|
||||
|
||||
@@ -219,11 +219,7 @@ function PostInner({
|
||||
)}
|
||||
</View>
|
||||
) : undefined}
|
||||
<TranslatedPost
|
||||
hideTranslateLink={true}
|
||||
post={post}
|
||||
postText={record.text}
|
||||
/>
|
||||
<TranslatedPost hideTranslateLink post={post} />
|
||||
{post.embed ? (
|
||||
<Embed
|
||||
embed={post.embed}
|
||||
|
||||
@@ -490,13 +490,7 @@ let PostContent = ({
|
||||
)}
|
||||
</View>
|
||||
) : undefined}
|
||||
{record && (
|
||||
<TranslatedPost
|
||||
hideTranslateLink={true}
|
||||
post={post}
|
||||
postText={record.text}
|
||||
/>
|
||||
)}
|
||||
{record && <TranslatedPost hideTranslateLink post={post} />}
|
||||
{postEmbed ? (
|
||||
<View style={[a.pb_xs]}>
|
||||
<Embed
|
||||
|
||||
Reference in New Issue
Block a user