Multi-language Support in React Native

Jun 25, 2023 ⋅ Modified: Jul 2, 2023 ⋅ 5 min read

Bilal Arslan

Hi there! I'm a full-stack developer who loves crafting web and mobile apps. When I'm not coding, I enjoy sharing my knowledge as a technical writer. Let's build something awesome together!

Introduction

If you want to grow your application and attract users from all around the world, offering multi-language support is crucial. By catering to a wider audience, you can expand your user base significantly. In this blog post, we will cover the topic of implementing multi-language support in React Native.

Creating Project

npx create-expo-app react-native-multi-language
  • Next, navigate to the project directory:
cd react-native-multi-language

Installing Dependencies

  • i18n-js is a small library to provide the i18n translations on the JavaScript, also we can use in React Native projects too 🌍🗣️🌐
npm i i18n-js
  • We will also use React-Navigation for handling screens ✌️
npm install @react-navigation/native
npx expo install react-native-screens react-native-safe-area-context
npm install @react-navigation/native-stack

Starting the Emulator

npx expo start
  • Great! Now that our project is up and running, let's move on to the implementation.

Implementation

  • For this tutorial, we will focus on four languages that English 🇬🇧, German 🇩🇪, Italian 🇮🇹 and Turkish 🇹🇷

  • Create four language files under ./src/langs/

  • English

// ./src/langs/en.json
 
{
    "home": "Home",
    "settings": "Settings",
    "select-language": "Select Language",
    "english": "English",
    "german": "German",
    "italian": "Italian",
    "turkish": "Turkish",
    "fruits": "Fruits",
    "grapes": "Grapes",
    "watermelon": "Watermelon",
    "pear": "Pear",
    "pineapple": "Pineapple",
    "strawberry": "Strawberry",
    "peach": "Peach",
    "kiwi": "Kiwi",
    "cherries": "Cherries"
}
  • German
// ./src/langs/gr.json
 
{
    "home": "Startseite",
    "settings": "Einstellungen",
    "select-language": "Sprache auswählen",
    "english": "Englisch",
    "german": "Deutsch",
    "italian": "Italienisch",
    "turkish": "Türkisch",
    "fruits": "Obst",
    "grapes": "Trauben",
    "watermelon": "Wassermelone",
    "pear": "Birne",
    "pineapple": "Ananas",
    "strawberry": "Erdbeere",
    "peach": "Pfirsich",
    "kiwi": "Kiwi",
    "cherries": "Kirschen"
}
  • Italian
// ./src/langs/it.json
 
{
    "home": "Home",
    "settings": "Impostazioni",
    "select-language": "Seleziona Lingua",
    "english": "Inglese",
    "german": "Tedesco",
    "italian": "Italiano",
    "turkish": "Turco",
    "fruits": "Frutta",
    "grapes": "Uva",
    "watermelon": "Anguria",
    "pear": "Pera",
    "pineapple": "Ananas",
    "strawberry": "Fragola",
    "peach": "Pesca",
    "kiwi": "Kiwi",
    "cherries": "Ciliegie"
}
  • Turkish
// ./src/langs/tr.json
 
{
    "home": "Ana Sayfa",
    "settings": "Ayarlar",
    "select-language": "Dil Seçin",
    "english": "İngilizce",
    "german": "Almanca",
    "italian": "İtalyanca",
    "turkish": "Türkçe",
    "fruits": "Meyveler",
    "grapes": "Üzüm",
    "watermelon": "Karpuz",
    "pear": "Armut",
    "pineapple": "Ananas",
    "strawberry": "Çilek",
    "peach": "Şeftali",
    "kiwi": "Kivi",
    "cherries": "Kiraz"
}
  • To manage languages and language switching, we will use an AppContext
// ./src/context/AppContext.js
 
import React from 'react';
export const AppContext = React.createContext();
  • Implementing HomeScreen.jsx
// ./src/screens/HomeScreen.jsx
 
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native'
import { FontAwesome5 } from '@expo/vector-icons';
 
import { AppContext } from '../context/AppContext';
 
const HomeScreen = ({ route, navigation }) => {
 
    const { t } = React.useContext(AppContext);
 
    const fruits = [
        { id: 1, icon: '🍇', value: 'grapes', background: 'rgba(107, 67, 139, 0.2)' },
        { id: 2, icon: '🍉', value: 'watermelon', background: 'rgba(248, 49, 47, 0.2)' },
        { id: 3, icon: '🍐', value: 'pear', background: 'rgba(195, 239, 60, 0.2)' },
        { id: 4, icon: '🍍', value: 'pineapple', background: 'rgba(243, 173, 96, 0.2)' },
        { id: 5, icon: '🍓', value: 'strawberry', background: 'rgba(248, 49, 47, 0.2)' },
        { id: 6, icon: '🍑', value: 'peach', background: 'rgba(255, 130, 45, 0.2)' },
        { id: 7, icon: '🥝', value: 'kiwi', background: 'rgba(69, 224, 118, 0.2)' },
        { id: 8, icon: '🍒', value: 'cherries', background: 'rgba(246, 50, 47, 0.2)' }
    ]
 
    const navigateToSettings = () => {
        navigation.navigate('Settings')
    }
 
    return (
        <View style={{
            flex: 1,
            paddingHorizontal: 16,
            paddingVertical: 32
        }}>
 
            <View style={{
                flexDirection: 'row',
                alignItems: 'center',
                justifyContent: 'space-between'
            }}>
                <Text style={{
                    fontSize: 32,
                    fontWeight: '800'
                }}>{t('home')}</Text>
                <TouchableOpacity onPress={() => navigateToSettings()}>
                    <FontAwesome5 name='cog' size={24} color='black' />
                </TouchableOpacity>
            </View>
 
            <Text style={{ fontSize: 16, fontWeight: '600' }}>{t('fruits')}</Text>
 
            {fruits.map(item => <View
                key={item.id}
                style={{
                    backgroundColor: item.background,
                    flexDirection: 'row',
                    alignItems: 'center',
                    padding: 16,
                    borderWidth: 2,
                    marginTop: 8,
                    borderRadius: 10
                }}>
                <Text style={{ fontSize: 20 }}>{item.icon}</Text>
                <Text style={{ marginLeft: 8, fontWeight: 500 }}>{t(item.value)}</Text>
            </View>)}
        </View>
    )
};
 
