Internationalization

Built-in multilingual support with English, Spanish, and French translations.

Overview

The player ships with complete translations for all UI elements in 3 languages. You can use the built-in languages, provide custom overrides, or even implement your own complete translation set.

🇺🇸
English
en

Default language

🇪🇸
Español
es

Spanish translation

🇫🇷
Français
fr

French translation

Quick Start

Set the initial language using the initialLanguage prop:

App.tsx
import { GamePlayer } from 'koin.js';

<GamePlayer
  romUrl="/game.nes"
  system="NES"
  title="Super Mario Bros."
  initialLanguage="es"  // Spanish UI
/>

What's Translated

Controls & UI

  • • Play, Pause, Reset buttons
  • • Save/Load controls
  • • Speed, Mute, Recording labels
  • • Fullscreen, Help, Keys
  • • Gamepad connection status

Modals

  • • Keyboard shortcuts reference
  • • Control remapping UI
  • • Gamepad configuration
  • • Save slot manager
  • • BIOS selection
  • • Cheat code browser

Overlays

  • • Loading & error states
  • • Pause screen
  • • Recording indicator
  • • Performance stats
  • • Toast notifications

RetroAchievements

  • • Login form
  • • Achievement browser
  • • Hardcore mode toggle
  • • Connection status
  • • Unlock notifications

Custom Translations

Override specific strings while keeping the rest of the language intact:

Partial Override
import { GamePlayer, en, type KoinTranslations } from 'koin.js';

const customTranslations: Partial<KoinTranslations> = {
  controls: {
    ...en.controls,
    play: 'START GAME',
    save: 'CHECKPOINT',
  },
  notifications: {
    ...en.notifications,
    saved: '💾 Progress Saved!',
  }
};

<GamePlayer
  translations={customTranslations}
/>

Note: Custom translations merge deeply with the base language, so you only need to specify the strings you want to change.

Advanced: Using the Hook

Access translations in custom components using the exported hook:

CustomComponent.tsx
import { useKoinTranslation } from 'koin.js';

function CustomButton() {
  const t = useKoinTranslation();
  
  return (
    <button>
      {t.controls.play}
    </button>
  );
}

Using the Provider

Wrap your custom components with the i18n provider:

App.tsx
import { KoinI18nProvider, es } from 'koin.js';
import CustomButton from './CustomButton';

<KoinI18nProvider translations={es}>
  <CustomButton />
</KoinI18nProvider>

When to Use

The GamePlayer component automatically wraps its children in the provider. Only use KoinI18nProvider directly if you're building custom UI outside of the player component.

Creating a Complete Translation

To add a new language, implement the full KoinTranslations interface:

locales/pt.ts
import { KoinTranslations } from 'koin.js';

export const pt: KoinTranslations = {
  controls: {
    play: 'Jogar',
    pause: 'Pausar',
    reset: 'Reiniciar',
    // ... all other control strings
  },
  notifications: {
    saved: 'Estado salvo',
    loaded: 'Estado carregado',
    // ... all notification strings
  },
  // ... implement all required sections
};

TypeScript Guarantee

The KoinTranslations type ensures you don't miss any strings. TypeScript will error if any required translation key is missing.

> API Reference_

initialLanguage?: 'en' | 'es' | 'fr'

Set the initial UI language (default: 'en')

translations?: RecursivePartial<KoinTranslations>

Partial or complete translation overrides

useKoinTranslation()

React hook to access current translations

KoinI18nProvider

Context provider for custom components

en, es, fr

Built-in translation objects