DEV Community

Cover image for i18n internationalization in React Native
Luiz Gabriel
Luiz Gabriel

Posted on

i18n internationalization in React Native

Introduction

In a world where there are millions of application users, we need to understand that this goes beyond the code. By necessity we have to prepare our application to receive people from different countries and different languages and to do this we will use internationalization(i18n)

What is internationalization(i18n)?

The application of internationalization will help us to adapt our app to different languages, making it easy and avoiding many unnecessary changes or checks in our code.

The adapted elements will be texts and the lib we will use is: react-i18next

Implementation

  • install lib
yarn add i18next react-i18next
Enter fullscreen mode Exit fullscreen mode
  • Create the files with the custom texts: create a folder with the languages and create the respective languages, we will use the following languages -> pt, en, es
  • Create a json for each language with all the texts
{
    "translation": {
        "name": "Nome",
        "welcome": "Seja Bem-Vindo",
        "choose": "Selecione um idioma",
        "portuguese": "Português",
        "english": "Inglês",
        "spanish": "Espanhol"
    }
}
Enter fullscreen mode Exit fullscreen mode
{
    "translation": {
        "name": "Nombre",
        "welcome": "Bienvenido",
        "choose": "Seleccione un idioma",
        "portuguese": "Portugués",
        "english": "Inglés",
        "spanish": "Español"
    }
}
Enter fullscreen mode Exit fullscreen mode
{
    "translation": {
        "name": "Name",
        "welcome": "Welcome",
        "choose": "Select a language",
        "portuguese": "Portuguese",
        "english": "English",
        "spanish": "Spanish"
    }
}
Enter fullscreen mode Exit fullscreen mode
  • now that we have the json and the texts all assigned, we need to do the configuration:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

// importing languages
import PtBR from "./languages/pt.json"
import EN from "./languages/en.json"
import ES from "./languages/es.json"

// Here are the languages used and the contents of each one
const resources = {
    pt: PtBR,
    en: EN,
    es: ES
};

// in this snippet is being initialized so we can use the lib 
i18n
  .use(initReactI18next)
  .init({
    compatibilityJSON: 'v3',
    // language resources
    resources,
    // here is the language you will use by default
    lng: 'pt',
  });

export default i18n;
Enter fullscreen mode Exit fullscreen mode

Defining a language through a select

screen with dropdown

  • We will use the lib react-native-dropdown-picker to implement the dropdown, below is the implemented code
import { StatusBar } from 'expo-status-bar';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, Text, View } from 'react-native';
import DropDownPicker from 'react-native-dropdown-picker';
import i18n from './internacionalization/i18n';

export default function App() {
// it is important to use the hook useTranslation(), it already updates the texts
// as soon as the user makes a change
  const { t } = useTranslation();
  const [open, setOpen] = useState(false);
  const [value, setValue] = useState(null);
  const [items, setItems] = useState([
    { label: t('portuguese'), value: 'pt' },
    { label: t('english'), value: 'en' },
    { label: t('spanish'), value: 'es' },
  ]);

  return (
    <View style={styles.container}>
      <Text style={styles.greeting}>{t('welcome')}</Text>
      <Text style={styles.name}>{`${t('name')} Luiz Gabriel`}</Text>
      <View style={styles.dropDown}>
        <DropDownPicker
          open={open}
          value={value}
          items={items}
          setOpen={setOpen}
          setValue={setValue}
          onChangeValue={(value) => {
            // this function changes the language on the i18n
            i18n.changeLanguage(value);
          }}
          setItems={setItems}
          placeholder={t('choose')}
        />
      </View>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  dropDown: {
    marginTop: 20,
    paddingHorizontal: 40,
  },
  greeting: {
    fontSize: 30,
    fontWeight: 'bold',
  },
  name: {
    fontSize: 20,
  },
});
Enter fullscreen mode Exit fullscreen mode

Defining language by user location

  • before getting the location you need to ask the user for permission
  • We will use the lib expo-location
  • install the library
npx expo install expo-location
Enter fullscreen mode Exit fullscreen mode
  • config your app.json
{
  "expo": {
    "plugins": [
      [
        "expo-location",
        {
          "locationAlwaysAndWhenInUsePermission": "Allow $(PRODUCT_NAME) to use your location.",
          "locationAlwaysPermission": "Allow $(PRODUCT_NAME) to use your location",
          "locationWhenInUsePermission": "Allow $(PRODUCT_NAME) to use your location"
        }
      ]
    ]
  }
}
Enter fullscreen mode Exit fullscreen mode
  • solution below
import { StatusBar } from 'expo-status-bar';
import React, { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, Text, View } from 'react-native';

import i18n from './internacionalization/i18n';

import * as Location from 'expo-location';

export default function App() {
  const { t } = useTranslation();

  const setLanguageByLocation = async (latitude, longitude) => {
    try {
      // geocoding a location to a postal address      
const geocode = await Location.reverseGeocodeAsync({ latitude, longitude });
      // return country code
      const country = geocode[0]?.isoCountryCode;
      const countryToLanguage = {
        BR: 'pt',
        US: 'en',
        ES: 'es',
      };

      const language = countryToLanguage[country] || 'pt'; 
      // change the language
      i18n.changeLanguage(language);
    } catch (error) {
      console.error("Erro ao definir idioma pela localização", error);
    }
  };

  useEffect(() => {
    (async () => {
      // get permission to get location
      let { status } = await Location.requestForegroundPermissionsAsync();
      if (status !== 'granted') {
        console.log('Permissão para acessar a localização foi negada');
        return;
      }

      // get current location
      let location = await Location.getCurrentPositionAsync({});
      setLanguageByLocation(location.coords.latitude, location.coords.longitude)
    })();
  }, []);

  return (
    <View style={styles.container}>
      <Text style={styles.greeting}>{t('welcome')}</Text>
      <Text style={styles.name}>{`${t('name')} Luiz Gabriel`}</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  greeting: {
    fontSize: 30,
    fontWeight: 'bold',
  },
  name: {
    fontSize: 20,
  },
});
Enter fullscreen mode Exit fullscreen mode

Setting language by device language

  • we will use the lib expo-localization, I chose this lib because it provides access to locale data on the native device and under the hood uses libs like react-i18next
  • install lib
npx expo install expo-localization
Enter fullscreen mode Exit fullscreen mode
  • config json
{
  "expo": {
    "plugins": ["expo-localization"]
  }
}
Enter fullscreen mode Exit fullscreen mode
  • solution above
import { StatusBar } from 'expo-status-bar';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { StyleSheet, Text, View } from 'react-native';
import * as Localization from "expo-localization";

import i18n from './internacionalization/i18n';

export default function App() {
  const { t } = useTranslation();

  useEffect(() => {
    // get the current language of the device
    const langCode = Localization.getLocales()[0].languageCode;
    // if language is null, set language to default value
    const language = langCode || 'pt';
    // change language
    i18n.changeLanguage(language);
  }, []);

  return (
    <View style={styles.container}>
      <Text style={styles.greeting}>{t('welcome')}</Text>
      <Text style={styles.name}>{`${t('name')} Luiz Gabriel`}</Text>
      <StatusBar style="auto" />
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
  greeting: {
    fontSize: 30,
    fontWeight: 'bold',
  },
  name: {
    fontSize: 20,
  },
});
Enter fullscreen mode Exit fullscreen mode

  • Explaining what i18n is
  • Setting the language manually
  • Setting the language by user location
  • Set app language according to device language

Linkedin: Luiz Gabriel Rebelatto Bianchi
Github: Luizrebelatto

Top comments (0)