Implement multilingual support by integrating i18n for dynamic text rendering across the app. Added language selection modal in HomeScreen and updated various components to utilize localized strings. Updated package dependencies for async storage and localization.

This commit is contained in:
2025-08-16 22:24:47 +05:00
parent 0f8c9b5e55
commit e431c42df1
13 changed files with 460 additions and 38 deletions

View File

@@ -1,31 +1,82 @@
import { StyleSheet, SafeAreaView, ScrollView } from 'react-native';
import { StyleSheet, SafeAreaView, ScrollView, I18nManager, Modal, Pressable } from 'react-native';
import { Text, View } from '@/components/Themed';
import FeatureCard from '@/components/FeatureCard';
import PrayerTimeCard from '@/components/PrayerTimeCard';
import ServicesGrid from '@/components/ServicesGrid';
import i18n from '@/i18n';
import * as Updates from 'expo-updates';
import AsyncStorage from '@react-native-async-storage/async-storage';
import Colors from '@/constants/Colors';
import { useState } from 'react';
export default function HomeScreen() {
const [modalVisible, setModalVisible] = useState(false);
const changeLanguage = async (lang: 'en' | 'tk' | 'ru') => {
if (!lang) return;
setModalVisible(false);
if (lang === i18n.locale.substring(0, 2)) return;
await AsyncStorage.setItem('user-language', lang);
i18n.locale = lang;
I18nManager.forceRTL(false); // Assuming LTR for all three languages
Updates.reloadAsync();
};
const languages = [
{ label: 'English', value: 'en' },
{ label: 'Türkmen', value: 'tk' },
{ label: 'Русский', value: 'ru' },
];
const currentLanguage = languages.find(l => l.value === i18n.locale.substring(0, 2))?.label;
return (
<SafeAreaView style={styles.container}>
<View style={styles.header}>
<Text style={styles.title}>{i18n.t('home')}</Text>
<Pressable onPress={() => setModalVisible(true)} style={pickerSelectStyles.inputIOS}>
<Text style={{ color: 'white' }}>{currentLanguage}</Text>
</Pressable>
</View>
<Modal
animationType="slide"
transparent={true}
visible={modalVisible}
onRequestClose={() => {
setModalVisible(!modalVisible);
}}>
<Pressable style={styles.modalOverlay} onPress={() => setModalVisible(false)}>
<View style={styles.modalView}>
{languages.map((lang) => (
<Pressable
key={lang.value}
style={styles.modalButton}
onPress={() => changeLanguage(lang.value as 'en' | 'tk' | 'ru')}>
<Text style={styles.modalButtonText}>{lang.label}</Text>
</Pressable>
))}
</View>
</Pressable>
</Modal>
<ScrollView>
<View style={styles.innerContainer}>
<Text style={styles.title}>Home</Text>
<FeatureCard
isNew
title="Your Journey to Hajj"
description="Everything you need for Hajj essentials."
title={i18n.t('yourJourneyToHajj')}
description={i18n.t('hajjEssentials')}
/>
<View style={styles.cardRow}>
<View style={{ flex: 1, marginRight: 10 }}>
<FeatureCard
title="Umrah"
description="Book Permit"
title={i18n.t('umrah')}
description={i18n.t('bookPermit')}
/>
</View>
<View style={{ flex: 1, marginLeft: 10 }}>
<FeatureCard
title="Noble Rawdah"
description="Book Permit"
title={i18n.t('nobleRawdah')}
description={i18n.t('bookPermit')}
/>
</View>
</View>
@@ -44,13 +95,81 @@ const styles = StyleSheet.create({
innerContainer: {
paddingHorizontal: 15,
},
header: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 15,
},
title: {
fontSize: 22,
fontWeight: 'bold',
marginVertical: 15,
},
langSwitcher: {
flexDirection: 'row',
},
langText: {
color: '#fff',
paddingHorizontal: 5,
fontWeight: 'bold',
},
cardRow: {
flexDirection: 'row',
justifyContent: 'space-between',
},
modalOverlay: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'rgba(0,0,0,0.5)',
},
modalView: {
margin: 20,
backgroundColor: Colors.dark.secondary,
borderRadius: 20,
padding: 35,
alignItems: 'center',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 4,
elevation: 5,
},
modalButton: {
padding: 10,
borderBottomWidth: 1,
borderBottomColor: '#333',
width: '100%',
},
modalButtonText: {
color: 'white',
textAlign: 'center',
},
});
const pickerSelectStyles = StyleSheet.create({
inputIOS: {
fontSize: 16,
paddingVertical: 12,
paddingHorizontal: 10,
borderWidth: 1,
borderColor: Colors.dark.secondary,
borderRadius: 4,
color: 'white',
paddingRight: 30, // to ensure the text is never behind the icon
},
inputAndroid: {
fontSize: 16,
paddingHorizontal: 10,
paddingVertical: 8,
borderWidth: 0.5,
borderColor: Colors.dark.secondary,
borderRadius: 8,
color: 'white',
paddingRight: 30, // to ensure the text is never behind the icon
},
});