2d35c1d9de
- New client-side i18n via React Context (useI18n, tArray, I18nProvider) - Catalog ships 21 locale stubs; only zh-CN/en/ja have reviewed translations - Header language switcher (globe icon + short label) before settings gear - All hardcoded Chinese UI text migrated to keys: typewriter, options, hints (with embedded gear icon via dangerouslySetInnerHTML), settings panel, footer/about, play page hints - AI output language follows user-selected locale via trailing one-liner directive appended to Architect/Writer/CharacterDesigner/InsertBeat user messages (preserves system-prompt cacheability) - Per-locale separator rule: zh uses middot between every glyph; en/ja use plain spaces - Option value → i18n key suffix maps preserve Chinese as the underlying identifier so analytics unions and STYLE_MAP keys stay byte-stable Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
5.8 KiB
5.8 KiB
InfiPlot i18n Implementation
Summary
A complete i18n infrastructure has been implemented for InfiPlot, enabling support for 22 languages:
- English (en)
- Simplified Chinese (zh-CN) - Source language
- Traditional Chinese Taiwan (zh-TW)
- Traditional Chinese Hong Kong (zh-HK)
- Japanese (ja)
- Korean (ko)
- Spanish (es)
- French (fr)
- German (de)
- Portuguese Brazil (pt-BR)
- Portuguese (pt)
- Russian (ru)
- Italian (it)
- Vietnamese (vi)
- Thai (th)
- Indonesian (id)
- Turkish (tr)
- Polish (pl)
- Dutch (nl)
- Ukrainian (uk)
- Hindi (hi)
- Czech (cs)
What Was Implemented
1. Core i18n Infrastructure (lib/i18n/)
- config.ts: Locale configuration, locale names, storage key management
- types.ts: TypeScript types for translation system
- utils.ts: Helper functions for nested value access, string formatting
- client.tsx: React context provider and
useI18n()hook for client components - server.ts: Server-side translation utilities for Next.js App Router
- index.ts: Main export file
2. Translation Files (lib/i18n/locales/)
- zh-CN.ts: Complete source translations (Chinese)
- en.ts: Reference English translations
- Additional locale files will be generated by the translation script
3. Translation Script (scripts/translate-i18n.mjs)
A Node.js script that:
- Reads the source zh-CN translation file
- Uses LLM APIs (Gemini or OpenAI-compatible) to translate to all target languages
- Preserves structure and handles special cases:
- Placeholder variables (
{{email}},{n}, etc.) - HTML tags (
<em>,<a>, etc.) - Select/message format syntax
- Proper nouns (InfiPlot, GitHub, Google, etc.)
- Placeholder variables (
- Generates TypeScript locale files
- Updates client.tsx and server.ts imports automatically
Usage:
# With Gemini
node scripts/translate-i18n.mjs --provider gemini --api-key YOUR_KEY
# With OpenAI-compatible API
TEXT_API_KEY=your_key TEXT_BASE_URL=https://api.openai.com/v1 node scripts/translate-i18n.mjs --provider openai
4. Components Updated with i18n
- ✅ CustomForm.tsx
- ✅ DialogueHistoryModal.tsx
- ✅ AuthModal.tsx
- ✅ PlayCanvas.tsx
- ✅ SettingsModal.tsx
- ✅ page.tsx (home page)
- ✅ layout.tsx (I18nProvider wrapper)
- ✅ LanguageSwitcher.tsx (new component)
Current Status
Completed
- i18n Infrastructure - All core files in
lib/i18n/ - Translation Files - zh-CN.ts (source) and en.ts (reference) complete
- Stub Files - Created for all 20 target languages (fallback to en)
- Component Integration - All UI components now use
t()function - Language Switcher - Added to page header with dropdown UI
- TypeScript Types - Full type safety for translation system
Remaining Work
-
Generate Actual Translations
- Run the translation script to translate stub files
- Review and edit generated translations for quality
- Test with native speakers if possible
-
Update Metadata (optional)
- Make page titles and descriptions dynamic based on locale
- Update
langattribute on html element dynamically
Optional Enhancements
-
Server-Side Rendering Support
- Implement locale detection from Accept-Language header
- Add middleware for locale routing (e.g., /en/play, /zh-CN/play)
- Cache translations for better performance
-
Date/Number Formatting
- Add locale-specific formatting for dates, numbers, currencies
- Use Intl.DateTimeFormat and Intl.NumberFormat
-
RTL Support
- Currently no RTL locales, but infrastructure is in place
- Add layout mirroring if needed for future RTL languages
-
Pluralization
- Enhance formatTranslation to support ICU message format
- Handle singular/plural forms
Translation Best Practices
When adding new strings:
- Keep strings neutral where possible
- Avoid culturally-specific references
- Provide context for translators in comments
- Test with longer strings (German, Russian can be 2-3x longer)
- Keep placeholders consistent (
{{varName}}or{varName})
API Keys Required
To generate translations, set one of:
GEMINI_API_KEYfor Google Gemini (recommended for cost)TEXT_API_KEYfor OpenAI-compatible APITEXT_BASE_URLfor custom OpenAI-compatible endpoints
Files Modified
New Files Created
lib/i18n/(entire directory)config.ts- Locale configurationclient.tsx- React context providerserver.ts- Server-side utilitiesutils.ts- Helper functionslocales/zh-CN.ts- Source translationslocales/en.ts- English referencelocales/zh-TW.ts- Traditional Chinese stublocales/zh-HK.ts- Hong Kong Chinese stublocales/ja.ts- Japanese stublocales/ko.ts- Korean stublocales/es.ts- Spanish stublocales/fr.ts- French stublocales/de.ts- German stublocales/pt-BR.ts- Portuguese Brazil stublocales/pt.ts- Portuguese stublocales/ru.ts- Russian stublocales/it.ts- Italian stublocales/vi.ts- Vietnamese stublocales/th.ts- Thai stublocales/id.ts- Indonesian stublocales/tr.ts- Turkish stublocales/pl.ts- Polish stublocales/nl.ts- Dutch stublocales/uk.ts- Ukrainian stublocales/hi.ts- Hindi stublocales/cs.ts- Czech stub
components/LanguageSwitcher.tsx- Language selector componentscripts/translate-i18n.mjs- Translation scriptdocs/i18n-implementation.md- This documentation
Modified Files
app/layout.tsx- Added I18nProvider wrapperapp/page.tsx- Added i18n to all strings and LanguageSwitchercomponents/CustomForm.tsx- Added i18ncomponents/DialogueHistoryModal.tsx- Added i18ncomponents/AuthModal.tsx- Added i18ncomponents/PlayCanvas.tsx- Added i18ncomponents/SettingsModal.tsx- Added i18n
TypeScript
All type definitions are in place. Run pnpm typecheck to verify.