In this cookbook we will implement quick and simple translations into the React project.
This project was bootstrapped with Create React App.
npm i -S react-intl @formatjs/cli
Or just use the existing one.
npm i -S easy-peasy
The translations state could be even persisted in React.Context
.
{
"app.hi": "Hi!"
}
{
"app.hi": "¡Hola!"
}
{
"app.hi": "Cześć!"
}
src/translations/types.ts
:
import { Action } from "easy-peasy"
// supported languages and their locales codes
// for non-TS project, it can be stored as object `const locale = { english: 'en', ...}`
export enum Locale {
English = 'en',
Polish = 'pl',
Spanish = 'es',
}
// yeah this is how we will store our messages
// for every locale, there is one messages object from our JSON files
export type AppTranslations = Record<string, string>
export type AllMessages = Record<Locale, AppTranslations>
export type TranslationsStore = {
locale: Locale,
translations: AppTranslations,
// easy-pasy action function takes the following params: 1. state object 2. the payload
selectLanguage: Action<TranslationsStore, Locale>
}
src/translations/config.ts
:
// import JSON translations files
import englishMessages from '../lang/en.json';
import spanishMessages from '../lang/es.json';
import polishMessages from '../lang/pl.json';
import { AllMessages, AppTranslations, Locale } from './types';
// list of supported languages using defined `Locale` enumerator
export const languages = [
{
locale: Locale.English,
name: 'English',
},
{
locale: Locale.Spanish,
name: 'Spanish',
},
{
locale: Locale.Polish,
name: 'Polish',
},
];
// Let's check if the locale that we want to use, is supported
// e.g. retrieving it from `localStorage` - get ready for the next steps 🤗
export const isSupportedLocale = (locale?: string) =>
Boolean(languages.find(language => language.locale === locale));
const messages: AllMessages = {
[Locale.English]: englishMessages,
[Locale.Spanish]: spanishMessages,
[Locale.Polish]: polishMessages,
};
export const getMessages = (locale: Locale): AppTranslations =>
(isSupportedLocale(locale) && messages[locale]) || englishMessages
Of course you can use whatever lib/solution you want 😊
src/translations/store.ts
:
import { action, createStore } from "easy-peasy";
import { getMessages } from "./config";
import { Locale, TranslationsStore } from "./types";
// define the app default languge
const defaultLocale = Locale.English;
export const translationsStore = createStore<TranslationsStore>({
locale: defaultLocale,
// get the translations for default locale
translations: getMessages(defaultLocale),
selectLanguage: action<TranslationsStore, Locale>((state, locale) => {
// let's mutate the state! 😄
state.locale = locale
state.translations = getMessages(locale)
})
});