expo-popcore-app/lib/i18n.ts

126 lines
3.8 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import i18n from 'i18next'
import { initReactI18next } from 'react-i18next'
import { NativeModules, Platform } from 'react-native'
import { storage } from './storage'
// 导入语言资源
import enUS from '../locales/en-US.json'
import zhCN from '../locales/zh-CN.json'
// 定义支持的语言
export const SUPPORTED_LANGUAGES = {
'zh-CN': '简体中文',
'en-US': 'English',
} as const
export type SupportedLanguage = keyof typeof SUPPORTED_LANGUAGES
// 获取系统语言Android 和 iOS 兼容)
const getSystemLanguage = (): string => {
try {
let locale: string | undefined
if (Platform.OS === 'ios') {
// iOS: 从 SettingsManager 获取
const settings = NativeModules.SettingsManager?.settings
locale = settings?.AppleLocale || settings?.AppleLanguages?.[0]
} else if (Platform.OS === 'android') {
// Android: 从 I18nManager 获取
locale = NativeModules.I18nManager?.localeIdentifier
}
if (locale) {
// 处理语言代码格式,例如 'zh_CN' -> 'zh-CN', 'en_US' -> 'en-US'
const normalized = locale.replace('_', '-').toLowerCase()
if (normalized.startsWith('zh')) {
return 'zh-CN'
} else if (normalized.startsWith('en')) {
return 'en-US'
}
}
} catch (error) {
// 静默处理错误,使用默认语言
console.warn('Error getting system language:', error)
}
return 'zh-CN' // 默认返回中文
}
// AsyncStorage 语言检测器(兼容 Android 和 iOS
const languageDetector = {
type: 'languageDetector' as const,
async: true,
detect: async (callback: (lng: string) => void) => {
try {
// 1. 优先使用用户保存的语言设置
const savedLanguage = await storage.getItem('app_language')
if (savedLanguage) {
// 兼容旧的语言代码格式
if (savedLanguage === 'zh' || savedLanguage === 'zh-CN') {
callback('zh-CN')
return
} else if (savedLanguage === 'en' || savedLanguage === 'en-US') {
callback('en-US')
return
}
}
// 2. 如果没有保存的语言,尝试使用系统语言
const systemLang = getSystemLanguage()
callback(systemLang)
} catch (error) {
console.error('Error detecting language:', error)
// 3. 如果出错,使用默认语言
callback('zh-CN')
}
},
init: () => { },
cacheUserLanguage: async (lng: string) => {
try {
// AsyncStorage 在 Android 和 iOS 上都正常工作
await storage.setItem('app_language', lng)
} catch (error) {
console.error('Error saving language:', error)
}
},
}
// i18n配置
i18n.use(languageDetector)
.use(initReactI18next)
.init({
// 语言资源
resources: {
'zh-CN': {
translation: zhCN,
},
'en-US': {
translation: enUS,
},
},
// 默认语言
fallbackLng: 'zh-CN',
// 调试模式(开发环境开启)
debug: false,
// 兼容性配置:使用 v3 格式处理复数,避免 Android 端 Intl.PluralRules 不支持的问题
compatibilityJSON: 'v3',
// 插值配置
interpolation: {
escapeValue: false, // React已经处理了XSS防护
},
// 命名空间配置
defaultNS: 'translation',
ns: ['translation'],
// 键值分隔符
keySeparator: '.',
nsSeparator: ':',
})
export default i18n