Files
digital-pilates/i18n/index.ts
richarjiang bca6670390 Add Chinese translations for medication management and personal settings
- 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.
2025-11-28 17:29:51 +08:00

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;