完善多语言支持
This commit is contained in:
137
app/profile.tsx
137
app/profile.tsx
@@ -17,7 +17,7 @@ import { ThemedText } from "@/components/themed-text";
|
||||
import { IconSymbol } from "@/components/ui/icon-symbol";
|
||||
import { useAppState } from "@/context/AppStateContext";
|
||||
import { useTheme } from "@/context/ThemeContext";
|
||||
import { changeLanguage } from "@/i18n";
|
||||
import { changeLanguage, SUPPORTED_LANGUAGES } from "@/i18n";
|
||||
import { appleSignIn, fetchUserProfile, logout } from "@/lib/api";
|
||||
import { storage } from "@/lib/storage";
|
||||
import type { UserProfile } from "@/types/api";
|
||||
@@ -45,6 +45,7 @@ export default function ProfileScreen() {
|
||||
const [user, setUser] = React.useState<UserProfile | null>(null);
|
||||
const [loginModalVisible, setLoginModalVisible] = React.useState(false);
|
||||
const [oddsModalVisible, setOddsModalVisible] = React.useState(false);
|
||||
const [languageModalVisible, setLanguageModalVisible] = React.useState(false);
|
||||
|
||||
const currentLanguage = i18n.language;
|
||||
|
||||
@@ -75,9 +76,16 @@ export default function ProfileScreen() {
|
||||
selectedBookmakers: next,
|
||||
});
|
||||
};
|
||||
const toggleLanguage = () => {
|
||||
const nextLang = currentLanguage.startsWith("en") ? "zh" : "en";
|
||||
changeLanguage(nextLang);
|
||||
const selectLanguage = (langCode: string) => {
|
||||
changeLanguage(langCode);
|
||||
setLanguageModalVisible(false);
|
||||
};
|
||||
|
||||
const getCurrentLanguageName = () => {
|
||||
const lang = SUPPORTED_LANGUAGES.find((l) =>
|
||||
currentLanguage.startsWith(l.code)
|
||||
);
|
||||
return lang?.name || "English";
|
||||
};
|
||||
|
||||
const handleAppleSignIn = async () => {
|
||||
@@ -108,13 +116,13 @@ export default function ProfileScreen() {
|
||||
},
|
||||
user:
|
||||
credential.fullName &&
|
||||
(credential.fullName.givenName || credential.fullName.familyName)
|
||||
(credential.fullName.givenName || credential.fullName.familyName)
|
||||
? {
|
||||
name: {
|
||||
firstName: credential.fullName.givenName || undefined,
|
||||
lastName: credential.fullName.familyName || undefined,
|
||||
},
|
||||
}
|
||||
name: {
|
||||
firstName: credential.fullName.givenName || undefined,
|
||||
lastName: credential.fullName.familyName || undefined,
|
||||
},
|
||||
}
|
||||
: undefined,
|
||||
};
|
||||
|
||||
@@ -192,6 +200,7 @@ export default function ProfileScreen() {
|
||||
options={{
|
||||
title: t("profile.title"),
|
||||
headerShown: true,
|
||||
headerBackTitle: t("settings.back"),
|
||||
// Ensure header matches theme to avoid white flash
|
||||
headerStyle: {
|
||||
backgroundColor: isDark ? "#000" : "#f2f2f7",
|
||||
@@ -231,9 +240,9 @@ export default function ProfileScreen() {
|
||||
<ThemedText type="title">
|
||||
{user?.nickname || t("profile.name")}
|
||||
</ThemedText>
|
||||
<ThemedText style={{ color: subTextColor }}>
|
||||
{/* <ThemedText style={{ color: subTextColor }}>
|
||||
{user?.appleId || ""}
|
||||
</ThemedText>
|
||||
</ThemedText> */}
|
||||
</View>
|
||||
</View>
|
||||
<TouchableOpacity
|
||||
@@ -308,24 +317,30 @@ export default function ProfileScreen() {
|
||||
},
|
||||
]}
|
||||
>
|
||||
<View style={styles.settingLabel}>
|
||||
<IconSymbol
|
||||
name="globe"
|
||||
size={20}
|
||||
color={iconColor}
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
<ThemedText>{t("settings.language")}</ThemedText>
|
||||
</View>
|
||||
<View style={styles.settingControl}>
|
||||
<TouchableOpacity onPress={toggleLanguage} style={styles.button}>
|
||||
<ThemedText>
|
||||
{currentLanguage.startsWith("zh")
|
||||
? t("settings.chinese")
|
||||
: t("settings.english")}
|
||||
<TouchableOpacity
|
||||
style={styles.settingItemContent}
|
||||
onPress={() => setLanguageModalVisible(true)}
|
||||
>
|
||||
<View style={styles.settingLabel}>
|
||||
<IconSymbol
|
||||
name="globe"
|
||||
size={20}
|
||||
color={iconColor}
|
||||
style={{ marginRight: 10 }}
|
||||
/>
|
||||
<ThemedText>{t("settings.language")}</ThemedText>
|
||||
</View>
|
||||
<View style={{ flexDirection: "row", alignItems: "center" }}>
|
||||
<ThemedText style={{ color: subTextColor, marginRight: 4 }}>
|
||||
{getCurrentLanguageName()}
|
||||
</ThemedText>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<IconSymbol
|
||||
name="chevron-forward"
|
||||
size={16}
|
||||
color={subTextColor}
|
||||
/>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<View
|
||||
@@ -543,7 +558,7 @@ export default function ProfileScreen() {
|
||||
onPress={handleAppleSignIn}
|
||||
/>
|
||||
)}
|
||||
<TouchableOpacity style={styles.googleButton} onPress={() => {}}>
|
||||
<TouchableOpacity style={styles.googleButton} onPress={() => { }}>
|
||||
<ThemedText>{t("settings.google_login")}</ThemedText>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
@@ -618,6 +633,68 @@ export default function ProfileScreen() {
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
visible={languageModalVisible}
|
||||
transparent
|
||||
animationType="slide"
|
||||
onRequestClose={() => setLanguageModalVisible(false)}
|
||||
>
|
||||
<TouchableOpacity
|
||||
style={styles.modalMask}
|
||||
activeOpacity={1}
|
||||
onPress={() => setLanguageModalVisible(false)}
|
||||
>
|
||||
<View
|
||||
style={[
|
||||
styles.modalCard,
|
||||
{
|
||||
backgroundColor: isDark ? "#1c1c1e" : "#fff",
|
||||
maxHeight: "70%",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<ThemedText style={styles.modalTitle}>
|
||||
{t("settings.language")}
|
||||
</ThemedText>
|
||||
<ScrollView style={{ marginVertical: 10 }}>
|
||||
{SUPPORTED_LANGUAGES.map((lang) => {
|
||||
const isSelected = currentLanguage.startsWith(lang.code);
|
||||
return (
|
||||
<TouchableOpacity
|
||||
key={lang.code}
|
||||
style={[
|
||||
styles.bookmakerItem,
|
||||
{ borderColor: isDark ? "#38383a" : "#eee" },
|
||||
]}
|
||||
onPress={() => selectLanguage(lang.code)}
|
||||
>
|
||||
<ThemedText
|
||||
style={{
|
||||
color: isSelected ? "#FF9500" : textColor,
|
||||
fontWeight: isSelected ? "bold" : "normal",
|
||||
}}
|
||||
>
|
||||
{lang.name}
|
||||
</ThemedText>
|
||||
{isSelected && (
|
||||
<IconSymbol name="checkmark" size={18} color="#FF9500" />
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
})}
|
||||
</ScrollView>
|
||||
<TouchableOpacity
|
||||
style={styles.modalCancel}
|
||||
onPress={() => setLanguageModalVisible(false)}
|
||||
>
|
||||
<ThemedText type="defaultSemiBold">
|
||||
{t("settings.cancel")}
|
||||
</ThemedText>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user