Pass key as argument to useTranslate hook

This commit is contained in:
DS Boyce
2026-03-03 12:36:22 -08:00
parent 06daefabac
commit 00c66eca47
5 changed files with 90 additions and 35 deletions
+9
View File
@@ -6,8 +6,17 @@ export const Context = createContext<{
translationState: Record<string, TranslationState>
translate: (parameters: {
key: string
/**
* The text to be translated.
*/
text: string
/**
* The language to translate the text into.
*/
targetLangCode: string
/**
* The source language of the text. Will auto-detect if not provided.
*/
sourceLangCode?: string
/**
* Whether to force the use of Google Translate. Default is false.
+29 -15
View File
@@ -77,31 +77,46 @@ async function attemptTranslation(
*
* Web uses index.web.ts which always opens Google Translate.
*/
export function useTranslate() {
export function useTranslate({key}: {key: string}) {
const context = useContext(Context)
if (!context) {
throw new Error(
'useTranslate must be used within a TranslateOnDeviceProvider',
)
}
return context
}
/**
* Hook to register a component as using a translation key.
* Automatically handles ref counting with screen focus management
* via useFocusEffect and cleans up the translation when the component
* loses focus.
*/
export function useTranslationKey(key: string) {
const {acquireTranslation} = useTranslate()
useFocusEffect(
useCallback(() => {
const cleanup = acquireTranslation(key)
if (!key) return
const cleanup = context.acquireTranslation(key)
return cleanup
}, [key, acquireTranslation]),
}, [key, context]),
)
const translate = useCallback(
async (params: {
text: string
targetLangCode: string
sourceLangCode?: string
forceGoogleTranslate?: boolean
}) => {
return context.translate({...params, key})
},
[key, context],
)
const clearTranslation = useCallback(
() => context.clearTranslation(key),
[key, context],
)
return {
translationState: context.translationState[key] ?? {
status: 'idle',
},
translate,
clearTranslation,
}
}
export function Provider({children}: React.PropsWithChildren<unknown>) {
@@ -184,7 +199,6 @@ export function Provider({children}: React.PropsWithChildren<unknown>) {
await googleTranslate(text, targetLangCode, sourceLangCode)
return
}
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut)
setTranslationState(prev => ({
...prev,
[key]: {status: 'loading'},
+39 -3
View File
@@ -11,18 +11,54 @@ const acquireTranslation = (_key: string) => {
}
const clearTranslation = (_key: string) => {}
export function useTranslationKey(_key: string) {}
/**
* Web always opens Google Translate.
*/
export function useTranslate() {
export function useTranslate(key: string) {
const context = useContext(Context)
if (!context) {
throw new Error(
'useTranslate must be used within a TranslateOnDeviceProvider',
)
}
// Always call hooks in consistent order
const translate = useCallback(
async (params: {
text: string
targetLangCode: string
sourceLangCode?: string
}) => {
if (!key) {
throw new Error(
'translate requires a key. Either pass key to useTranslate() or use context.translate() with key parameter',
)
}
return context.translate({...params, key})
},
[key, context],
)
const clearTranslation = useCallback(() => {
if (!key) {
throw new Error(
'clearTranslation requires a key. Either pass key to useTranslate() or use context.clearTranslation() with key parameter',
)
}
return context.clearTranslation(key)
}, [key, context])
// If a key is provided, return wrapped versions that automatically use the key
if (key) {
return {
translationState: context.translationState[key] ?? {
status: 'idle' as const,
},
translate,
clearTranslation,
}
}
return context
}