Log languages a post is tagged with after translating (#10014)

Co-authored-by: Eric Bailey <git@esb.lol>
This commit is contained in:
DS Boyce
2026-03-17 10:31:23 -07:00
committed by GitHub
parent be0d00de17
commit 1386a559b7
11 changed files with 102 additions and 81 deletions
+2 -12
View File
@@ -1,16 +1,6 @@
import {createContext} from 'react'
import {type TranslationFunctionParams, type TranslationState} from './types'
import {type ContextType} from './types'
export const Context = createContext<{
translationState: Record<string, TranslationState>
translate: (
parameters: TranslationFunctionParams & {
key: string
forceGoogleTranslate: boolean
},
) => Promise<void>
clearTranslation: (key: string) => void
acquireTranslation: (key: string) => () => void
} | null>(null)
export const Context = createContext<ContextType | null>(null)
Context.displayName = 'TranslationContext'
+25 -22
View File
@@ -11,7 +11,12 @@ import {logger} from '#/logger'
import {useAnalytics} from '#/analytics'
import {HAS_ON_DEVICE_TRANSLATION, IS_ANDROID, IS_IOS} from '#/env'
import {Context} from './context'
import {type TranslationFunctionParams, type TranslationState} from './types'
import {
type ContextType,
type TranslationFunctionParams,
type TranslationOptions,
type TranslationState,
} from './types'
import {guessLanguage} from './utils'
export * from './types'
@@ -98,10 +103,8 @@ async function attemptTranslation(
export function useTranslate({
key,
forceGoogleTranslate = false,
}: {
key: string
forceGoogleTranslate?: boolean
}) {
postLangCodes,
}: TranslationOptions) {
const context = useContext(Context)
if (!context) {
throw new Error(
@@ -118,9 +121,14 @@ export function useTranslate({
const translate = useCallback(
async (params: TranslationFunctionParams) => {
return context.translate({...params, key, forceGoogleTranslate})
return context.translate({
...params,
key,
forceGoogleTranslate,
postLangCodes,
})
},
[context, forceGoogleTranslate, key],
[context, forceGoogleTranslate, key, postLangCodes],
)
const clearTranslation = useCallback(
@@ -199,27 +207,17 @@ export function Provider({children}: React.PropsWithChildren<unknown>) {
})
}, [])
const translate = useCallback(
const translate = useCallback<ContextType['translate']>(
async ({
key,
text,
targetLangCode,
sourceLangCode,
sourceSelection = 'automatic',
postLangCodes,
...options
}: {
key: string
text: string
targetLangCode: string
sourceLangCode?: string
forceGoogleTranslate?: boolean
}) => {
if (options?.forceGoogleTranslate || !HAS_ON_DEVICE_TRANSLATION) {
ax.metric('translate:result', {
method: 'google-translate',
os: Platform.OS,
sourceLanguage: sourceLangCode ?? null,
targetLanguage: targetLangCode,
})
await googleTranslate(text, targetLangCode, sourceLangCode)
return
}
@@ -240,8 +238,10 @@ export function Provider({children}: React.PropsWithChildren<unknown>) {
ax.metric('translate:result', {
method: 'on-device',
os: Platform.OS,
sourceSelection,
sourceLanguage: result.sourceLanguage,
targetLanguage: result.targetLanguage,
postLanguages: postLangCodes,
})
if (!IS_ANDROID) {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
@@ -253,17 +253,20 @@ export function Provider({children}: React.PropsWithChildren<unknown>) {
translatedText: result.translatedText,
sourceLanguage: result.sourceLanguage,
targetLanguage: result.targetLanguage,
postLanguages: postLangCodes,
},
}))
} catch (e) {
logger.error('Failed to translate post on device', {safeMessage: e})
logger.error('Failed to translate text on device', {safeMessage: e})
// On-device translation failed (language pack missing or user
// dismissed the download prompt). Fall back to Google Translate.
// dismissed the download prompt).
ax.metric('translate:result', {
method: 'fallback-alert',
os: Platform.OS,
sourceSelection,
sourceLanguage: sourceLangCode ?? null,
targetLanguage: targetLangCode,
postLanguages: postLangCodes,
})
let errorMessage = l`Device failed to translate :(`
if (!IS_ANDROID) {
+16 -26
View File
@@ -3,7 +3,12 @@ import {useCallback, useContext, useMemo} from 'react'
import {useGoogleTranslate} from '#/lib/hooks/useGoogleTranslate'
import {useAnalytics} from '#/analytics'
import {Context} from './context'
import {type TranslationFunctionParams, type TranslationState} from './types'
import {
type ContextType,
type TranslationFunctionParams,
type TranslationOptions,
type TranslationState,
} from './types'
export * from './types'
export * from './utils'
@@ -17,12 +22,7 @@ const clearTranslation = (_key: string) => {}
/**
* Web always opens Google Translate.
*/
export function useTranslate({
key,
}: {
key: string
forceGoogleTranslate?: boolean
}) {
export function useTranslate({key, postLangCodes}: TranslationOptions) {
const context = useContext(Context)
if (!context) {
throw new Error(
@@ -33,9 +33,14 @@ export function useTranslate({
// Always call hooks in consistent order
const translate = useCallback(
async (params: TranslationFunctionParams) => {
return context.translate({...params, key, forceGoogleTranslate: true})
return context.translate({
...params,
key,
forceGoogleTranslate: true,
postLangCodes,
})
},
[key, context],
[key, context, postLangCodes],
)
const clearTranslation = useCallback(() => {
@@ -55,23 +60,8 @@ export function Provider({children}: React.PropsWithChildren<unknown>) {
const ax = useAnalytics()
const googleTranslate = useGoogleTranslate()
const translate = useCallback(
async ({
text,
targetLangCode,
sourceLangCode,
}: {
key: string
text: string
targetLangCode: string
sourceLangCode?: string
}) => {
ax.metric('translate:result', {
method: 'google-translate',
os: 'web',
sourceLanguage: sourceLangCode ?? null,
targetLanguage: targetLangCode,
})
const translate = useCallback<ContextType['translate']>(
async ({text, targetLangCode, sourceLangCode}) => {
await googleTranslate(text, targetLangCode, sourceLangCode)
},
[ax, googleTranslate],
+26
View File
@@ -27,8 +27,34 @@ export type TranslationFunctionParams = {
* The source language of the text. Will auto-detect if not provided.
*/
sourceLangCode?: string
/**
* Whether we auto-detected the language or it was selected manually. Defaults to 'automatic'.
*/
sourceSelection?: 'automatic' | 'manual'
}
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).
*/
postLangCodes?: string[]
}
export type TranslationFunction = (
parameters: TranslationFunctionParams,
) => Promise<void>
export type ContextType = {
translationState: Record<string, TranslationState>
translate: (
parameters: TranslationFunctionParams & TranslationOptions,
) => Promise<void>
clearTranslation: (key: string) => void
acquireTranslation: (key: string) => () => void
}