Introduction
Internationalization in React is often treated as a translation problem. Replace strings with keys, load dictionaries, call it done.
That works until the product grows. Then you discover that i18n touches routing, formatting, validation, SEO, caching, design, content workflows, and sometimes even business logic.
Good React internationalization is architecture. It is not just a helper function named t.
Strings Are the Smallest Part
Text replacement is the visible part of i18n, but it is rarely the hardest part.
A real multilingual application needs answers to several questions:
- How is the active locale chosen?
- Is the locale part of the URL?
- How are dates, numbers, currencies, and plural forms formatted?
- Can translations be loaded without hurting performance?
- How do translated pages appear to search engines?
- What happens when a translation is missing?
If these decisions are made ad hoc, the codebase slowly fills with local exceptions.
Locale Routing Matters for SEO
For public pages, locale routing is an SEO decision. Search engines need stable URLs for each language version. Users need shareable links that preserve language.
A common structure is:
/en/pricing
/de/pricing
/uk/pricing
This makes language explicit. It also gives the application a natural place to generate canonical URLs, alternate links, and localized metadata.
Hiding locale only in local storage or browser preferences may feel simpler, but it creates weaker URLs. For content-heavy sites, that trade-off is usually not worth it.
Translation Keys Are an API
Translation keys look like implementation details, but they behave like an API between developers, translators, and content workflows.
Poor keys describe placement:
home.hero.title
home.hero.subtitle
button.submit
These can be fine in small apps, but they become fragile when the layout changes. Better keys often describe meaning:
pricing.plan.enterprise.title
checkout.payment.submit
auth.passwordReset.successMessage
The key should help a translator understand context. A word like "Save" can mean storing a document, saving money, or rescuing a draft from being lost. Context changes translation.
Formatting Is Not Translation
Dates, numbers, currencies, and plural rules should not be hand-built with string concatenation.
Use platform tools like Intl.DateTimeFormat, Intl.NumberFormat, and proper pluralization support from your i18n library.
The difference matters:
new Intl.NumberFormat("de-DE", {
style: "currency",
currency: "EUR",
}).format(1299.5);
Formatting is full of local conventions. Decimal separators, currency placement, calendar expectations, and plural categories vary. If the application ignores those details, the UI feels translated but not localized.
Missing Translations Need a Policy
Every mature i18n system needs a missing translation policy.
During development, missing keys should be loud. In production, the app should degrade gracefully. That might mean falling back to a default locale, showing a tracked placeholder, or blocking release when required translations are missing.
The important part is consistency. Random fallbacks make QA difficult and can create embarrassing production pages.
Performance Should Be Designed Early
Large translation dictionaries can become a performance issue. Loading every language and every namespace at startup is wasteful.
A better approach is to load translations by locale and route or feature. The user visiting /en/pricing does not need every admin dashboard string in five languages.
Modern tools can help with compile-time extraction, tree-shaking, and route-level loading. The specific library matters less than the strategy: ship the language data the page actually needs.
React Component Design for i18n
Internationalization also affects component design.
Avoid components that hard-code English sentence structure across multiple props:
<Banner prefix="Save" value="20%" suffix="today" />
This assumes the translated sentence can be assembled in the same order. Often it cannot.
Prefer passing a complete translated message, or use rich text translation patterns that allow translators to control word order while developers control safe markup.
Conclusion
React internationalization without pain starts by treating i18n as a system, not a string replacement chore.
Locale routing, translation keys, formatting, loading strategy, SEO metadata, and component composition all belong to the same architectural conversation.
If you design that system early, adding a new language becomes a product operation. If you postpone it, adding a new language becomes a refactor disguised as content work.