How to Easily Implement React Native Localization in 2024

Featured 2, React-Native

By leveraging React native localization, you can build mobile applications supporting multiple locales. With this tool in your toolkit, you can scale your apps globally, ensuring your users enjoy personalized experiences.

In this article, we will develop a simple react-native application with multi-lingual support using the react-i18next framework. It’s a powerful internationalization framework for React/React Native based on i18nextIf you don’t want to set up the project yourself, you can find the full one in our GitHub repository and clone it—it’s as easy as pie.

Prerequisites

This article assumes that you have:

  1. Knowledge of React.
  2. Node.js and npm are installed on your computer.

Why React-18Next?

Extensibility: Compared to other i18n frameworks, i18next is extensible and can be used in any Javascript environment (and a few non-Javascript – .net, elm, iOS, Android), with any UI framework, and with any i18n format.

The React native localization project structure

The final project should look like the picture below:

1. Installing Expo

The first step in our React native localization project is to use Expo to build our app. But first, we need to install expo-cliIt’s the primary interface between a developer and other Expo tools used for different tasks throughout the project development cycle.

📌

To use the expocli you will need these requirements.

Include the following lines:

  npm install --global expo-cli && npx create-expo-app l10n-app
This will create an Expo project called ‘l10n-app’

2. Initialize react-i18next

In your project root directory, install the react-i18next package.
npm install react-i18next i18next --save
 Next, install Expo-localization to get access to the locale data of the native device.
 npx expo install expo-localization
 Create an i18n.js file in your project’s root directory and write the code below.

				
					import i18n from 'i18next';
import * as Localization from 'expo-localization';
import {initReactI18next} from "react-i18next";

// creating a language detection plugin using expo
// http://i18next.com/docs/ownplugin/#languagedetector

const languageDetector = {
    type: 'languageDetector',
    async: true, // async detection
    detect: (callback) => {
        // We will get back a string like "en-UK".
        callback(Localization.locale);

    },

    init: () => {
    },

    cacheUserLanguage: () => {
    },
};


i18n
    .use(initReactI18next) // passes i18n down to react-i18next
    .use(languageDetector)
    .init({
        fallbackLng: 'en-US',
        compatibilityJSON: 'v3',
        // the translations

        resources: {
            'en-US': {
                translation: {
                    home_title_1: "Meeting scheduling",
                    home_title_2: "made easy",
                    header_title_home: 'Home',
                    header_title_lang: 'Change Language',
                    home_button_text: 'Change Language',
                    home_body: "Never miss a meeting. Never be late for one too. Keep track of your meetings and receive smart reminders in appropriate times. Read your smart “Daily Agenda” every morning.",


                }
            },
            'zh-CN': {
                translation: {
                    home_title_1: "会议安排",
                    home_title_2: "变得容易",
                    header_title_home: '主页',
                    header_title_lang: '改变语言',
                    home_button_text: '改变语言',
                    home_body: "永远不要错过会议。也不要迟到。跟踪您的会议并在适当的时间收到智能提醒。每天早上阅读您的智能“每日议程”。",

                }
            },
            // have a initial namespace
            ns: ['translation'],
            supportedLngs: [  // Supported languages
                {
                    code: 'en',
                    locale: 'English'
                }, {
                    code: 'zh-CN',
                    locale: 'Chinese (Simplified)'
                }
            ],
            defaultNS: 'translation',
            interpolation: {
                escapeValue: false // not needed for react
            }
        }
    })
export default i18n;
				
			
  l18n.js file

🔔

In production, it is better to put the translations in separate .json files and import them.
  Read the react18next documentation if you want to learn more about the above code.

3. Navigation.

We are going to add navigation to our app so that we can navigate to different screens.
				
					npm install @react-navigation/native
				
			
Run this in your project directory to add react-navigation dependencies.

				
					npx expo install react-native-screens react-native-safe-area-context
				
			
  Finally, we need to install @react-navigation/native-stack

				
					npm install @react-navigation/native-stack
				
			
After that create a navigation directory, then create a Navigation.js file in it. Finally include the code below in the file:
				
					import Home from "../screens/Home";
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';
import Languages from "../screens/Languages";
import {useTranslation} from "react-i18next";

const Stack = createNativeStackNavigator();


export default function Navigation() {
    const {t} = useTranslation()


    return (

        <NavigationContainer>
            <Stack.Navigator initialRouteName="Home">
                <Stack.Screen name="Home"
                              options={{title: t('header_title_home')}}
                              component={Home}/>
                <Stack.Screen name="Languages"
                              options={{title: t('header_title_lang')}}
                              component={Languages}/>
            </Stack.Navigator>
        </NavigationContainer>
    );
}
				
			
 createNativeStackNavigator is a function that returns an object containing 2 properties: Screen and Navigator. Both of them are React components used to configure the navigator.
