Complete internationalization implementation for web applications. Provides systematic AI-driven workflow to achieve 100% i18n coverage with zero hardcoded strings in SOURCE CODE...
Implement complete internationalization (i18n) for web applications with 100% coverage. This skill provides a systematic, AI-driven workflow to eliminate all hardcoded strings and establish a scalable translation system.
For immediate i18n implementation:
t() calls⚠️ Important: For projects with > 1000 strings, you MUST split translation files by namespace. See modular-files.md for complete guidance.
Expected outcome: 100% of UI text uses i18n system, application works flawlessly in all supported languages.
This skill ONLY handles source code internationalization.
✅ IN SCOPE - Components and Source Code:
src/, app/, components/, views/, pages/❌ OUT OF SCOPE - Documentation Files:
docs/ folderWhen detecting existing i18n implementation:
FIRST PRIORITY: Check source code directories (src/, app/, components/, views/)
useTranslation(), t() function callsSECOND PRIORITY: Ignore documentation files
README*.md files do NOT count as i18n implementationdocs/ folder should be completely ignored✅ CORRECT - Check source code only:
# Check for i18n in source code
Grep: "i18n|useTranslation|i18next" in src/ directory
Glob: "src/**/locales/**/*.json"
Glob: "src/**/i18n/**"
# Check component files
Grep: "from [\"']react-i18next[\"']|from [\"']vue-i18n[\"']" in src/
❌ WRONG - Don't check documentation:
# These will detect documentation i18n, which is wrong
Glob: "**/README*.md"
Glob: "docs/**"
Grep: "i18n" in all files (includes docs)
Myth: "My project has README.md and README.zh-CN.md, so it has i18n." Fact: No, documentation internationalization is separate from code i18n.
Myth: "I have i18n in my docs/ folder, so I can skip i18n setup." Fact: Documentation i18n doesn't help your UI components translate.
Myth: "Finding i18n references anywhere means the project is internationalized." Fact: Only source code i18n counts. Documentation must be ignored.
Use this skill when:
Key principle: 100% coverage is the only acceptable standard. Zero hardcoded strings in UI.
Phase 1: Project Analysis (5-10 min)
Phase 2: String Extraction (30-60 min)
Phase 3: Translation Infrastructure (15-20 min)
Phase 4: Component Migration (40-80 min)
useTranslation hookt() callsPhase 5: Validation (10-15 min)
Total time: 1.5-3 hours for typical app (50-100 components)
✅ 100% of user-facing text uses i18n ✅ Zero hardcoded strings in UI components ✅ Translation files complete for all languages ✅ Application works perfectly in all supported languages ✅ No console errors or warnings
Before touching any code:
Identify the framework:
i18next + react-i18nextvue-i18n@ngx-translate/coreAnalyze component structure:
Glob: "src/components/**/*.{tsx,jsx,vue}"
Glob: "src/views/**/*.{tsx,jsx,vue}"
Check existing i18n in SOURCE CODE only:
# ✅ CORRECT - Check source code directories only
Grep: "i18n|i18next|vue-i18n|useTranslation" in src/
Glob: "src/**/locales/**"
Glob: "src/**/i18n/**"
# ❌ WRONG - Don't check documentation
# Do NOT search in: docs/, README*.md, .md files
CRITICAL: Only check source code directories. Ignore documentation files completely.
Create component inventory:
For each component, without exception:
Read the component file
Extract every user-facing string:
<div>Hello World</div><label>Email</label><input placeholder="Enter email" /><button>Submit</button><h1>Dashboard</h1><p>Error occurred</p>title, aria-label, alt<option>English</option>Determine appropriate namespace
Create translation key using naming conventions
Add to master translation list
Pattern to follow:
For component: src/components/chat/ChatView.tsx
Extracted strings:
- "Chat" → chat.chatView.title
- "New Conversation" → chat.chatView.newConversation
- "Type a message..." → chat.chatView.inputPlaceholder
- "Send" → chat.chatView.sendButton
For React projects:
Install dependencies:
npm install i18next react-i18next i18next-browser-languagedetector
Create configuration (src/i18n/config.ts):
import i18n from "i18next"
import { initReactI18next } from "react-i18next"
import LanguageDetector from "i18next-browser-languagedetector"
import enTranslations from "./locales/en.json"
import zhTranslations from "./locales/zh.json"
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources: {
en: { translation: enTranslations },
zh: { translation: zhTranslations },
},
fallbackLng: "en",
lng: "en",
interpolation: { escapeValue: false },
})
export default i18n
Create translation files:
src/i18n/locales/en.json - Copy all extracted strings heresrc/i18n/locales/zh.json - Translate all values to ChineseInitialize in main entry point:
import "./i18n/config" // Must be first import
For each component:
Add useTranslation hook:
import { useTranslation } from "react-i18next"
export const MyComponent: React.FC = () => {
const { t } = useTranslation("namespace")
Replace every hardcoded string:
// Before
<h1>Settings</h1>
<button>Save</button>
<input placeholder="Enter email" />
// After
<h1>{t("title")}</h1>
<button>{t("save")}</button>
<input placeholder={t("emailPlaceholder")} />
Handle special cases:
t("greeting", { name: userName })t(isLoading ? "loading" : "complete")const { t: tCommon } = useTranslation("common")Verify component still works
Pattern examples: See patterns.md for 20+ detailed examples.
Complete these checks:
Search for remaining hardcoded strings:
Grep: all components for text patterns
Expected: Zero user-facing hardcoded strings
Validate translation files:
Test language switching:
Review translation quality
Complete checklist: See checklist.md
workflow.md - Complete 5-phase workflow
patterns.md - Translation patterns and examples
namespaces.md - Namespace organization
checklist.md - Complete validation checklists
100% coverage means:
Process components methodically:
Use logical namespaces:
common - Shared UI elements{feature} - Feature-specific stringssettings - Settings/configurationerrors - Error messagesSee namespaces.md for complete guide.
Don't rush:
Verification is critical:
// Before
<h1>Welcome</h1>
// After
<h1>{t("welcome")}</h1>
// Before
<p>Hello, {userName}!</p>
// After
<p>{t("greeting", { userName })}</p>
// Translation file
"greeting": "Hello, {{userName}}!"
// Before
<input placeholder="Enter email" />
<button title="Click to submit">Submit</button>
// After
<input placeholder={t("emailPlaceholder")} />
<button title={t("submitTitle")}>{t("submit")}</button>
const { t: tCommon } = useTranslation("common")
const { t: tSettings } = useTranslation("settings")
<button>{tCommon("save")}</button>
<h1>{tSettings("title")}</h1>
See patterns.md for 20+ more examples.
Symptom: Console warnings about missing keys
Solution:
Symptom: Language changed but text didn't update
Solution:
Symptom: Some text doesn't translate
Solution:
Symptom: UI looks wrong after translation
Solution:
word-break or text truncation# Install dependencies (React)
npm install i18next react-i18next i18next-browser-languagedetector
# Validate JSON
cat src/i18n/locales/en.json | jq .
# Find hardcoded strings
grep -r '">[A-Z]' src/components/
src/i18n/
├── config.ts (or index.ts)
├── types.ts (optional, for TypeScript)
└── locales/
├── en.json (base language)
└── zh.json (target language)
src/main.tsx - Initialize i18n
// Single namespace
const { t } = useTranslation("namespace")
// Multiple namespaces
const { t: tCommon } = useTranslation("common")
const { t: tFeature } = useTranslation("feature")
// With interpolation
t("key", { variable: value })
For typical applications:
| Component Count | Time Required |
|---|---|
| Small (< 25 components) | 1-1.5 hours |
| Medium (25-75 components) | 1.5-3 hours |
| Large (75-150 components) | 3-5 hours |
| Very Large (> 150 components) | 5+ hours |
Time breakdown:
✅ When i18n is complete:
If stuck:
Remember: 100% coverage is the standard. Zero tolerance for hardcoded strings in user-facing UI.