export default HomeScreen;
Home Screen
  • Implementing SettingsScreen.jsx
// ./src/screens/SettingsScreen.jsx
 
import React from 'react';
import { View, Text, TouchableOpacity } from 'react-native'
import { FontAwesome5 } from '@expo/vector-icons';
 
import { AppContext } from '../context/AppContext';
 
const SettingsScreen = ({ }) => {
 
    const { t, locale, setLocale } = React.useContext(AppContext);
 
    const languages = [
        { id: 'en', value: 'english' },
        { id: 'gr', value: 'german' },
        { id: 'it', value: 'italian' },
        { id: 'tr', value: 'turkish' }]
 
    return (
        <View style={{
            flex: 1,
            paddingHorizontal: 16,
            paddingVertical: 32
        }}>
 
            <View style={{
                flexDirection: 'row',
                alignItems: 'center',
                justifyContent: 'space-between'
            }}>
                <Text style={{
                    fontSize: 32,
                    fontWeight: '800'
                }}>{t('settings')}</Text>
            </View>
 
            <Text>{t('select-language')}</Text>
 
            {languages.map(item =>
                <TouchableOpacity
                    key={item.id}
                    style={{
                        flexDirection: 'row',
                        alignItems: 'center',
                        padding: 16,
                        borderWidth: 0.8,
                        marginTop: 8,
                        borderRadius: 10
                    }}
                    onPress={() => setLocale(item.id)}>
                    <FontAwesome5 name={locale === item.id ? 'check-square' : 'square'} size={24} color='black' />
                    <Text style={{ marginLeft: 8 }}>{t(item.value)}</Text>
                </TouchableOpacity>)}
 
 
        </View>
    )
};
 
export default SettingsScreen;
Settings Screen
  • App.jsx
// ./App.js
 
import React, { useState, useMemo } from 'react';
import { StatusBar } from 'expo-status-bar';
import { SafeAreaProvider } from 'react-native-safe-area-context';
 
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
 
import HomeScreen from './src/screens/HomeScreen';
import SettingsScreen from './src/screens/SettingsScreen';
 
import { I18n } from 'i18n-js';
import en from './src/langs/en.json';
import gr from './src/langs/gr.json';
import it from './src/langs/it.json';
import tr from './src/langs/tr.json';
const i18n = new I18n({ en, gr, it, tr });
 
const Stack = createNativeStackNavigator();
 
import { AppContext } from './src/context/AppContext';
 
export default function App() {
 
  const [locale, setLocale] = useState('tr');
 
  const appContext = useMemo(() => {
    return {
      t: (scope, options) => {
        return i18n.t(scope, { locale, ...options });
      },
      locale,
      setLocale
    }
  }, [locale]);
 
  return (
    <SafeAreaProvider style={{ flex: 1 }}>
      <StatusBar />
      <NavigationContainer>
        <AppContext.Provider value={appContext}>
          <Stack.Navigator initialRouteName='Home' screenOptions={{ headerShown: false }}>
            <Stack.Screen name='Home' component={HomeScreen} />
            <Stack.Screen name='Settings' component={SettingsScreen} />
          </Stack.Navigator>
        </AppContext.Provider>
      </NavigationContainer>
    </SafeAreaProvider>
  );
}
 
  • We have imported all the languages and initialized the i18n object. The t function is responsible for handling translations. We have also shared the t function through the AppContext, making it accessible to all screens via the AppContext. The setLocale function is used to update the translation value, which can be set to en, gr, it, or tr in the code.

Project Dependencies

  "dependencies": {
    "@react-navigation/native": "^6.1.7",
    "@react-navigation/native-stack": "^6.9.13",
    "expo": "~48.0.18",
    "expo-status-bar": "~1.4.4",
    "i18n-js": "^4.2.3",
    "react": "18.2.0",
    "react-native": "0.71.8",
    "react-native-safe-area-context": "4.5.0",
    "react-native-screens": "~3.20.0"
  },

Source Code

Github Repository Link

Conclusion

  • By following the steps outlined in this blog post, you can seamlessly integrate multi-language support into your React Native applications, allowing users to interact with your app in their preferred language. Thank you for reading this guide on implementing multi-language support in React Native. We hope you found it informative and helpful for your development journey. Happy coding! 👨‍💻👩‍💻