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>
184 lines
5.8 KiB
Markdown
184 lines
5.8 KiB
Markdown
# 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.)
|
|
- Generates TypeScript locale files
|
|
- Updates client.tsx and server.ts imports automatically
|
|
|
|
Usage:
|
|
```bash
|
|
# 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
|
|
|
|
1. **i18n Infrastructure** - All core files in `lib/i18n/`
|
|
2. **Translation Files** - zh-CN.ts (source) and en.ts (reference) complete
|
|
3. **Stub Files** - Created for all 20 target languages (fallback to en)
|
|
4. **Component Integration** - All UI components now use `t()` function
|
|
5. **Language Switcher** - Added to page header with dropdown UI
|
|
6. **TypeScript Types** - Full type safety for translation system
|
|
|
|
### Remaining Work
|
|
|
|
1. **Generate Actual Translations**
|
|
- Run the translation script to translate stub files
|
|
- Review and edit generated translations for quality
|
|
- Test with native speakers if possible
|
|
|
|
2. **Update Metadata** (optional)
|
|
- Make page titles and descriptions dynamic based on locale
|
|
- Update `lang` attribute on html element dynamically
|
|
|
|
### Optional Enhancements
|
|
|
|
1. **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
|
|
|
|
2. **Date/Number Formatting**
|
|
- Add locale-specific formatting for dates, numbers, currencies
|
|
- Use Intl.DateTimeFormat and Intl.NumberFormat
|
|
|
|
3. **RTL Support**
|
|
- Currently no RTL locales, but infrastructure is in place
|
|
- Add layout mirroring if needed for future RTL languages
|
|
|
|
4. **Pluralization**
|
|
- Enhance formatTranslation to support ICU message format
|
|
- Handle singular/plural forms
|
|
|
|
## Translation Best Practices
|
|
|
|
When adding new strings:
|
|
|
|
1. Keep strings neutral where possible
|
|
2. Avoid culturally-specific references
|
|
3. Provide context for translators in comments
|
|
4. Test with longer strings (German, Russian can be 2-3x longer)
|
|
5. Keep placeholders consistent (`{{varName}}` or `{varName}`)
|
|
|
|
## API Keys Required
|
|
|
|
To generate translations, set one of:
|
|
- `GEMINI_API_KEY` for Google Gemini (recommended for cost)
|
|
- `TEXT_API_KEY` for OpenAI-compatible API
|
|
- `TEXT_BASE_URL` for custom OpenAI-compatible endpoints
|
|
|
|
## Files Modified
|
|
|
|
### New Files Created
|
|
- `lib/i18n/` (entire directory)
|
|
- `config.ts` - Locale configuration
|
|
- `client.tsx` - React context provider
|
|
- `server.ts` - Server-side utilities
|
|
- `utils.ts` - Helper functions
|
|
- `locales/zh-CN.ts` - Source translations
|
|
- `locales/en.ts` - English reference
|
|
- `locales/zh-TW.ts` - Traditional Chinese stub
|
|
- `locales/zh-HK.ts` - Hong Kong Chinese stub
|
|
- `locales/ja.ts` - Japanese stub
|
|
- `locales/ko.ts` - Korean stub
|
|
- `locales/es.ts` - Spanish stub
|
|
- `locales/fr.ts` - French stub
|
|
- `locales/de.ts` - German stub
|
|
- `locales/pt-BR.ts` - Portuguese Brazil stub
|
|
- `locales/pt.ts` - Portuguese stub
|
|
- `locales/ru.ts` - Russian stub
|
|
- `locales/it.ts` - Italian stub
|
|
- `locales/vi.ts` - Vietnamese stub
|
|
- `locales/th.ts` - Thai stub
|
|
- `locales/id.ts` - Indonesian stub
|
|
- `locales/tr.ts` - Turkish stub
|
|
- `locales/pl.ts` - Polish stub
|
|
- `locales/nl.ts` - Dutch stub
|
|
- `locales/uk.ts` - Ukrainian stub
|
|
- `locales/hi.ts` - Hindi stub
|
|
- `locales/cs.ts` - Czech stub
|
|
- `components/LanguageSwitcher.tsx` - Language selector component
|
|
- `scripts/translate-i18n.mjs` - Translation script
|
|
- `docs/i18n-implementation.md` - This documentation
|
|
|
|
### Modified Files
|
|
- `app/layout.tsx` - Added I18nProvider wrapper
|
|
- `app/page.tsx` - Added i18n to all strings and LanguageSwitcher
|
|
- `components/CustomForm.tsx` - Added i18n
|
|
- `components/DialogueHistoryModal.tsx` - Added i18n
|
|
- `components/AuthModal.tsx` - Added i18n
|
|
- `components/PlayCanvas.tsx` - Added i18n
|
|
- `components/SettingsModal.tsx` - Added i18n
|
|
|
|
## TypeScript
|
|
|
|
All type definitions are in place. Run `pnpm typecheck` to verify.
|