Wrap the Stack component inside the NavigationContainer to manage our navigation tree.
  • Component prop: accepts a component.
  • Options: accepts navigator options such as the title to render.
  • Name: corresponds to the name of the route we will use to navigate.

🔔

Since we also want to translate the header title, we need to pass the text to the t function.


Wrap your Navigation component with I18nextProvider to pass down the i18next instance to the children components.
				
					import {I18nextProvider} from "react-i18next";
import i18n from "./i18n";
import Navigation from "./navigation/Navigation";
import {SafeAreaProvider} from "react-native-safe-area-context";

export default function App() {
    return (
        <I18nextProvider i18n={i18n}>
            <SafeAreaProvider>
                <Navigation/>
            </SafeAreaProvider>
        </I18nextProvider>
    );
}
				
			
To learn more about the above code, feel free to read the react18next documentation.

4. Home screen

Create a screens directory in your project’s root directory and create a Home.js file in the screens directory.
  We are going to use the useTranslation hook to get the t function in our functional component. The t function is used to translate content in your app.
  Pass all the translatable strings inside the t function as arguments.
				
					import {Button, StyleSheet, Text, View} from 'react-native';
import {useTranslation} from "react-i18next";


export default function Home({navigation}) {
    const {t} = useTranslation()


    return (

        <View style={styles.container}>
            <Text style={{...styles.text, color: '#fff'}}>
                {t('home_title_1')}
            </Text>
            <Text style={{...styles.text, color: '#f97316'}}>
                {t('home_title_2')}
            </Text>
            <Text style={{...styles.body, color: '#fff'}}>
                {t('home_body')}
            </Text>
            <Button color={'#f97316'} title={t('home_button_text')} onPress={() => navigation.navigate('Languages')}/>
        </View>

    );
}
const styles = StyleSheet.create({
    container: {
        flex: 1, backgroundColor: '#1f2937', alignItems: 'center',
        justifyContent: 'center', padding: '5%'

    }, text: {
        fontSize: 30, fontWeight: 'bold', padding: '4%'
    }, body: {
        fontSize: 14, fontWeight: 'normal', marginBottom: '20%'
    }
});
				
			

Here is how the React native localization project should look like:

5. Language screen

Now create a Languages.js file in the screens directory and add this code to it. We are going to use this screen to list all supported languages and switch between languages.
				
					import {FlatList, StyleSheet, Text, TouchableOpacity, View} from 'react-native';
import {useTranslation} from "react-i18next";


export default function Languages() {
    const {i18n} = useTranslation()
    // Supported Languages List
    const {supportedLngs} = i18n.services.resourceStore.data

    return (

        <View style={styles.container}>
            <FlatList data={supportedLngs} renderItem={({item}) => (

                <TouchableOpacity onPress={() => i18n.changeLanguage(item.code)} style={styles.listItem}>
                    <Text>{item.locale}</Text>
                </TouchableOpacity>
                
            )}/>
        </View>

    );
}
const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#fff',

    },

    listItem: {
        padding: '4%',
        flex: 1,
        width: '100%',
        borderBottomWidth: 1,

    }
});
				
			
  Remember, we passed a list of objects containing the supported languages. This is where we use it to list all the supported languages/locales. Pass the array in the data prop in the FlatList component and a component to the renderItem prop.

How to Easily Localize React-Native Apps in 2023
How to Easily Implement React Native Localization in 2024

6. Results

At this point, the app is able to support multiple locales and switch between them.
Translated Copy - How to Easily Implement React Native Localization in 2024
Translated UI
Full UI sequence- React-Native Localization

7. Interpolation

Interpolation allows the integration of dynamic values into your translations. To demonstrate this, add this key to the English translation.
				
					launch_date: '{{count}} day left to launch',
				
			
On the front end, add this line to the home screen page.

				
					<Text style={{...styles.body, color: '#fff',padding :'0%'}}>
    {t('launch_date', {count:1})}
</Text>
				
			
Keys, by default, are strings surrounded by curly brackets, i.e., count. The dynamic value is 1 for the count key.

Updated Home Screen

8. Pluralization

Now that we have passed dynamic data inside our strings, we need to consider pluralization. Suppose our count was 2 or more. Do you see the problem now? How would we handle that? If we don’t take it into account, it will display 2 day left to launch.
Add the key below, which is the plural form of the launch_date key. Now if your count is greater than one, it’ll take the plural form.
				
					launch_date_plural: '{{count}} days left to launch',
				
			
Pluralization of the launch_date key.

9. Adding more locales

For an app already in production, it is better to load translations through a backend service (Starling, Lokalize, etc.). In this way, when translations are published, they readily become available for use in the app without having to go back to the code.
Furthermore, considering the scale and depth of the necessary potential changes, we encourage you to partner with battle-tested professionals. Alternatively, feel free to leave us any questions related to react native localization. We’d be happy to oblige.