Create a Multi-Language Website with React Context API

Halil Can Ozcelik
3 min readNov 8, 2019

--

In this article, I will try to explain my approach to develop a multi-language website with React Context API. If you are used to reading code better than words, you can examine the example project from this Github repository.

And here is the live POC of the project. (This link exists on the Github Repo too)

First, I strongly suggest taking a glance at the React Context API and useContext Hook documents from the official React website.

And here we go! This is the folder structure of the project:

Texts are stored as JSON for each language. You can see the example for English below:

{  "exploreHeader": "Explore",  "welcomeDescription": "This is a demo app for multi-language website with React Context API",  "clickMe": "Click Me",  "aboutMe": "For more info about the author",  "buttonClicked": "You clicked to button!"}

All of them are stored in a dictionary object and it will be shown according to the selected language which I will explain later in this article.

import tr from './tr.json';import en from './en.json';import de from './de.json';
export const dictionaryList = { en, tr, de };export const languageOptions = { en: 'English', tr: 'Türkçe', de: 'Deutsch'};

The language selector is filled by languageOptions. Users can change the language of the website from there.

I will create a context that contains the selected language and dictionary.

import { languageOptions, dictionaryList } from '../languages';// create the language context with default selected languageexport const LanguageContext = createContext({  userLanguage: 'en',  dictionary: dictionaryList.en});

Then define the Context Provider. We can set the selected language and get related texts from the dictionary by this context provider.

// it provides the language context to appexport function LanguageProvider({ children }) {  const [userLanguage, setUserLanguage] = useState('en');  const provider = {    userLanguage,    dictionary: dictionaryList[userLanguage],    userLanguageChange: selected => {      const defaultLanguage = window.localStorage.getItem('rcml-lang');
const [userLanguage, setUserLanguage] = useState(defaultLanguage || 'en');
setUserLanguage(newLanguage); window.localStorage.setItem('rcml-lang', newLanguage); } }; return ( <LanguageContext.Provider value={provider}> {children} </LanguageContext.Provider> );};

When the language selector is changed, it will call the userLanguageChange() method of the provider.

You can examine the LanguageSelector.js below:

import React, { useContext } from 'react';import { languageOptions } from '../languages';import { LanguageContext } from '../containers/Language';export default function LanguageSelector() {  const { userLanguage, userLanguageChange } = useContext(LanguageContext);  // set selected language by calling context method  const handleLanguageChange = e => userLanguageChange(e.target.value);  return (    <select      onChange={handleLanguageChange}      value={userLanguage}    >      {Object.entries(languageOptions).map(([id, name]) => (        <option key={id} value={id}>{name}</option>      ))}    </select>  );};

And we need to wrap the main component which is App.js with LanguageProvider.

function App() {
return (
<LanguageProvider>
<div className=”App”>
<header className=”App-header”>
<LanguageSelector />
</header>
<Explore />
</div>
</LanguageProvider>
);
}

Then, we define Text component to translate our texts.

// get text according to id & current languageexport function Text({ tid }) {  const languageContext = useContext(LanguageContext);  return languageContext.dictionary[tid] || tid;};

Now, we can use this component to gather related text according to the selected language from predefined language objects (which I mentioned at the beginning of the article).
Also, we can call the language context directly to use such as the input placeholder example below.
Here are several usage examples in a component:

export default function Explore() {
const [clickText, setClickText] = useState();
const { dictionary } = useContext(LanguageContext);

const handleClick = () => {
setClickText(<Text tid="buttonClicked" />);
}

return (
<div>
<h1><Text tid="exploreHeader" /></h1>
<p><Text tid="welcomeDescription" /></p>

<div>
<input type="text" placeholder={dictionary.enterText} />
<button onClick={handleClick}>
<Text tid="clickMe" />
</button>
<p>{clickText}</p>
</div>

<a href="https://halilcanozcelik.com" target="_blank" rel="noopener noreferrer">
<Text tid="aboutMe" />
</a>
</div>
);
}

Additionally, the selected language should be stored in the database or local storage of the browsers and context states filled by this option at the beginning. An option of languageOptions can be used for a fallback scenario, I used English (“en”) in this project. Also, I have stored the selected language in local storage and reading from there at the beginning. If there is no info, then using browser language as the default language.

I hope it will be helpful.

--

--