# I18N for Mobile app
TODO list for i18n:
- detect language from user
- handle display for static messages
- handle display for dynamic messages
- handle for external packages
- axios request with locale in header
- dayjs display
# Supported locales
Define supported locales for your app
export enum SupportedLocale {
vi = 'vi',
en = 'en',
}
export const DEFAULT_CONTENT_LOCALE = SupportedLocale.vi
export const FALLBACK_DETECTED_LOCALE = SupportedLocale.en
helpers
export function isLocaleSupported(locale: string): boolean {
return Object.values(SupportedLocale).includes(locale as SupportedLocale)
}
export function getSupportedLocale(locale: string): SupportedLocale | undefined {
return isLocaleSupported(locale) ? locale as SupportedLocale : undefined
}
# Language detection
# Static messages
Use lingui
(opens new window) library
# External packages
# Dynamic messages
When the backend doesn't provide a translated content for content-language
in header. It's nice to have feature => The app will request to an endpoint to translate text then display for UI
# Foundation
service.ts
import instance from '@/services/axios'
export type TranslationPayload = {
content: string
sourceLanguage?: string
targetLanguage: string
}
export async function translateText(payload: TranslationPayload) {
const res = await instance.post<TranslationResponse>('/translations/text', payload)
return res.data
}
useGetTranslatedTextQuery.tsx
type Options = {
originalLocale?: string
}
export function useGetTranslatedTextQuery(content: string, options?: Options) {
const {
isKeepOriginal,
originalLocale,
targetLocale
} = useDetectTranslatable(options)
const hash = hashTo32Chars(content || '')
const result = useQuery({
queryKey: ['translatedText', hash, targetLocale],
enabled: !!content,
queryFn: async () => {
if (isKeepOriginal) {
return content
}
const res = await translateText({
content,
targetLanguage: targetLocale,
sourceLanguage: originalLocale,
})
return res.translatedContent
},
})
return {
...result,
isKeepOriginal,
}
}
export function useDetectTranslatable(options?: Options) {
const { i18n } = useLingui()
const targetLocale = i18n.locale as SupportedLocale
const originalLocale = options?.originalLocale || DEFAULT_CONTENT_LOCALE
const isKeepOriginal = targetLocale === originalLocale
return {
translatable: !isKeepOriginal,
isKeepOriginal,
originalLocale,
targetLocale,
}
}