Automatically extract hardcoded strings and internationalize your React codebase
This pro codemod intelligently identifies hardcoded text in your React components and transforms them into properly internationalized code using modern i18n libraries like next-intl, react-i18next, or react-intl.
🚀 Features
AI-powered: Uses advanced AI to generate meaningful translation keys and handle complex string patterns
Multi-library support: Works with next-intl, react-i18next, and react-intl
Smart Sharding: Handles large codebases by intelligently splitting work across teams/directories
Automated PR creation: Creates pull requests with proper reviews and formatting
Message catalog management: Automatically creates and updates translation files
Context-aware: Preserves code structure and handles complex JSX patterns
🔧 How It Works
The codemod scans your React/TypeScript files for hardcoded strings in JSX elements and transforms them into internationalized code:
Before
tsx
import React from "react";
export function MyComponent() {
return (
<div>
<h1>Welcome to our app</h1>
<p>Please sign in to continue</p>
<button>Get Started</button>
</div>
);
}
After (next-intl)
tsx
import { useTranslations } from "next-intl";
import React from "react";
export function MyComponent() {
const t = useTranslations();
return (
<div>
<h1>{t("welcome_title")}</h1>
<p>{t("sign_in_prompt")}</p>
<button>{t("get_started_button")}</button>
</div>
);
}
{
"welcome_back": "Welcome back, {name}!",
"message_count": "{count, plural, =0 {You have no new messages} =1 {You have # new message} other {You have # new messages}}",
"last_login": "Last login: {date, date, medium}"
}
export function OrderStatus({ status, items, total, user }) {
return (
<div>
<h2>
{status === "pending"
? "Your order is being processed"
: status === "shipped"
? "Your order is on the way!"
: "Order delivered"}
</h2>
<p>
{user.isPremium
? `Hi ${user.name}, your ${items.length} premium items (${total}) will arrive tomorrow`
: `Hello ${user.name}, your ${items.length} items totaling ${total} will arrive in 3-5 days`}
</p>
</div>
);
}
After:
tsx
import { useTranslations } from "next-intl";
export function OrderStatus({ status, items, total, user }) {
const t = useTranslations();
return (
<div>
<h2>{t("order_status", { status })}</h2>
<p>
{t("delivery_info", {
isPremium: user.isPremium,
name: user.name,
itemCount: items.length,
total,
})}
</p>
</div>
);
}
Generated Catalog:
json
{
"order_status": "{status, select, pending {Your order is being processed} shipped {Your order is on the way!} other {Order delivered}}",
"delivery_info": "{isPremium, select, true {Hi {name}, your {itemCount, plural, =1 {# premium item} other {# premium items}} ({total, number, currency}) will arrive tomorrow} other {Hello {name}, your {itemCount, plural, =1 {# item} other {# items}} totaling {total, number, currency} will arrive in 3-5 days}}"
}
Rich Text with Components (next-intl)
Before:
tsx
export function PolicyNotice({ companyName }) {
return (
<div>
<p>
By clicking "Accept", you agree to our{" "}
<Link href="/terms">Terms of Service</Link> and{" "}
<Link href="/privacy">Privacy Policy</Link>.
</p>
<p>
Questions? <strong>Contact {companyName} support</strong> for help.
</p>
</div>
);
}
{
"policy_agreement": "By clicking \"Accept\", you agree to our <termsLink>Terms of Service</termsLink> and <privacyLink>Privacy Policy</privacyLink>.",
"support_contact": "Questions? <strong>Contact {companyName} support</strong> for help."
}
Rich Text with Components (react-intl)
The same ICU messages above can be rendered with react-intl like this: