Respuesta rápida
Para añadir internacionalización (i18n) a React, usa react-i18next. Instálalo con npm install react-i18next i18next, create JSON translation files, configure i18next with your languages, and use the useTranslation hook (const { t } = useTranslation()) to display translated strings. For Next.js projects, use next-intl instead for better App Router integration. IntlPull can manage translations and provide AI-powered translation when you scale beyond JSON files.
Introduction to React Internationalization
Building a React application for a global audience requires proper internationalization (i18n). This guide covers everything you need to know about implementing i18n in React applications, from basic setup to advanced patterns.
Why Internationalization Matters
- Reach Global Markets: 75% of internet users prefer content in their native language
- Increase Conversion: Localized apps see up to 70% higher conversion rates
- Better UX: Users engage more with content they can fully understand
- SEO Benefits: Localized content ranks better in regional search results
Choosing an i18n Library
react-intl (FormatJS)
JSX1import { IntlProvider, FormattedMessage } from 'react-intl'; 2 3function App() { 4 return ( 5 <IntlProvider messages={messages} locale="en"> 6 <FormattedMessage id="greeting" defaultMessage="Hello, World!" /> 7 </IntlProvider> 8 ); 9}
Pros:
- Official React implementation of FormatJS
- Excellent ICU message format support
- Built-in number, date, and currency formatting
Cons:
- Larger bundle size
- Steeper learning curve for ICU syntax
react-i18next
JSX1import { useTranslation } from 'react-i18next'; 2 3function App() { 4 const { t } = useTranslation(); 5 return <h1>{t('greeting')}</h1>; 6}
Pros:
- Lightweight and flexible
- Great TypeScript support
- Plugin ecosystem (backends, language detection)
Cons:
- Less strict message formatting
- Requires more configuration
next-intl (for Next.js)
JSX1import { getTranslations } from 'next-intl/server'; 2 3async function HomePage() { 4 const t = await getTranslations('home'); 5 return <h1>{t('title')}</h1>; 6}
Pros:
- Built specifically for Next.js
- Server component support
- Automatic routing
Setting Up Your Project
Step 1: Install Dependencies
Terminalnpm install react-i18next i18next
Step 2: Create Translation Files
/locales
/en
common.json
home.json
/es
common.json
home.json
/fr
common.json
home.json
Step 3: Configure i18next
JavaScript1// i18n.js 2import i18n from 'i18next'; 3import { initReactI18next } from 'react-i18next'; 4 5i18n 6 .use(initReactI18next) 7 .init({ 8 resources: { 9 en: { translation: require('./locales/en/common.json') }, 10 es: { translation: require('./locales/es/common.json') }, 11 }, 12 lng: 'en', 13 fallbackLng: 'en', 14 interpolation: { escapeValue: false }, 15 }); 16 17export default i18n;
Step 4: Wrap Your App
JSX1import './i18n'; 2 3function App() { 4 return ( 5 <Suspense fallback="Loading..."> 6 <YourApp /> 7 </Suspense> 8 ); 9}
Advanced Patterns
Handling Pluralization
JSON1{ 2 "items": "You have {{count}} item", 3 "items_plural": "You have {{count}} items" 4}
JSXt('items', { count: 5 }) // "You have 5 items"
Interpolation with Components
JSX<Trans i18nKey="welcome" components={{ strong: <strong /> }}> Welcome, <strong>{{name}}</strong>! </Trans>
Context-Based Translations
JSON1{ 2 "friend": "A friend", 3 "friend_male": "A boyfriend", 4 "friend_female": "A girlfriend" 5}
Lazy Loading Translations
JavaScript1i18n.use(Backend).init({ 2 backend: { 3 loadPath: '/locales/{{lng}}/{{ns}}.json', 4 }, 5});
Managing Translations at Scale
As your app grows, managing JSON files manually becomes painful:
- Version conflicts: Multiple developers editing the same files
- Missing translations: Hard to track what's translated
- No context: Translators don't see where strings are used
- Slow workflow: Manual export/import cycles
The Solution: Translation Management Systems
A TMS like IntlPull solves these problems:
Terminal1# Pull latest translations 2npx @intlpullhq/cli download 3 4# Push new strings 5npx @intlpullhq/cli upload 6 7# Check translation status 8npx @intlpullhq/cli status
Benefits:
- Real-time sync with your codebase
- Context screenshots for translators
- AI-powered translation suggestions
- Collaboration with review workflows
Best Practices
1. Extract All Strings
Never leave hardcoded text:
JSX1// Bad 2<button>Submit</button> 3 4// Good 5<button>{t('form.submit')}</button>
2. Use Meaningful Keys
JSON1// Bad 2{ 3 "text1": "Welcome", 4 "text2": "Sign up" 5} 6 7// Good 8{ 9 "home.hero.title": "Welcome", 10 "auth.signup.button": "Sign up" 11}
3. Include Context
JSON1{ 2 "save": "Save", 3 "save_description": "Button to save user profile changes" 4}
4. Handle RTL Languages
JSX<div dir={isRTL ? 'rtl' : 'ltr'}> {children} </div>
5. Format Dates and Numbers Properly
JSX1const formattedDate = new Intl.DateTimeFormat(locale).format(date); 2const formattedPrice = new Intl.NumberFormat(locale, { 3 style: 'currency', 4 currency: 'USD', 5}).format(price);
Common Mistakes to Avoid
- String concatenation: Use interpolation instead
- Hardcoded formatting: Let the i18n library handle it
- Ignoring context: Same word can have different translations
- Not testing RTL: Test with Arabic or Hebrew
- Manual file management: Use a TMS
Performance Optimization
Code Splitting Translations
JavaScriptconst HomeTranslations = lazy(() => import('./locales/home'));
Using Suspense
JSX<Suspense fallback={<Skeleton />}> <TranslatedComponent /> </Suspense>
Memoizing Formatted Values
JSX1const formattedPrice = useMemo( 2 () => formatCurrency(price, locale), 3 [price, locale] 4);
Testing Internationalized Apps
JavaScript1// test-utils.js 2import { render } from '@testing-library/react'; 3import { I18nextProvider } from 'react-i18next'; 4import i18n from './i18n-test'; 5 6function renderWithI18n(ui, locale = 'en') { 7 i18n.changeLanguage(locale); 8 return render( 9 <I18nextProvider i18n={i18n}>{ui}</I18nextProvider> 10 ); 11}
Conclusion
React internationalization doesn't have to be complex. Start with a solid foundation, follow best practices, and use the right tools to manage translations at scale.
Next steps:
- Set up react-i18next or next-intl in your project
- Extract existing hardcoded strings
- Connect to IntlPull for translation management
- Add AI-powered translations for quick localization
Ready to simplify your React i18n workflow? Start your free IntlPull trial and manage translations like a pro.
Frequently Asked Questions
What is the best i18n library for React?
react-i18next is the best i18n library for most React projects due to its lightweight size, flexibility, and excellent TypeScript support. For Next.js projects, use next-intl instead—it's designed specifically for App Router and Server Components. react-intl (FormatJS) is a good alternative if you need strict ICU message format compliance.
How do I add internationalization to an existing React app?
To add i18n to an existing React app: (1) Install react-i18next: npm install react-i18next i18next, (2) Create translation JSON files in a locales folder, (3) Configure i18next with your languages and wrap your app, (4) Replace hardcoded strings with t('keyName') calls using the useTranslation hook. IntlPull's CLI can help extract existing hardcoded strings automatically.
How do I handle pluralization in React i18n?
Use plural keys with count variable: In your JSON, add "items": "{{count}} item" and "items_plural": "{{count}} items". Then call t('items', { count: 5 }) and react-i18next automatically selects the correct form. For complex plurals (Russian, Arabic), use ICU format: "{count, plural, one {# item} few {# items} many {# items} other {# items}}".
Should I use react-i18next or next-intl for Next.js?
Use next-intl for Next.js projects. It's designed specifically for Next.js App Router with native Server Component support, automatic locale routing, and a smaller bundle than react-i18next. react-i18next works in Next.js but requires extra configuration for Server Components and doesn't integrate as seamlessly with Next.js features.
How do I test React components with i18n?
Wrap components with I18nextProvider in tests using a test i18n configuration. Create a custom render function that provides the i18n context. Test against translation keys or actual translated text depending on your preference. Mock translations can simplify testing but testing with real translations catches more issues.
How do I manage translation files at scale?
Use a Translation Management System (TMS) like IntlPull when you have 500+ strings or 3+ languages. Manual JSON management becomes error-prone at scale. IntlPull provides: CLI sync (npx @intlpullhq/cli upload/download), AI-powered translation, translator collaboration, and context screenshots—eliminating manual file management.
