A React application demonstrating internationalization (i18n) using React Intl with support for multiple languages.
- 🌍 Multi-language support (English & Spanish)
- 🔄 Dynamic language switching
- 📝 Message formatting with pluralization
- 📅 Date formatting with locale support
- 🔢 Number formatting
- 💾 Locale persistence in localStorage
- React 18
- TypeScript
- React Intl (FormatJS)
- Create React App
- Node.js 18+ and npm installed
- Install dependencies:
npm install- Start the development server:
npm run buildThe app will open at http://localhost:3000
- Build for production:
npm run buildsrc/
├── components/
│ ├── [App.tsx](http://_vscodecontentref_/0) # Main app component
│ ├── [LanguageSwitcher.tsx](http://_vscodecontentref_/1) # Language toggle component
│ ├── [QuestionsList.tsx](http://_vscodecontentref_/2) # Sample list with i18n
│ └── [QuestionsList.messages.ts](http://_vscodecontentref_/3) # Message definitions
├── i18n/
│ ├── LocaleProvider.tsx # Locale context provider
│ ├── [ReactIntlProvider.tsx](http://_vscodecontentref_/4) # React Intl wrapper
│ ├── [useAsyncMessages.ts](http://_vscodecontentref_/5) # Hook for loading translations
│ └── assets/
│ ├── [en-US.json](http://_vscodecontentref_/6) # English translations
│ └── [es-ES.json](http://_vscodecontentref_/7) # Spanish translations
├── index.tsx # App entry point
└── styles.css # Global styles
- Locale Management
The app uses a custom LocaleProvider to manage the current locale and persist it to localStorage.
- Message Definitions
Messages are defined using defineMessages from react-intl with unique IDs:
export const messages = defineMessages({
title: {
id: "questions.title",
defaultMessage: "Questions",
description: "Heading for question list",
},
// ...
});- Translation Files
Translation files in assets map message IDs to translated strings:
{
"questions.title": "Preguntas",
"questions.questionCount": "{count, plural, one {# pregunta} other {# preguntas}}"
}- Using Translations
Display translated messages with FormattedMessage:
<FormattedMessage {...messages.title} />With variables and formatting:
<FormattedMessage {...messages.questionCount} values={{ count: 6 }} />- Create a new JSON file in assets (e.g., fr-FR.json)
- Add translations matching the message IDs
- Update the Locale type in
LocaleProvider.tsx - Add a button in
LanguageSwitcher.tsx - Update the dynamic import logic in
useAsyncMessages.ts
MIT