How to add Multiple Languages to your React-native app.
Supporting multiple languages to your mobile or web application nowadays is popular and seems to become a must-have feature for some reasons:
Marketing and Advertising to get the user's attention is easier than ever before.
A local problem can be a global problem, so founders and creators don't restrict their solution to one or two areas.
Calling for investors of course it's important for them to understand what's your app does and what's the hell you're trying to resolve.
You'll make an app for your boy/girlfriend in the USA or UK, Brasil, but he/she could not understand your native language 😂
Let me introduce you to how to add multiple languages to your React-native mobile app within only 30 minutes.
Technical notes: I will mainly use AsyncStorage, Context API, HOC, react-native-localize library, and i18n-js library for this translation feature. So if you need to revise or understand more about them, please read at:
Context API: https://reactjs.org/docs/context.html
i18n-js: https://github.com/fnando/i18n-js
react-native-localize: https://github.com/zoontek/react-native-localize
For the navigation, I use react-navigation version 5. If this is new to you, please visit https://reactnavigation.org for reference.
Let's get started:
First time launching App, your Local Storage is empty, nothing in there. So, I will take the Device language as the default and save it to the Local Storage. We will do this in the file where you set up your navigation. Don't worry about the LanguageProvider or LanguageContext, we will create in the next 3 steps. For now, you just create a blank file languageProvider.js somewhere.
import React, { useEffect, useCallback, useContext, useReducer } from 'react';
import { createNativeStackNavigator } from 'react-native-screens/native-stack';
import * as RNLocalize from 'react-native-localize'
import LanguageProvider, {
LanguageContext
} from 'Path to your language provider'
const context = useContext(LanguageContext)
//Check the device language
const locales = RNLocalize.getLocales()
// We will check here
useEffect(() => {
async function onLoadLocalLanguage() {
const devLang = locales[0].languageCode
const langStore = await Storage.get('lang:languageInfoStorage')
if (!langStore) {
await Storage.set(
'lang:languageInfoStorage',
devLang
)
context.onSetLanguage(devLang)
return
}
context.onSetLanguage(langStore)
}
if (context) onLoadLocalLanguage()
}, [context])
2. Prepare your language JSON files and put them somewhere in the app folder structure. Here I give 3 files for example vi.json (Vietnamese), en.json (English), ja.json (Japanese), with sample content as follows:
vi.json:
{
"hello": "xin chào",
"article": "Bài viết",
}
en.json:
{
"hello": "Hello",
"article": "Article",
}
ja.json:
{
"hello": "こんにちは",
"article": "投稿",
}
3. Create a Storage helper file, this file contains helper functions that help us to manipulate the local data:
import AsyncStorage from '@react-native-community/async-storage'
// Save data to the local storate
async function set(key, data) {
const jsonData = JSON.stringify(data)
try {
await AsyncStorage.setItem(key, jsonData)
} catch (error) {
/* Alert error */
console.log('set data error', error)
}
}
// Get data from local storate
async function get(key) {
try {
const jsonData = await AsyncStorage.getItem(key)
return JSON.parse(jsonData)
} catch (error) {
/* Alert error */
console.log('get data error', error)
}
}
// Remove data from local storate with key
async function remove(key) {
try {
await AsyncStorage.removeItem(key)
return true
} catch (error) {
console.log('remove data error', error)
}
}
// Delete all the local data
function clear() {
AsyncStorage.clear()
}
export default {
set,
get,
remove,
clear,
}
4. Create the LanguageProvider Context
import React from 'react'
import { Storage } from 'Path to your Storage utils'
export const LanguageContext = React.createContext({})
const LanguageProvider = ({ children }) => {
const [language, setLanguage] = React.useState('vi')
React.useEffect(() => {
// this will check the Storage for the default language
const onLocalLoad = async () => {
const lang = await Storage.get('lang:languageInfoStorage')
setLanguage(lang)
}
onLocalLoad()
}, [])
const onSetLanguage = React.useCallback(
value => {
setLanguage(value)
},
[language]
)
const store = {
language,
onSetLanguage
}
return (
<LanguageContext.Provider value={store}>
{children}
</LanguageContext.Provider>
)
}
export default LanguageProvider
5. Create the withTranslation HOC
import React from 'react'
import i18n from 'i18n-js'
import en from '../../app/language/en.json'
import vi from '../../app/language/vi.json'
import ja from '../../app/language/ja.json'
import { LanguageContext } from 'path to your language provider'
const withTranslation = () => Component => {
function Translation(childProps) {
const { language } = React.useContext(LanguageContext)
const onLoadLocalization = React.useCallback(() => {
i18n.defaultLocale = language
i18n.locale = i18n.defaultLocale = language
i18n.fallbacks = true
i18n.missingBehaviour = 'guess'
i18n.translations = { en, vi, ja }
}, [language])
React.useEffect(() => onLoadLocalization(), [language])
const translate = React.useCallback(
key => {
if (key) {
return i18n.t(key, { locale: language })
}
return ''
},
[language]
)
return <Component {...childProps} translate={translate} />
}
return Translation
}
export default withTranslation()
6. Wrap the whole navigation with the LanguageProvider like this:
<LanguageProvider>
<AppStack.Navigator screenOptions={{...}}/>
<AppStack.Screen name='BottomNav' component={BottomNavigator} />
</AppStack.Navigator>
</LanguageProvider>
7. It's done for setup. In your component, you wrap the component with the withTranslation HOC.
import React from 'react'
import { Header } from 'components'
import { withTranslation } from 'path to your withTranslation HOC'
import { Wrapper, Text } from './styled'
function Contribute(props) {
const { translate } = props
return (
<Wrapper>
<Header title={translate('hello')} back icon />
<Text>Hello from Heaven</Text>
</Wrapper>
)
}
export default withTranslation(Contribute)
8 Okay, so, how to switch between 3 languages? It's easy, in your Language Setting screen:
8.1. you wrap it with the withTranslation HOC like this:
export default withTranslation(LanguageSetting)
8.2. Then, in your function to choose each language, you set your preferred language and set it to the local storage:
import { Storage } from 'path to your Storage helpers'
import { LanguageContext } from 'path to your language provider'
const { language, onSetLanguage } = React.useContext(LanguageContext)
async function setStoreLang(prefLang) {
await Storage.set(
'lang:languageInfoStorage',
prefLang
)
}
function onSetLang(lang) {
if (onSetLanguage) onSetLanguage(lang)
setStoreLang(lang)
}
YOU MADE IT!
I have to say, there are many ways to make multiple languages feature for your React-native app. You can practice, choose the best or invent your own.
If you have any questions, please leave a comment or email me.
Commentaires