Skip to content

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.pylanguages, translation_keys, user_language_preferences tables.
  • 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

  1. Log into admin with translator permissions.
  2. Settings → Translation Management.
  3. Pick language + namespace.
  4. 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

  1. Create account, request translator permissions.
  2. Complete style-guide training.
  3. Start with simple/common translations.
  4. Peer review in language teams.
  5. 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 for t('…') 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.