feat: localstorage与SecureStore
This commit is contained in:
parent
6ab9f5db6a
commit
9939fd23aa
7
app.json
7
app.json
@ -34,6 +34,13 @@
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
}
|
||||
],
|
||||
[
|
||||
"expo-secure-store",
|
||||
{
|
||||
"configureAndroidBackup": true,
|
||||
"faceIDPermission": "Allow $(PRODUCT_NAME) to access your Face ID biometric data."
|
||||
}
|
||||
]
|
||||
],
|
||||
"experiments": {
|
||||
|
||||
@ -1,35 +1,68 @@
|
||||
import React, { createContext, useState, useContext, useEffect } from 'react';
|
||||
import * as SecureStore from 'expo-secure-store';
|
||||
import { Platform } from 'react-native';
|
||||
import React, { createContext, useContext, useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
type LanguageContextType = {
|
||||
currentLanguage: string;
|
||||
changeLanguage: (lang: string) => void;
|
||||
};
|
||||
// 保存语言设置
|
||||
async function save(key: string, value: string) {
|
||||
if (Platform.OS === 'web') {
|
||||
localStorage.setItem(key, value);
|
||||
} else {
|
||||
await SecureStore.setItemAsync(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
// 获取语言设置
|
||||
async function load(key: string): Promise<string | null> {
|
||||
if (Platform.OS === 'web') {
|
||||
return localStorage.getItem(key);
|
||||
} else {
|
||||
return await SecureStore.getItemAsync(key);
|
||||
}
|
||||
}
|
||||
const LanguageContext = createContext<LanguageContextType | undefined>(undefined);
|
||||
|
||||
export const LanguageProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const { i18n } = useTranslation();
|
||||
// 从localStorage获取保存的语言设置,如果没有则使用当前语言或默认为'en'
|
||||
const savedLanguage = localStorage.getItem('i18nextLng') || i18n.language || 'en';
|
||||
const [currentLanguage, setCurrentLanguage] = useState(savedLanguage);
|
||||
const [currentLanguage, setCurrentLanguage] = useState(i18n.language || 'en');
|
||||
|
||||
// 初始化时加载保存的语言设置
|
||||
useEffect(() => {
|
||||
const loadSavedLanguage = async () => {
|
||||
try {
|
||||
const savedLang = await load('i18nextLng');
|
||||
if (savedLang) {
|
||||
setCurrentLanguage(savedLang);
|
||||
i18n.changeLanguage(savedLang);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load language setting:', error);
|
||||
}
|
||||
};
|
||||
|
||||
loadSavedLanguage();
|
||||
}, [i18n]);
|
||||
|
||||
const changeLanguage = (lang: string) => {
|
||||
i18n.changeLanguage(lang);
|
||||
// 将语言设置保存到localStorage
|
||||
localStorage.setItem('i18nextLng', lang);
|
||||
// 保存语言设置
|
||||
save('i18nextLng', lang).catch(error => {
|
||||
console.error('Failed to save language setting:', error);
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
// 确保初始化时使用正确的语言
|
||||
if (savedLanguage && i18n.language !== savedLanguage) {
|
||||
i18n.changeLanguage(savedLanguage);
|
||||
}
|
||||
|
||||
const handleLanguageChanged = () => {
|
||||
setCurrentLanguage(i18n.language);
|
||||
// 将更改后的语言保存到localStorage
|
||||
localStorage.setItem('i18nextLng', i18n.language);
|
||||
const newLanguage = i18n.language;
|
||||
setCurrentLanguage(newLanguage);
|
||||
// 将更改后的语言保存到存储
|
||||
save('i18nextLng', newLanguage).catch(error => {
|
||||
console.error('Failed to save language setting:', error);
|
||||
});
|
||||
};
|
||||
|
||||
i18n.on('languageChanged', handleLanguageChanged);
|
||||
@ -37,7 +70,7 @@ export const LanguageProvider: React.FC<{ children: React.ReactNode }> = ({ chil
|
||||
return () => {
|
||||
i18n.off('languageChanged', handleLanguageChanged);
|
||||
};
|
||||
}, [i18n, savedLanguage]);
|
||||
}, [i18n]);
|
||||
|
||||
return (
|
||||
<LanguageContext.Provider value={{ currentLanguage, changeLanguage }}>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
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';
|
||||
|
||||
@ -28,13 +29,30 @@ i18n
|
||||
escapeValue: false, // 不需要转义,React已经处理了
|
||||
},
|
||||
|
||||
detection: {
|
||||
detection: Platform.OS === 'web' ? {
|
||||
// Web 环境使用 localStorage
|
||||
order: ['localStorage', 'navigator'],
|
||||
caches: ['localStorage'],
|
||||
lookupLocalStorage: 'i18nextLng',
|
||||
// 确保语言设置被保存到localStorage
|
||||
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) // 使用类型断言绕过类型检查
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
10
package-lock.json
generated
10
package-lock.json
generated
@ -23,6 +23,7 @@
|
||||
"expo-linking": "~7.1.5",
|
||||
"expo-localization": "^16.1.5",
|
||||
"expo-router": "~5.1.0",
|
||||
"expo-secure-store": "~14.2.3",
|
||||
"expo-splash-screen": "~0.30.9",
|
||||
"expo-status-bar": "~2.2.3",
|
||||
"expo-symbols": "~0.4.5",
|
||||
@ -7262,6 +7263,15 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-secure-store": {
|
||||
"version": "14.2.3",
|
||||
"resolved": "https://registry.npmjs.org/expo-secure-store/-/expo-secure-store-14.2.3.tgz",
|
||||
"integrity": "sha512-hYBbaAD70asKTFd/eZBKVu+9RTo9OSTMMLqXtzDF8ndUGjpc6tmRCoZtrMHlUo7qLtwL5jm+vpYVBWI8hxh/1Q==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"expo": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/expo-splash-screen": {
|
||||
"version": "0.30.9",
|
||||
"resolved": "https://registry.npmjs.org/expo-splash-screen/-/expo-splash-screen-0.30.9.tgz",
|
||||
|
||||
@ -46,7 +46,8 @@
|
||||
"react-native-safe-area-context": "^5.4.0",
|
||||
"react-native-screens": "~4.11.1",
|
||||
"react-native-web": "~0.20.0",
|
||||
"react-native-webview": "13.13.5"
|
||||
"react-native-webview": "13.13.5",
|
||||
"expo-secure-store": "~14.2.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user