- Introduced new translation files for medication, personal, and weight management in Chinese. - Updated the main index file to include the new translation modules. - Enhanced the medication type definitions to include 'ointment'. - Refactored workout type labels to utilize i18n for better localization support. - Improved sleep quality descriptions and recommendations with i18n integration.
77 lines
2.3 KiB
TypeScript
77 lines
2.3 KiB
TypeScript
import * as Localization from 'expo-localization';
|
|
import i18n from 'i18next';
|
|
import { initReactI18next } from 'react-i18next';
|
|
|
|
import { getItemSync, setItem } from '@/utils/kvStore';
|
|
import en from './en';
|
|
import zh from './zh';
|
|
|
|
export const LANGUAGE_PREFERENCE_KEY = 'app_language_preference';
|
|
export const SUPPORTED_LANGUAGES = ['zh', 'en'] as const;
|
|
export type AppLanguage = typeof SUPPORTED_LANGUAGES[number];
|
|
|
|
const fallbackLanguage: AppLanguage = 'zh';
|
|
|
|
const resources = {
|
|
zh: {
|
|
translation: zh,
|
|
},
|
|
en: {
|
|
translation: en,
|
|
},
|
|
};
|
|
|
|
export const isSupportedLanguage = (language?: string | null): language is AppLanguage => {
|
|
if (!language) return false;
|
|
return SUPPORTED_LANGUAGES.some((code) => language === code || language.startsWith(`${code}-`));
|
|
};
|
|
|
|
export const getNormalizedLanguage = (language?: string | null): AppLanguage => {
|
|
if (!language) return fallbackLanguage;
|
|
const normalized = SUPPORTED_LANGUAGES.find((code) => language === code || language.startsWith(`${code}-`));
|
|
return normalized ?? fallbackLanguage;
|
|
};
|
|
|
|
const getStoredLanguage = (): AppLanguage | null => {
|
|
try {
|
|
const stored = getItemSync?.(LANGUAGE_PREFERENCE_KEY) as AppLanguage | null | undefined;
|
|
if (stored && isSupportedLanguage(stored)) {
|
|
return stored;
|
|
}
|
|
} catch (error) {
|
|
// ignore storage errors and fall back to device preference
|
|
}
|
|
return null;
|
|
};
|
|
|
|
const getDeviceLanguage = (): AppLanguage | null => {
|
|
try {
|
|
const locales = Localization.getLocales();
|
|
const preferred = locales.find((locale) => locale.languageCode && isSupportedLanguage(locale.languageCode));
|
|
return preferred?.languageCode as AppLanguage | undefined || null;
|
|
} catch (error) {
|
|
return null;
|
|
}
|
|
};
|
|
|
|
const initialLanguage = getStoredLanguage() ?? getDeviceLanguage() ?? fallbackLanguage;
|
|
|
|
void i18n.use(initReactI18next).init({
|
|
compatibilityJSON: 'v4',
|
|
resources,
|
|
lng: initialLanguage,
|
|
fallbackLng: fallbackLanguage,
|
|
interpolation: {
|
|
escapeValue: false,
|
|
},
|
|
returnNull: false,
|
|
});
|
|
|
|
export const changeAppLanguage = async (language: AppLanguage) => {
|
|
const nextLanguage = isSupportedLanguage(language) ? language : fallbackLanguage;
|
|
await i18n.changeLanguage(nextLanguage);
|
|
await setItem(LANGUAGE_PREFERENCE_KEY, nextLanguage);
|
|
};
|
|
|
|
export default i18n;
|