Add i18next integration

feature/app-setup
vinay kumar 2025-06-28 09:57:23 +05:30
parent 363b88fd92
commit 48877cbf0f
6 changed files with 86 additions and 24 deletions

View File

@ -1,11 +1,11 @@
import React from 'react';
import FontAwesome from '@expo/vector-icons/FontAwesome';
import { Link, Tabs } from 'expo-router';
import { Pressable } from 'react-native';
import Colors from '@/constants/Colors';
import { useColorScheme } from '@/components/useColorScheme';
import { useClientOnlyValue } from '@/components/useClientOnlyValue';
import React from "react";
import FontAwesome from "@expo/vector-icons/FontAwesome";
import { Link, Tabs } from "expo-router";
import { Pressable } from "react-native";
import Colors from "@/constants/Colors";
import { useColorScheme } from "@/components/useColorScheme";
import { useClientOnlyValue } from "@/components/useClientOnlyValue";
import { TAB_CONFIG } from "@/constants/config";
// You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/
function TabBarIcon(props: {
@ -21,9 +21,7 @@ export default function TabLayout() {
return (
<Tabs
screenOptions={{
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
// Disable the static render of the header on web
// to prevent a hydration error in React Navigation v6.
tabBarActiveTintColor: Colors[colorScheme ?? "light"].tint,
headerShown: useClientOnlyValue(false, true),
}}>
<Tabs.Screen

View File

@ -1,21 +1,27 @@
import FontAwesome from '@expo/vector-icons/FontAwesome';
import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
import { useFonts } from 'expo-font';
import { Stack } from 'expo-router';
import * as SplashScreen from 'expo-splash-screen';
import { useEffect } from 'react';
import 'react-native-reanimated';
import i18next, { getLanguage } from "../services/i18n/index";
import FontAwesome from "@expo/vector-icons/FontAwesome";
import {
DarkTheme,
DefaultTheme,
ThemeProvider,
} from "@react-navigation/native";
import { useFonts } from "expo-font";
import { Stack, useRouter } from "expo-router";
import * as SplashScreen from "expo-splash-screen";
import { useEffect, useState } from "react";
import "react-native-reanimated";
import { I18nextProvider } from "react-i18next"; //I18nextProvider
import { useColorScheme } from '@/components/useColorScheme';
import { useColorScheme } from "@/components/useColorScheme";
export {
// Catch any errors thrown by the Layout component.
ErrorBoundary,
} from 'expo-router';
} from "expo-router";
export const unstable_settings = {
// Ensure that reloading on `/modal` keeps a back button present.
initialRouteName: '(tabs)',
initialRouteName: "(tabs)",
};
// Prevent the splash screen from auto-hiding before asset loading is complete.
@ -23,7 +29,7 @@ SplashScreen.preventAutoHideAsync();
export default function RootLayout() {
const [loaded, error] = useFonts({
SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
...FontAwesome.font,
});
@ -49,11 +55,13 @@ function RootLayoutNav() {
const colorScheme = useColorScheme();
return (
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<I18nextProvider i18n={i18next}>
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
<Stack>
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="modal" options={{ presentation: 'modal' }} />
<Stack.Screen name="modal" options={{ presentation: "modal" }} />
</Stack>
</ThemeProvider>
</I18nextProvider>
);
}

40
services/i18n/index.ts Normal file
View File

@ -0,0 +1,40 @@
import i18next from "i18next";
import { initReactI18next } from "react-i18next";
import en from "../i18n/locals/en.json";
import hi from "../i18n/locals/hi.json";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { STORAGE_KEYS } from "../../constants/config";
export const languageResources = {
en: { translation: en },
hi: { translation: hi },
};
i18next.use(initReactI18next).init({
compatibilityJSON: "v4",
lng: "hi",
fallbackLng: "en",
resources: languageResources,
debug: true,
});
i18next.on("initialized", () => {
console.log("✅ i18next initialized with language:", i18next.language);
console.log("Translation test (welcome):", i18next.t("welcome"));
});
export const setLanguage = async (language: string) => {
await AsyncStorage.setItem(STORAGE_KEYS.LANGUAGE, language);
i18next.changeLanguage(language);
};
export const getLanguage = async () => {
const lang = await AsyncStorage.getItem(STORAGE_KEYS.LANGUAGE);
if (lang) {
i18next.changeLanguage(lang);
}
return lang;
};
export default i18next;

View File

@ -0,0 +1,8 @@
{
"en": {
"name": "English"
},
"hi": {
"name": "हिंदी"
}
}

View File

@ -0,0 +1,4 @@
{
"change-language": "Change language",
"welcome": "Welcome to Driver Saathi"
}

View File

@ -0,0 +1,4 @@
{
"change-language": "भाषा बदलें",
"welcome": "ड्राइवर साथी में आपका स्वागत है"
}