Skip to content

Instantly share code, notes, and snippets.

@jeffsheets
Last active December 30, 2019 22:41
Show Gist options
  • Save jeffsheets/b465a174eaccd7bd81c075964c0a9c5d to your computer and use it in GitHub Desktop.
Save jeffsheets/b465a174eaccd7bd81c075964c0a9c5d to your computer and use it in GitHub Desktop.
Create React App CRA2 with react-intl i18n message extraction and translation

i18n Translations

To generate new translations:

  1. remove .messages folder
  2. Extract all messages into .messages dir with: yarn i18n:extract
  3. Add new messages into {lang}.json files with: yarn i18n:manageTranslations
  4. Translate any new entries in {lang}.json files and commit to repo (see Untranslated keys: output of previous command for list of keys needing translation)

Setup

yarn add react-intl
yarn add react-intl.macro
yarn add --dev react-intl-translations-manager

Notes

This gist shows how to use react-intl with defaultMessage of English so a separate default en.json file is not needed, while not ejecting from Create React App.

ignore the extracted i18n messages by adding /.messages to .gitignore

(gist filenames cannot have / in filename, so these files use - in place of directories)

{
"name": "jeffsheets-react-intl",
"dependencies": {
"react": "^16.8.1",
"react-dom": "^16.8.1",
"react-intl": "^2.8.0",
"react-intl.macro": "^0.3.6",
"react-scripts": "2.1.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --colors",
"i18n:extract": "MESSAGE_DIR='./.messages' react-scripts build",
"i18n:manageTranslations": "node ./translationRunner.js"
},
"devDependencies": {
"react-intl-translations-manager": "^5.0.3"
}
}
import React from 'react';
import { FormattedMessage } from 'react-intl.macro';
export const App = ({username}) => {
return (
<>
<h1><FormattedMessage id="app.title" defaultMessage="Sample App" /></h1>
<FormattedMessage
id="app.hello.user"
defaultMessage="Hello {username}! Welcome!"
values={{username}}
/>
</>
);
}
import es from './translations/es.json';
// English is the default message in each of our source files, so no need for a separate en.json file
const en = {};
// If we add more than just spanish, just import the files and export it below: export default { en, es, de }
export default { en, es };
{
"app.title": "Aplicación de ejemplo",
"app.hello.user": "Hola {username} ¡Bienvenido!"
}
import React from 'react';
import ReactDOM from 'react-dom';
import { App } from './components/App';
import { addLocaleData, IntlProvider } from 'react-intl';
import enLocaleData from 'react-intl/locale-data/en';
import esLocaleData from 'react-intl/locale-data/es';
import translations from 'i18n/locales';
//English and Spanish (add more langs here)
addLocaleData(enLocaleData);
addLocaleData(esLocaleData);
//In future this would be set by a control on the page
// if you want to test Spanish just change this to es
const localeProp = 'en';
ReactDOM.render(
<IntlProvider
locale={localeProp}
defaultLocale="en"
key={localeProp}
messages={translations[localeProp]}
>
<App username="test123"/>
</IntlProvider>,
document.getElementById('root')
);
// See https://github.com/GertjanReynaert/react-intl-translations-manager
const manageTranslations = require('react-intl-translations-manager').default;
manageTranslations({
messagesDirectory: '.messages',
translationsDirectory: 'src/i18n/translations/',
// en is defaultLocale so no need to list en here
languages: ['es']
});
@Bluzkry
Copy link

Bluzkry commented Dec 30, 2019

Shouldn't src-index.js, line 7 be the below?

import translations from '.i18n/locales'; not import translations from 'i18n/locales';

@jeffsheets
Copy link
Author

@arvinsim, yes good catch!

@Bluzkry, depends on if absolute resolutions are setup or not, but yes that would work too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment