# 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,
  }
}

# Simple case

# Complex