added french

This commit is contained in:
tapframe 2026-01-06 16:11:54 +05:30
parent 334d0b1863
commit 27ce25f5c5
8 changed files with 2530 additions and 105 deletions

View file

@ -578,6 +578,8 @@
"english": "الإنجليزية", "english": "الإنجليزية",
"portuguese": "البرتغالية", "portuguese": "البرتغالية",
"arabic": "العربية", "arabic": "العربية",
"spanish": "الإسبانية",
"french": "الفرنسية",
"account": "الحساب", "account": "الحساب",
"content_discovery": "المحتوى والاكتشاف", "content_discovery": "المحتوى والاكتشاف",
"appearance": "المظهر", "appearance": "المظهر",

View file

@ -578,6 +578,8 @@
"english": "English", "english": "English",
"portuguese": "Portuguese", "portuguese": "Portuguese",
"arabic": "Arabic", "arabic": "Arabic",
"spanish": "Spanish",
"french": "French",
"account": "Account", "account": "Account",
"content_discovery": "Content & Discovery", "content_discovery": "Content & Discovery",
"appearance": "Appearance", "appearance": "Appearance",

1174
src/i18n/locales/es.json Normal file

File diff suppressed because it is too large Load diff

1174
src/i18n/locales/fr.json Normal file

File diff suppressed because it is too large Load diff

View file

@ -556,6 +556,8 @@
"english": "Inglês", "english": "Inglês",
"portuguese": "Português", "portuguese": "Português",
"arabic": "Árabe", "arabic": "Árabe",
"spanish": "Espanhol",
"french": "Francês",
"account": "Conta", "account": "Conta",
"content_discovery": "Conteúdo e Descoberta", "content_discovery": "Conteúdo e Descoberta",
"appearance": "Aparência", "appearance": "Aparência",

View file

@ -1,9 +1,13 @@
import en from './locales/en.json'; import en from './locales/en.json';
import pt from './locales/pt.json'; import pt from './locales/pt.json';
import ar from './locales/ar.json'; import ar from './locales/ar.json';
import es from './locales/es.json';
import fr from './locales/fr.json';
export const resources = { export const resources = {
en: { translation: en }, en: { translation: en },
pt: { translation: pt }, pt: { translation: pt },
ar: { translation: ar }, ar: { translation: ar },
es: { translation: es },
fr: { translation: fr },
}; };

Binary file not shown.

View file

