FiveM Script-Locales: Übersetzbare Skripte mit en.lua, ox_lib und ESX

Mache dein FiveM-Skript übersetzbar: ein Locales-Ordner mit en.lua und es.lua, eine einfache Locale-Funktion, ox_lib's Locale-System, ESX TranslateCap und eine Sprach-Config.

Dein Skript hat 'You have no money' hart an vierzig Stellen kodiert. Ein Server-Besitzer in Madrid oder Berlin möchte es in seiner Sprache, und der einzige Weg ist, den Code zu bearbeiten. Die Behebung ist eine Locale-Schicht: Strings leben in Pro-Sprache-Dateien, der Code fragt nach Schlüsseln. Diese Anleitung zeigt eine einfache Plain-Lua-Version, dann ox_lib's System und ESX's.

Die Idee

Anstelle von:

lua
ESX.ShowNotification('You have no money')

der Code schreibt:

lua
ESX.ShowNotification(L('no_money'))

und eine Sprachdatei liefert den Text für no_money. Übersetzer ändern dann Dateien, nie Code, und offene Locale-Dateien können unverschlüsselt versandt werden (siehe escrow_ignore).

Eine Plain Lua Locale-Funktion

Ordner-Layout:

text
my_script/
  fxmanifest.lua
  config.lua
  locales/
    en.lua
    es.lua
  shared/locale.lua

locales/en.lua:

lua
Locales = Locales or {}

Locales['en'] = {
    no_money = 'You have no money',
    bought   = 'You bought %s for $%s',
}

locales/es.lua:

lua
Locales = Locales or {}

Locales['es'] = {
    no_money = 'No tienes dinero',
    bought   = 'Compraste %s por $%s',
}

shared/locale.lua, die Funktion, die einen Schlüssel aufschlägt:

lua
function L(key, ...)
    local lang = Locales[Config.Locale] or Locales['en']
    local text = lang[key] or Locales['en'][key] or key
    if select('#', ...) > 0 then
        return text:format(...)
    end
    return text
end

Manifest, mit den Locales zuerst und der Config vor der Funktion:

lua
fx_version 'cerulean'
game 'gta5'

shared_scripts {
    'config.lua',
    'locales/*.lua',
    'shared/locale.lua',
}
client_script 'client/main.lua'
server_script 'server/main.lua'

Und in config.lua:

lua
Config = {}
Config.Locale = 'en'

Verwendung, mit %s Platzhaltern, die von string.format gefüllt werden:

lua
print(L('bought', 'bread', 5))   -- You bought bread for $5

Die Fallbacks sind wichtig: ein fehlender Schlüssel in es fällt zu en zurück, und ein fehlender Schlüssel überall gibt den Schlüssel selbst zurück, daher siehst du no_money auf dem Bildschirm statt eines Fehlers. Ein Loch in einer Übersetzung zeigt sich dann als ein sichtbarer Schlüssel, nicht ein Absturz.

Tipp: Behalte die gleichen Schlüssel in jeder Sprachdatei. Ein kleines Skript, das die en Schlüssel mit jeder anderen Datei vergleicht, fängt fehlende Übersetzungen vor der Veröffentlichung.

ox_lib's Locale-System

Wenn dein Skript bereits ox_lib abhängig ist, kannst du sein eingebautes Locales statt L() schreiben verwenden. Die Form ist: Lade ox_lib im Manifest, lege deine Übersetzungen in einen locales/ Ordner (ox_lib nutzt .json Dateien, die nach Sprache benannt sind, wie locales/en.json), include sie mit files, und rufe lib.locale() einmal auf:

lua
-- fxmanifest.lua
shared_script '@ox_lib/init.lua'
files { 'locales/*.json' }
json
{
  "no_money": "You have no money",
  "bought": "You bought %s for $%s"
}
lua
lib.locale()   -- load the language

lib.notify({ description = locale('no_money'), type = 'error' })
print(locale('bought', 'bread', 5))

