loading...

Quick translation setup with React

damcosset profile image Damien Cosset ・4 min read

Introduction

As part of my InvoiceMaker application development, I wanted to have a French version of the software. There are a lot of librairies/frameworks available to handle translations in a React application. I figured I don't really need to add more packages to take care of this, and could just code something simple myself. So, here it is!

What I wanted

I wanted something very simple. I would take a look at the user's browser language. If that language was French (fr-FR or fr specifically), I would set the language of my application to French. Else, it would be in English.

I know there are different flavors of French, but for now, handling French from France was just what I needed.

How?

First, let's create a react application. We won't need much of it, I'll just show how to get started simply. We'll use create-react-app:

Run: create-react-app translations-setup

Let's now move into your newly created directory and run npm start.

Get the current language

First, we need to know which language the user's browser is using. Modify App.js to add the following code:

import React from 'react'
import logo from './logo.svg'
import './App.css'
let frenchCodes = ['fr-FR', 'fr-fr', 'fr']
let language = navigator.language || navigator.userLanguage
if (!frenchCodes.includes(language)) {
    language = 'en-US'
}
// App component below...

Here, we define which language we are going to use. We use the language property on the window.navigator object.

I've put the french codes inside an array. Some navigators might return it in lowercase ( I believe some versions of Safari do that ).

Then, if the language is not included inside that array, I know it's not the user's browser is not in French. Therefore, I set the language to US english.

JSON files for translations

Next, we will create the files where the translations will be stored. Create a folder inside the src folder called i18n. Inside that folder, create two JSON files, en-US.json and fr-FR.json, and a js file called index.js.

The JSON files will hold the translations for their respective languages:

  • fr-FR.json
{
    "appTitle": "Modifiez src/App.js et sauvegarder pour recharger.",
    "appLink": "Apprenez React",
    "newPageTitle": "Nouvelle Page",
    "english": "Anglais",
    "french": "Français"
}
  • en-US.json
{
    "appTitle": "Edit src/App.js and save to reload.",
    "appLink": "Learn React",
    "newPageTitle": "New Page",
    "english": "English",
    "french": "French"
}

The keys' names are completely arbitrary. Call them whatever you like, as long as they make sense to you, because this is what we'll be using in our application.

Finally, we will import the translations files inside a unique index.js file:

import fr_FR from './fr-FR.json'
import en_US from './en-US.json'
const translations = {
    'fr-FR': fr_FR,
    'en-US': en_US
}

export default translations

Great, our translations are now accessible from a single file.

Context

Now, we need to put it all together. We will need to access the current language in all parts of our application. To do this, we'll use Context.

First, let's create our Context. Create a new LanguageContext.js file, and copy the following code inside:

import React from 'react'

const LanguageContext = React.createContext()

export default LanguageContext

Next, we will wrap the App component inside the Context provider and set a state to hold the language we are using. This state will be passed to the context provider to be used throughout our application. I will also add two buttons to change the current language of our application easily. Your App.js file should look like this:

import React, { useState } from 'react'
import logo from './logo.svg'
import './App.css'
import NewComponent from './NewComponent'
import translations from './i18n/'
import LanguageContext from './LanguageContext'
let frenchCodes = ['fr-FR', 'fr-fr', 'fr']
let language = navigator.language || navigator.userLanguage
if (!frenchCodes.includes(language)) {
    language = 'en-US'
}

function App() {
    const [lng, setLng] = useState(language)
    return (
        <LanguageContext.Provider value={lng}>
            <div className='App'>
                <header className='App-header'>
                    <img src={logo} className='App-logo' alt='logo' />
                    <p>{translations[lng]['appTitle']}</p>
                    <a
                        className='App-link'
                        href='https://reactjs.org'
                        target='_blank'
                        rel='noopener noreferrer'>
                        {translations[lng]['appLink']}
                    </a>
                    <NewComponent />
                    <button onClick={() => setLng('fr-FR')}>
                        {translations[lng]['french']}
                    </button>
                    <button onClick={() => setLng('en-US')}>
                        {translations[lng]['english']}
                    </button>
                </header>
            </div>
        </LanguageContext.Provider>
    )
}

export default App

To use our translations here, we import the translations from the i18n/index.js. Then, to get the current language, we use the lng variable, stored in the state and used as a value in our context. So, translations[lng] will give us the translations of the current language. Then, we add the key we desire to get the appropriate value.

You may have noticed that there is a new component in our App. I've added the NewComponent component, and this one uses the useContext hook to get the proper translations:

import React, { useContext } from 'react'
import LanguageContext from './LanguageContext'
import translations from './i18n'

const NewComponent = function() {
    const lng = useContext(LanguageContext)
    return (
        <div>
            <h1>{translations[lng]['newPageTitle']}</h1>
        </div>
    )
}

export default NewComponent

You'll need to import the LanguageContext and your translations file. By giving useContext the LanguageContext, you will be able to have the current language used in your application everywhere you want.

And there you have a simple and quick way to take care of translations without adding any new packages or librairies to your project.😉

You may find the code on Github.

Have fun ❤️

Posted on Dec 12 '17 by:

damcosset profile

Damien Cosset

@damcosset

French web developer mostly interested in Javascript and JAVA

Discussion

markdown guide