119 lines
3.5 KiB
TypeScript
119 lines
3.5 KiB
TypeScript
import i18n from 'i18next';
|
||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||
import { initReactI18next } from 'react-i18next';
|
||
import { Platform } from 'react-native';
|
||
// 自动生成的导入
|
||
import translations from './translations-generated';
|
||
|
||
// 初始化i18next
|
||
i18n
|
||
// 检测用户语言
|
||
.use(LanguageDetector)
|
||
// 将i18n实例传递给react-i18next
|
||
.use(initReactI18next)
|
||
// 初始化i18next
|
||
.init({
|
||
// 初始不加载任何资源
|
||
resources: translations,
|
||
|
||
// 支持命名空间
|
||
ns: ['common', 'example', 'download'],
|
||
defaultNS: 'common',
|
||
|
||
// 设置默认语言为中文
|
||
lng: 'zh',
|
||
fallbackLng: 'en',
|
||
debug: process.env.NODE_ENV === 'development',
|
||
|
||
interpolation: {
|
||
escapeValue: false, // 不需要转义,React已经处理了
|
||
},
|
||
|
||
detection: Platform.OS === 'web' ? {
|
||
// Web 环境使用 localStorage
|
||
order: ['localStorage', 'navigator'],
|
||
caches: ['localStorage'],
|
||
lookupLocalStorage: 'i18nextLng',
|
||
lookupFromPathIndex: 0,
|
||
lookupFromSubdomainIndex: 0
|
||
} : {
|
||
// 原生环境使用自定义存储
|
||
order: ['customStorage', 'device'],
|
||
caches: ['customStorage'],
|
||
// 使用类型断言解决类型问题
|
||
...({
|
||
lookupCustomStorage: {
|
||
getItem: async (key: string) => {
|
||
const { getItemAsync } = await import('expo-secure-store');
|
||
return getItemAsync(key);
|
||
},
|
||
setItem: async (key: string, value: string) => {
|
||
const { setItemAsync } = await import('expo-secure-store');
|
||
await setItemAsync(key, value);
|
||
}
|
||
}
|
||
} as any) // 使用类型断言绕过类型检查
|
||
}
|
||
});
|
||
|
||
// 按需加载翻译资源的函数
|
||
export const loadNamespaceForLanguage = async (lng: string, ns: string) => {
|
||
// 如果已经加载过该命名空间,则不重复加载
|
||
if (i18n.hasResourceBundle(lng, ns)) {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const langTranslations = translations[lng as keyof typeof translations];
|
||
if (!langTranslations) {
|
||
console.warn(`No translations found for language: ${lng}`);
|
||
return;
|
||
}
|
||
const resource = langTranslations[ns as keyof typeof langTranslations];
|
||
if (resource) {
|
||
i18n.addResourceBundle(lng, ns, resource, true, true);
|
||
} else {
|
||
console.warn(`No translations found for ${lng}/${ns}`);
|
||
}
|
||
} catch (error) {
|
||
console.error(`Failed to load translations for ${lng}/${ns}:`, error);
|
||
}
|
||
};
|
||
|
||
// 加载指定命名空间及其备用语言的翻译
|
||
export const loadNamespaceWithFallback = async (ns: string, language?: string) => {
|
||
const currentLng = language || i18n.language || 'en';
|
||
|
||
// 加载当前语言的翻译
|
||
await loadNamespaceForLanguage(currentLng, ns);
|
||
|
||
// 如果当前语言不是英语,也加载英语作为备用
|
||
if (currentLng !== 'en') {
|
||
await loadNamespaceForLanguage('en', ns);
|
||
}
|
||
};
|
||
|
||
// 预加载公共翻译资源
|
||
export const preloadCommonTranslations = async () => {
|
||
const currentLng = i18n.language || 'en';
|
||
|
||
// 预加载 common 和 example 命名空间
|
||
await Promise.all([
|
||
loadNamespaceForLanguage(currentLng, 'common'),
|
||
loadNamespaceForLanguage(currentLng, 'example')
|
||
]);
|
||
|
||
// 如果当前语言不是英语,也预加载英语作为备用
|
||
if (currentLng !== 'en') {
|
||
await Promise.all([
|
||
loadNamespaceForLanguage('en', 'common'),
|
||
loadNamespaceForLanguage('en', 'example')
|
||
]);
|
||
}
|
||
};
|
||
|
||
// 初始加载公共翻译
|
||
preloadCommonTranslations();
|
||
|
||
export default i18n;
|