Skip to content

Translation System

Artmines edited this page Nov 17, 2025 · 1 revision

Translation System

QC-AdvancedMedic features a complete multi-language translation system supporting English, French, and Spanish out of the box.

How It Works

The system uses a unified locale approach where both Lua scripts and NUI (React UI) share the same translation source:

  1. JSON locale files in locales/ folder (en.json, fr.json, es.json)
  2. config.lua loads the selected locale into Config.Strings
  3. Lua scripts use locale('key') function
  4. NUI components receive translations object via SendNUIMessage

Setting the Language

Edit config.lua and change Config.Locale:

-- Language/Locale Settings (change to 'en', 'fr', or 'es')
Config.Locale = 'fr'  -- Options: 'en', 'fr', 'es'

The system will automatically:

  • Load the corresponding JSON file (e.g., locales/fr.json)
  • Display all UI text in that language
  • Show notifications in that language
  • Update NUI panels in that language

Available Languages

Language Code Keys Status
English en 376 ✅ Complete
French fr 376 ✅ Complete
Spanish es 376 ✅ Complete

For Developers

Using Translations in Lua

-- Simple usage
lib.notify({ title = locale('cl_error'), type = 'error' })

-- With string formatting
local message = string.format(locale('sv_purchased_items'), quantity, itemName, price)
-- Output: "Purchased 5x Bandage for $25"

-- With fallback
local text = locale('some_key') or 'Default Text'

Using Translations in NUI

All NUI components receive a translations prop with all locale strings:

// DeathScreen.tsx, InspectionPanel.tsx, MedicalPanel.tsx
interface ComponentProps {
  translations?: { [key: string]: string };
}

const Component: React.FC<ComponentProps> = ({ translations }) => {
  return (
    <div>
      <h1>{translations?.cl_death_disabled || 'Disabled'}</h1>
      <p>{translations?.cl_death_wait_medic || 'Wait to call medic'}</p>
    </div>
  );
};

How translations reach NUI:

-- client.lua (or server file)
SendNUIMessage({
    type = 'show-death-screen',
    data = {
        message = "...",
        seconds = 300,
        translations = Config.Strings  -- Send all locale strings
    }
})
// App.tsx receives and passes to components
<DeathScreen
  message={state.deathScreenData.message}
  translations={state.deathScreenData.translations}  // Pass to component
/>

Adding a New Language

  1. Create locale file: locales/xx.json (where xx is language code)

  2. Copy structure from en.json:

{
    "cl_error": "Error",
    "cl_success": "Success",
    ...
}
  1. Translate all 376 keys - maintain format strings (%s, %d, %.1f)

  2. Test thoroughly - check Lua notifications and all 3 NUI panels

Translation Key Naming Convention

Keys use prefixes to indicate where they're used:

  • cl_* - Client-side notifications/UI
  • sv_* - Server-side notifications
  • ui_* - NUI interface text
  • wound_* - Wound descriptions
  • treatment_* - Treatment messages
  • mission_* - Mission system
  • fracture_* - Fracture/injury system
  • bodyPart_* - Body part names
  • tool_* - Medical tool names

Format String Examples

When translating, preserve format placeholders:

{
    "sv_purchased_items": "Purchased %dx %s for $%d",
    "sv_final_duty_pay_earned": "Earned $%d for %.1f minutes",
    "sv_doctor_examining": "Dr. %s is examining you"
}

French translation:

{
    "sv_purchased_items": "Acheté %dx %s pour $%d",
    "sv_final_duty_pay_earned": "Gagné %d$ pour %.1f minutes",
    "sv_doctor_examining": "Dr. %s vous examine"
}

Locale System Architecture

┌─────────────────────────────────────────┐
│         locales/en.json (376 keys)      │
│         locales/fr.json (376 keys)      │
│         locales/es.json (376 keys)      │
└─────────────────┬───────────────────────┘
                  │
                  ▼
        ┌─────────────────────┐
        │    config.lua        │
        │ LoadLocaleStrings()  │
        │ → Config.Strings     │
        └──────────┬───────────┘
                   │
        ┌──────────┴──────────┐
        │                     │
        ▼                     ▼
┌──────────────┐    ┌─────────────────┐
│  Lua Scripts │    │  NUI Components │
│ locale(key)  │    │  translations?. │
└──────────────┘    └─────────────────┘

Important Notes

  1. Format strings must match across all languages (same %s, %d positions)
  2. All 3 NUI panels (DeathScreen, InspectionPanel, MedicalPanel) use the same translation pattern
  3. Server console shows locale loading: [QC-AdvancedMedic] Loaded fr locale with 376 strings
  4. Missing keys will fall back to English or show the key name
  5. Restart required - locale changes require full server restart

Troubleshooting

Seeing "Loaded XX locale with 0 strings"?

  • Check JSON syntax (valid comma placement, closing braces)
  • Verify file encoding is UTF-8
  • Ensure Config.Locale matches filename (case-sensitive)

NUI still showing English?

  • Check browser console (F12) for errors
  • Verify translations prop is being passed to components
  • Rebuild NUI: cd ui && bun run build

Lua showing wrong language?

  • Verify config.lua has Config.Locale = 'fr' (or your language)
  • Check locale files are in locales/ folder
  • Restart the resource completely

Contributing Translations

Want to add a new language? We accept pull requests!

  1. Fork the repository
  2. Create locales/yourlang.json with all 376 keys translated
  3. Test all NUI panels and Lua notifications
  4. Submit PR with language name and your credits

Translation credits:

  • English: Quantum Projects Community
  • French: Quantum Projects Community
  • Spanish: Quantum Projects Community

Questions? Open an issue on GitHub or check the Configuration guide.

📖 QC-AdvancedMedic

🏠 Home


📚 Documentation

  1. Architecture
  2. Client Systems
  3. Server Systems
  4. Database Schema

⚙️ Configuration

  1. Configuration
  2. Translation System
  3. API Reference

🛠️ Development

  1. Extending the System
  2. Performance Optimization

⚠️ Support

  1. Known Issues

🔗 Links


v0.3.1-alpha

Clone this wiki locally