Internationalization¶
Five-language i18next setup spanning the player client, admin UI, AI dialogue, and translation-management endpoints. Translations ship as bundled JSON namespaces and are also exposed via a database-backed admin API for live editing.
1. Languages¶
| Language | Code | Keys | Status |
|---|---|---|---|
| English | en |
510 | Base (100%) |
| Spanish | es |
510 | Complete (100%) |
| French | fr |
510 | Complete (100%) |
| Chinese Simplified | zh |
510 | Complete (100%) |
| Portuguese | pt |
510 | Complete (100%, Brazilian conventions) |
Total: ~2,040 translations across 4 namespaces (common, auth, admin, game).
Translations were authored via AI linguistic generation and adapted for gaming terminology (e.g. Comandante / Commandant / 指挥官 / Comandante; Nave Exploradora / Vaisseau Éclaireur / 侦察船 / Nave Explorador).
2. File layout¶
shared/i18n/
├── config.ts # unified i18next config
├── index.ts # main module
├── locales/ # `common` namespace per language
│ ├── en.json (121 keys)
│ ├── es.json, fr.json, zh.json, pt.json
└── namespaces/ # other namespaces
├── auth.json (69 keys)
├── admin.json (154 keys)
├── game.json (166 keys)
├── es/ { auth.json, admin.json, game.json }
├── fr/ { ... }
├── zh/ { ... }
└── pt/ { ... }
Per-language frontend wiring lives at:
- services/admin-ui/src/i18n.ts and components/common/LanguageSwitcher.tsx
- services/player-client/src/i18n.ts and components/common/LanguageSwitcher.tsx
Both apps use i18next 23.16, react-i18next 13.5, the http-backend, and the browser language detector.
3. Backend¶
Service & models¶
services/gameserver/src/models/translation.py—languages,translation_keys,user_language_preferencestables.services/gameserver/src/services/translation_service.py— fallback handling, caching, user-preference persistence.services/gameserver/src/services/multilingual_ai_service.py— multilingual context for AI responses.
API (/api/v1/i18n/)¶
Public
| Method | Path | Purpose |
|--------|------|---------|
| GET | /i18n/languages | List supported languages |
| GET | /i18n/detect | Auto-detect from request |
| GET | /i18n/{lang} | All translations for a language |
| GET | /i18n/{lang}/{namespace} | Namespace-scoped translations |
User
| Method | Path | Purpose |
|--------|------|---------|
| GET | /i18n/user/preference | Get preferred language |
| POST | /i18n/user/preference | Set preferred language |
| GET | /i18n/user/ai-context | Get AI language context |
Admin
| Method | Path | Purpose |
|--------|------|---------|
| GET | /i18n/admin/progress/{lang} | Translation completion |
| POST | /i18n/admin/translation/{lang}/{ns} | Update single translation |
| POST | /i18n/admin/bulk/{lang}/{ns} | Bulk import |
| POST | /i18n/admin/initialize | Initialize system |
13 translation endpoints in total per the API inventory.
Database¶
languages(id, code, name, native_name, direction, is_active, completion_percentage)
translation_keys(id, key, language_id, namespace_id, value, context, is_verified)
user_language_preferences(id, user_id, language_id, manual_override)
4. Adding new translatable content¶
1. Pick a namespace¶
common (shared UI), auth, admin, game, plus reserved-but-not-yet-loaded ai, marketing, errors, validation.
2. Add the key¶
Add to the English base file (e.g. shared/i18n/namespaces/admin.json):
{
"newFeature": {
"title": "New Feature",
"description": "Description of the new feature",
"actions": { "enable": "Enable", "disable": "Disable" }
}
}
3. Use it in components¶
import { useTranslation } from 'react-i18next';
const { t } = useTranslation('admin');
return <h2>{t('newFeature.title')}</h2>;
Patterns:
- Interpolation: t('welcome', { name: 'John' })
- Pluralization: t('items', { count: 5 })
- Fallback: t('key', { defaultValue: 'Default' })
4. Push to the database (optional)¶
curl -X POST /api/v1/i18n/admin/bulk/en/admin \
-H "Authorization: Bearer $TOKEN" \
-d '{"translations": {...}, "overwrite": true}'
The database path supports admin-managed dynamic translations; the file path is the day-to-day default for static text bundles.
5. Translator workflow¶
Admin UI¶
- Log into admin with translator permissions.
- Settings → Translation Management.
- Pick language + namespace.
- Edit; check "Verified" once reviewed.
Direct API¶
curl -X POST /api/v1/i18n/admin/translation/es/admin \
-H "Authorization: Bearer $TOKEN" \
-d '{
"key": "dashboard.title",
"value": "Panel de Control Central",
"context": "Main dashboard page title"
}'
Quality bar¶
- Translate meaning, not words.
- Use established gaming terminology.
- Watch character-length constraints on UI elements.
- Preserve tone / formality per language conventions.
- Test in actual interface.
Per-language conventions¶
| Language | Notes |
|---|---|
| Spanish | Formal usted for system messages; balance formal/informal in UI; consider regional variants |
| French | Maintain language purity; correct accent marks; formal address; consider French-Canadian forks if needed |
| Chinese | Simplified character set; appropriate formality; gaming-context terminology |
| Portuguese | Brazilian conventions by default; gaming idioms |
6. Community contributions¶
- Create account, request translator permissions.
- Complete style-guide training.
- Start with simple/common translations.
- Peer review in language teams.
- Native-speaker validation before promoting to verified.
Recognition: translation credits, language-team leaderboards, contributor badges.
7. Progress tracking¶
curl -X GET /api/v1/i18n/admin/progress/es \
-H "Authorization: Bearer $TOKEN"
Returns completion %, verified vs unverified counts, per-namespace breakdown, last-updated timestamps.
8. Tooling¶
Translator-side helpers in the gameserver/web repos:
npm run extract-strings— scan source fort('…')calls and emit a draft key list.npm run validate-translations— verify every translation file has the same key shape as the English base.
Right-to-left languages are not currently in scope; adding one (e.g. Arabic) will require RTL layout work in both UIs.