@ -12,9 +12,9 @@ import {
Platform, Platform,
Dimensions, Dimensions,
Linking, Linking,
Modal,
FlatList, FlatList,
} from 'react-native'; } from 'react-native';
import { BottomSheetModal, BottomSheetView, BottomSheetBackdrop } from '@gorhom/bottom-sheet';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { mmkvStorage } from '../services/mmkvStorage'; import { mmkvStorage } from '../services/mmkvStorage';
import { useNavigation } from '@react-navigation/native'; import { useNavigation } from '@react-navigation/native';
@ -150,7 +150,22 @@ const SettingsScreen: React.FC = () => {
]; ];
const { settings, updateSetting } = useSettings(); const { settings, updateSetting } = useSettings();
const [hasUpdateBadge, setHasUpdateBadge] = useState(false); const [hasUpdateBadge, setHasUpdateBadge] = useState(false);
const [languageModalVisible, setLanguageModalVisible] = useState(false); const languageSheetRef = useRef<BottomSheetModal>(null);
const insets = useSafeAreaInsets();
// Render backdrop for bottom sheet
const renderBackdrop = useCallback(
(props: any) => (
<BottomSheetBackdrop
{...props}
disappearsOnIndex={-1}
appearsOnIndex={0}
opacity={0.6}
/>
),
[]
);
// CustomAlert state // CustomAlert state
const [alertVisible, setAlertVisible] = useState(false); const [alertVisible, setAlertVisible] = useState(false);
const [alertTitle, setAlertTitle] = useState(''); const [alertTitle, setAlertTitle] = useState('');
@ -184,7 +199,6 @@ const SettingsScreen: React.FC = () => {
const { lastUpdate } = useCatalogContext(); const { lastUpdate } = useCatalogContext();
const { isAuthenticated, userProfile, refreshAuthStatus } = useTraktContext(); const { isAuthenticated, userProfile, refreshAuthStatus } = useTraktContext();
const { currentTheme } = useTheme(); const { currentTheme } = useTheme();
const insets = useSafeAreaInsets();
// Tablet-specific state // Tablet-specific state
const [selectedCategory, setSelectedCategory] = useState('account'); const [selectedCategory, setSelectedCategory] = useState('account');
@ -589,11 +603,13 @@ const SettingsScreen: React.FC = () => {
description={ description={
i18n.language === 'pt' ? t('settings.portuguese') : i18n.language === 'pt' ? t('settings.portuguese') :
i18n.language === 'ar' ? t('settings.arabic') : i18n.language === 'ar' ? t('settings.arabic') :
i18n.language === 'es' ? t('settings.spanish') :
i18n.language === 'fr' ? t('settings.french') :
t('settings.english') t('settings.english')
} }
icon="globe" icon="globe"
renderControl={() => <ChevronRight />} renderControl={() => <ChevronRight />}
onPress={() => setLanguageModalVisible(true)} onPress={() => languageSheetRef.current?.present()}
/> />
{(settingsConfig?.categories?.['content']?.visible !== false) && ( {(settingsConfig?.categories?.['content']?.visible !== false) && (
<SettingItem <SettingItem
@ -810,90 +826,147 @@ const SettingsScreen: React.FC = () => {
onClose={() => setAlertVisible(false)} onClose={() => setAlertVisible(false)}
/> />
<Modal <BottomSheetModal
visible={languageModalVisible} ref={languageSheetRef}
transparent={true} index={0}
animationType="fade" snapPoints={['50%']}
onRequestClose={() => setLanguageModalVisible(false)} enablePanDownToClose={true}
backdropComponent={renderBackdrop}
backgroundStyle={{
backgroundColor: currentTheme.colors.darkGray || '#0A0C0C',
borderTopLeftRadius: 16,
borderTopRightRadius: 16,
}}
handleIndicatorStyle={{
backgroundColor: currentTheme.colors.mediumGray,
width: 40,
}}
> >
<TouchableOpacity <BottomSheetView style={[styles.actionSheetContent, { paddingBottom: insets.bottom + 16 }]}>
style={styles.modalOverlay} <View style={[styles.bottomSheetHeader, { backgroundColor: currentTheme.colors.darkGray || '#0A0C0C' }]}>
activeOpacity={1} <Text style={[styles.bottomSheetTitle, { color: currentTheme.colors.white }]}>
onPress={() => setLanguageModalVisible(false)}
>
<View style={[styles.modalContent, { backgroundColor: currentTheme.colors.elevation1 }]}>
<Text style={[styles.modalTitle, { color: currentTheme.colors.highEmphasis }]}>
{t('settings.select_language')} {t('settings.select_language')}
</Text> </Text>
<TouchableOpacity onPress={() => languageSheetRef.current?.close()}>
<TouchableOpacity <Feather name="x" size={24} color={currentTheme.colors.lightGray} />
style={[
styles.languageOption,
i18n.language === 'en' && { backgroundColor: currentTheme.colors.primary + '20' }
]}
onPress={() => {
i18n.changeLanguage('en');
setLanguageModalVisible(false);
}}
>
<Text style={[
styles.languageText,
{ color: currentTheme.colors.highEmphasis },
i18n.language === 'en' && { color: currentTheme.colors.primary, fontWeight: 'bold' }
]}>
{t('settings.english')}
</Text>
{i18n.language === 'en' && (
<Feather name="check" size={20} color={currentTheme.colors.primary} />
)}
</TouchableOpacity>
<TouchableOpacity
style={[
styles.languageOption,
i18n.language === 'pt' && { backgroundColor: currentTheme.colors.primary + '20' }
]}
onPress={() => {
i18n.changeLanguage('pt');
setLanguageModalVisible(false);
}}
>
<Text style={[
styles.languageText,
{ color: currentTheme.colors.highEmphasis },
i18n.language === 'pt' && { color: currentTheme.colors.primary, fontWeight: 'bold' }
]}>
{t('settings.portuguese')}
</Text>
{i18n.language === 'pt' && (
<Feather name="check" size={20} color={currentTheme.colors.primary} />
)}
</TouchableOpacity>
<TouchableOpacity
style={[
styles.languageOption,
i18n.language === 'ar' && { backgroundColor: currentTheme.colors.primary + '20' }
]}
onPress={() => {
i18n.changeLanguage('ar');
setLanguageModalVisible(false);
}}
>
<Text style={[
styles.languageText,
{ color: currentTheme.colors.highEmphasis },
i18n.language === 'ar' && { color: currentTheme.colors.primary, fontWeight: 'bold' }
]}>
{t('settings.arabic')}
</Text>
{i18n.language === 'ar' && (
<Feather name="check" size={20} color={currentTheme.colors.primary} />
)}
</TouchableOpacity> </TouchableOpacity>
</View> </View>
</TouchableOpacity> <ScrollView
</Modal> style={{ backgroundColor: currentTheme.colors.darkGray || '#0A0C0C' }}
contentContainerStyle={styles.bottomSheetContent}
>
<TouchableOpacity
style={[
styles.languageOption,
i18n.language === 'en' && { backgroundColor: currentTheme.colors.primary + '20' }
]}
onPress={() => {
i18n.changeLanguage('en');
languageSheetRef.current?.close();
}}
>
<Text style={[
styles.languageText,
{ color: currentTheme.colors.highEmphasis },
i18n.language === 'en' && { color: currentTheme.colors.primary, fontWeight: 'bold' }
]}>
{t('settings.english')}
</Text>
{i18n.language === 'en' && (
<Feather name="check" size={20} color={currentTheme.colors.primary} />
)}
</TouchableOpacity>
<TouchableOpacity
style={[
styles.languageOption,
i18n.language === 'pt' && { backgroundColor: currentTheme.colors.primary + '20' }
]}
onPress={() => {
i18n.changeLanguage('pt');
languageSheetRef.current?.close();
}}
>
<Text style={[
styles.languageText,
{ color: currentTheme.colors.highEmphasis },
i18n.language === 'pt' && { color: currentTheme.colors.primary, fontWeight: 'bold' }
]}>
{t('settings.portuguese')}
</Text>
{i18n.language === 'pt' && (
<Feather name="check" size={20} color={currentTheme.colors.primary} />
)}
</TouchableOpacity>
<TouchableOpacity
style={[
styles.languageOption,
i18n.language === 'ar' && { backgroundColor: currentTheme.colors.primary + '20' }
]}
onPress={() => {
i18n.changeLanguage('ar');
languageSheetRef.current?.close();
}}
>
<Text style={[
styles.languageText,
{ color: currentTheme.colors.highEmphasis },
i18n.language === 'ar' && { color: currentTheme.colors.primary, fontWeight: 'bold' }
]}>
{t('settings.arabic')}
</Text>
{i18n.language === 'ar' && (
<Feather name="check" size={20} color={currentTheme.colors.primary} />
)}
</TouchableOpacity>
<TouchableOpacity
style={[
styles.languageOption,
i18n.language === 'es' && { backgroundColor: currentTheme.colors.primary + '20' }
]}
onPress={() => {
i18n.changeLanguage('es');
languageSheetRef.current?.close();
}}
>
<Text style={[
styles.languageText,
{ color: currentTheme.colors.highEmphasis },
i18n.language === 'es' && { color: currentTheme.colors.primary, fontWeight: 'bold' }
]}>
{t('settings.spanish')}
</Text>
{i18n.language === 'es' && (
<Feather name="check" size={20} color={currentTheme.colors.primary} />
)}
</TouchableOpacity>
<TouchableOpacity
style={[
styles.languageOption,
i18n.language === 'fr' && { backgroundColor: currentTheme.colors.primary + '20' }
]}
onPress={() => {
i18n.changeLanguage('fr');
languageSheetRef.current?.close();
}}
>
<Text style={[
styles.languageText,
{ color: currentTheme.colors.highEmphasis },
i18n.language === 'fr' && { color: currentTheme.colors.primary, fontWeight: 'bold' }
]}>
{t('settings.french')}
</Text>
{i18n.language === 'fr' && (
<Feather name="check" size={20} color={currentTheme.colors.primary} />
)}
</TouchableOpacity>
</ScrollView>
</BottomSheetView>
</BottomSheetModal>
</View> </View>
); );
}; };
@ -902,32 +975,26 @@ const styles = StyleSheet.create({
container: { container: {
flex: 1, flex: 1,
}, },
modalOverlay: { actionSheetContent: {
flex: 1, flex: 1,
backgroundColor: 'rgba(0,0,0,0.5)', },
justifyContent: 'center', bottomSheetHeader: {
flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
padding: 20, justifyContent: 'space-between',
paddingHorizontal: 20,
paddingVertical: 16,
borderBottomWidth: 1,
borderBottomColor: 'rgba(255,255,255,0.1)',
}, },
modalContent: { bottomSheetTitle: {
width: '100%',
maxWidth: 340,
borderRadius: 16,
padding: 20,
elevation: 5,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
},
modalTitle: {
fontSize: 18, fontSize: 18,
fontWeight: 'bold', fontWeight: '600',
marginBottom: 16, },
textAlign: 'center', bottomSheetContent: {
paddingHorizontal: 16,
paddingTop: 8,
paddingBottom: 24,
}, },
languageOption: { languageOption: {
flexDirection: 'row', flexDirection: 'row',