Überprüfe die ox_lib docs für das aktuelle Format und wie die Sprache ausgewählt wird (ein Server-Convar), da die Datei-Layout und Optionsnamen sich zwischen Versionen geändert haben. Wenn du ox_lib/init.lua nicht gefunden siehst, behebe das zuerst: ox_lib init.lua nicht gefunden.

ESX und TranslateCap

ESX-Skripte haben ihr eigenes Locale-Muster. Locale-Dateien füllen eine Locales Tabelle und das Framework liefert eine Übersetzungs-Funktion:

lua
-- fxmanifest.lua
shared_scripts {
    '@es_extended/imports.lua',
    '@es_extended/locale.lua',
    'locales/*.lua',
    'config.lua',
}
lua
-- locales/en.lua
Locales['en'] = {
    ['no_money'] = 'You have no money',
}
lua
TriggerEvent('esx:showNotification', TranslateCap('no_money'))

Ältere Skripte nutzen _U('no_money') für das gleiche. TranslateCap ist der aktuelle Name in neuen ESX Legacy, und die Sprache wird durch Config.Locale oder die Einstellung des Frameworks selbst ausgewählt. Wie mit ox_lib, überprüfe die Docs der ESX-Version, die du ausführst, für die exakten Dateinamen und welche der zwei Funktionen es erwartet.

QBCore hat ein ähnliches Lang Modul (locales/en.lua nutzt Lang:t('key')), das gleich funktioniert: eine Tabelle pro Sprache und eine Funktion, die Schlüssel auflöst.

Wähle die Sprache

Biete eine Config-Zeile an, in der Nähe der Oberseite von config.lua:

lua
Config.Locale = 'en'   -- 'en', 'es', 'fr'...

Wenn dein Skript eine Mischung aus Client, Server und NUI ist, denke daran, dass NUI-Text seine eigenen Übersetzungen braucht: Sende die Strings an die Seite einmal, wenn sie sich öffnet, statt Englisch in den HTML zu schreiben. Siehe FiveM NUI mit React und Vite um Daten an die Seite zu übergeben.

Checkliste

Symptom Behebung
Englischer Text hart-kodiert in Code Verschiebe ihn zu locales/en.lua und rufe L('key') auf
attempt to index a nil value auf Locales[...] Lade Locale-Dateien vor dem Code, der sie liest
Roher Schlüssel zeigt auf dem Bildschirm Der Schlüssel fehlt in der gewählten Sprache und in en
Falsche Sprache verwendet Überprüfe Config.Locale und den Locale-Convar
ox_lib locale() gibt den Schlüssel zurück Rufe lib.locale() zuerst auf und include locales/*.json in files
NUI immer noch Englisch Übergebe die übersetzten Strings an die Seite

Kurze Antworten

Wo sollte ich Übersetzungen in einem FiveM-Skript ablegen?

In einem locales/ Ordner mit einer Datei pro Sprache, wie en.lua und es.lua, geladen bevor der Code, der sie verwendet, geladen wird. Das Skript fragt dann nach einem Schlüssel, nie nach einem wörtlichen String.

Hat ox_lib ein Locale-System?

Ja. Es liest Locale-Dateien und gibt dir locale('key') nach dem Aufrufen von lib.locale(). Überprüfe die ox_lib Docs für das aktuelle Dateiformat und die Einstellung, die die Sprache aussucht.

Wie wähle ich die Sprache?

Mit einem Config.Locale Wert in deiner Config, oder mit einem Convar, den dein Framework oder ox_lib liest. Fallen Sie zu Englisch zurück, wenn ein Schlüssel oder eine Sprache fehlt.

Scripts ohne dieses Problem

Mic PhoneEin faltbares Handy, das sich zum Tablet aufklappt und bis aufs echte Handy des Spielers reicht.Script ansehen →Shop CreatorBau einen Shop in unter einer Minute — Besitzer, Angestellte, Tresore und Überfälle inklusive.Script ansehen →Item Creator V2Erstelle nutzbare Items mit Animationen, Props, Effekten und mehr — ganz ohne Code.Script ansehen →

Weiterlesen