AI-Assisted i18n: Localizing Your React App 10x Faster
The Localization Bottleneck
The Localization Bottleneck
Internationalization is one of those tasks that every team knows they should do early but always postpones until a client asks for it. Then it becomes a nightmare: hundreds of hardcoded strings scattered across dozens of components, date formats that assume US locale, RTL layout support that was never considered, and a deadline that is always too tight.
I have localized React applications for Hebrew, Arabic, Spanish, German, and Japanese markets. The manual approach — finding every string, extracting it to a key, translating it, testing every page — used to take two to four weeks for a medium-sized app. With AI assistance, I now do it in two to three days.
Here is the exact process.
Step 1: Set Up the i18n Infrastructure (10 Minutes)
Install react-i18next, the industry standard for React internationalization:
npm install react-i18next i18next i18next-browser-languagedetector i18next-http-backend
Create the configuration:
// src/i18n/config.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import HttpBackend from 'i18next-http-backend';
i18n
.use(HttpBackend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
fallbackLng: 'en',
supportedLngs: ['en', 'he', 'es', 'de'],
defaultNS: 'common',
ns: ['common', 'dashboard', 'settings', 'auth'],
interpolation: {
escapeValue: false, // React already escapes
},
backend: {
loadPath: '/locales/{{lng}}/{{ns}}.json',
},
detection: {
order: ['querystring', 'localStorage', 'navigator'],
caches: ['localStorage'],
},
});
export default i18n;
Import it in your entry file:
// src/main.tsx
import './i18n/config';
Step 2: Extract All Hardcoded Strings (30 Minutes)
This is the most tedious part of localization, and where AI saves the most time:
Scan the entire src/ directory and find every hardcoded user-facing string.
Include:
- JSX text content: <h1>Welcome back</h1>
- Attribute strings: placeholder="Enter your email"
- Template literals with user text: `Hello, ${name}!`
- Error messages: toast.error("Something went wrong")
- Button labels, form labels, tooltips, aria-labels
- Validation messages: "Email is required"
Exclude:
- CSS class names
- Console.log messages
- Internal variable names
- API endpoint URLs
- TypeScript type definitions
For each string found:
1. File path and line number
2. The original string
3. A suggested i18n key following the pattern: namespace.section.description
4. Whether it contains interpolation variables
Output as a CSV: file, line, original, key, hasInterpolation
Example:
src/pages/Dashboard.tsx, 45, "Welcome back", dashboard.header.welcomeBack, false
src/pages/Dashboard.tsx, 52, "You have {count} notifications", dashboard.header.notificationCount, true
On a typical 50-component app, this finds 200-400 strings. Doing this manually takes a full day. AI does it in minutes.
Step 3: Generate Translation Files (15 Minutes)
Take the extracted strings and generate the English base translation file:
Using the extracted strings list, generate the translation JSON files.
Create:
1. public/locales/en/common.json — shared strings (nav, footer, buttons, errors)
2. public/locales/en/dashboard.json — dashboard-specific strings
3. public/locales/en/settings.json — settings page strings
4. public/locales/en/auth.json — login, signup, password reset strings
Format:
{
"header": {
"welcomeBack": "Welcome back",
"notificationCount": "You have {{count}} notifications",
"notificationCount_one": "You have {{count}} notification",
"notificationCount_other": "You have {{count}} notifications"
}
}
Requirements:
- Use nested keys for organization (max 3 levels deep)
- Handle pluralization with i18next plural suffix (_one, _other, _zero)
- Use {{variable}} syntax for interpolation
- Group by page section, not by component
Step 4: Generate Translations for Target Languages (20 Minutes)
This is where AI truly shines. Professional translation costs $0.10-0.20 per word. For 400 strings averaging 5 words each, that is $200-400 per language. AI translations are not perfect, but they are 85-90% production-ready:
Translate the English translation files to Hebrew (he).
Requirements:
1. Keep all JSON keys in English (only translate values)
2. Keep all {{interpolation}} variables unchanged
3. Handle pluralization rules for Hebrew (_one, _two, _other)
4. Handle grammatical gender where relevant
5. Keep brand names, technical terms, and product names in English
6. Use natural, conversational Hebrew — not overly formal
7. For UI elements (buttons, labels), keep translations concise
8. RTL: no special handling needed in translation files, just natural Hebrew
Create: public/locales/he/common.json, dashboard.json, settings.json, auth.json
Also flag any strings that:
- Are ambiguous without context (the same English word can mean different things)
- Have cultural references that may not translate well
- Need different lengths that might break the UI layout
Repeat for each target language. For languages I do not speak, I have a native speaker review the AI translations. They typically need to correct 10-15% of strings — mostly nuance and tone, not meaning.
Step 5: Replace Strings in Components (30 Minutes)
Now automate the actual code changes:
Read src/pages/Dashboard.tsx and replace all hardcoded strings with
i18next translation calls.
Rules:
1. Import useTranslation: import { useTranslation } from 'react-i18next';
2. Add const { t } = useTranslation('dashboard'); at the top of the component
3. Replace strings:
- "Welcome back" -> {t('header.welcomeBack')}
- "You have 5 notifications" -> {t('header.notificationCount', { count: 5 })}
- placeholder="Search..." -> placeholder={t('common:search.placeholder')}
4. For strings with HTML: use Trans component
- "Read our <a>terms</a>" -> <Trans i18nKey="footer.terms" components={{ a: <Link to="/terms" /> }} />
5. Keep the same visual layout — do not change any styling or structure
6. If a component uses strings from multiple namespaces, import them:
const { t } = useTranslation(['dashboard', 'common']);
Show me the complete updated file.
Run this for each component file. I typically batch 3-5 small components per prompt and handle large components individually.
Step 6: Handle RTL Layout (15 Minutes)
For RTL languages like Hebrew and Arabic, you need layout adjustments:
Scan the entire src/ directory for CSS/Tailwind patterns that need RTL support:
1. Fixed directional values:
- margin-left, margin-right -> margin-inline-start, margin-inline-end
- padding-left, padding-right -> padding-inline-start, padding-inline-end
- left, right -> inset-inline-start, inset-inline-end
- text-align: left -> text-align: start
2. Tailwind classes:
- ml-4 -> ms-4 (margin-start)
- pr-2 -> pe-2 (padding-end)
- left-0 -> start-0
- text-left -> text-start
3. Flexbox/Grid direction:
- Items that should reverse in RTL
- Icons that have directional meaning (arrows, chevrons)
4. Components that need special RTL handling:
- Navigation breadcrumbs
- Progress bars
- Sliders and carousels
For each issue, show the file, current code, and the RTL-safe replacement.
Step 7: Test Every Language (10 Minutes)
Add a language switcher for development and QA:
// src/components/dev/LanguageSwitcher.tsx
import { useTranslation } from 'react-i18next';
export function LanguageSwitcher() {
const { i18n } = useTranslation();
return (
<div className="fixed bottom-4 right-4 flex gap-2 z-50">
{['en', 'he', 'es', 'de'].map((lng) => (
<button
key={lng}
onClick={() => i18n.changeLanguage(lng)}
className={`px-3 py-1 rounded text-sm ${
i18n.language === lng ? 'bg-blue-600 text-white' : 'bg-gray-200'
}`}
>
{lng.toUpperCase()}
</button>
))}
</div>
);
}
Then use Claude Code to check for layout issues:
With the app running in Hebrew (RTL), check for common layout issues:
1. Text overflow — Hebrew strings are often longer than English
2. Truncated labels — buttons and form labels cut off
3. Misaligned icons — icons that should flip in RTL
4. Number formatting — dates, currencies, phone numbers
5. Form validation messages — do they display correctly in RTL?
For each issue found, suggest the CSS fix.
Results I Have Seen
Medium-sized SaaS app (52 components, ~350 strings):
- Manual localization estimate: 3-4 weeks
- AI-assisted localization: 2.5 days
- Translation accuracy (reviewed by native speakers): 87% usable as-is, 13% needed minor edits
- Cost savings: ~$1,200 in professional translation fees for the first pass
The AI does not replace professional translators for final quality, but it gets you 85-90% of the way there in a fraction of the time. For MVP and beta launches, that is more than enough.