FiveM script locales: script traducibili con en.lua, ox_lib e ESX

Rendi il tuo script FiveM traducibile: una cartella di locales con en.lua e es.lua, una semplice funzione locale, il sistema di locale di ox_lib, TranslateCap di ESX e un config di lingua.

Il tuo script ha 'You have no money' hard-codificato in quaranta posti. Un proprietario di server a Madrid o Berlino lo vuole nella sua lingua, e l'unico modo è modificare il codice. La soluzione è un livello di locale: le stringhe vivono in file per lingua, il codice chiede chiavi. Questa guida mostra una versione semplice in Lua semplice, quindi il sistema di ox_lib e ESX.

L'idea

Invece di:

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

il codice scrive:

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

e un file di lingua fornisce il testo per no_money. I traduttori quindi modificano i file, mai il codice, e i file di locale aperti possono essere spediti non crittografati (vedi escrow_ignore).

Una semplice funzione di locale in Lua

Layout della cartella:

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, la funzione che cerca una chiave:

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, con i locales per primi e il config prima della funzione:

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'

E in config.lua:

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

Utilizzo, con i placeholder %s riempiti da string.format:

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

I fallback contano: una chiave mancante in es ritorna a en, e una chiave mancante ovunque restituisce la chiave stessa, quindi vedi no_money sullo schermo invece di un errore. Un buco in una traduzione poi si mostra come una chiave visibile, non un crash.

Suggerimento: mantieni le stesse chiavi in ogni file di lingua. Un piccolo script che confronta le chiavi di en con ogni altro file cattura le traduzioni mancanti prima del rilascio.

Il sistema locale di ox_lib

Se il tuo script dipende già da ox_lib, puoi usare i suoi locales integrati invece di scrivere L(). La forma è: carica ox_lib nel manifest, metti le tue traduzioni in una cartella locales/ (ox_lib usa file .json nominati per lingua, come locales/en.json), includili con files, e chiama lib.locale() una volta:

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))

Controlla i documenti di ox_lib per il formato attuale e come la lingua è scelta (una convar del server), perché il layout del file e i nomi delle opzioni sono cambiati tra le versioni. Se vedi ox_lib/init.lua non trovato, correggilo prima: ox_lib init.lua non trovato.

ESX e TranslateCap

Gli script ESX hanno il loro pattern di locale. I file di locale riempiono una tabella Locales e il framework fornisce una funzione di traduzione:

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'))

Gli script più vecchi usano _U('no_money') per la stessa cosa. TranslateCap è il nome attuale in ESX Legacy recente, e la lingua è selezionata da Config.Locale o dall'impostazione propria del framework. Come con ox_lib, controlla i documenti della versione ESX che esegui per i nomi di file esatti e quale delle due funzioni si aspetta.

QBCore ha un modulo simile Lang (locales/en.lua usando Lang:t('key')) che funziona allo stesso modo: una tabella per lingua e una funzione che risolve le chiavi.

Scelta della lingua

Offri una riga di config, vicino all'inizio di config.lua:

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

Se il tuo script è un mix di client, server e NUI, ricorda che il testo NUI ha bisogno delle sue traduzioni: invia le stringhe alla pagina una volta quando si apre, invece di scrivere inglese nell'HTML. Vedi FiveM NUI con React e Vite per passare dati alla pagina.

Elenco di controllo

Sintomo Soluzione
Testo inglese hard-codificato nel codice Spostalo in locales/en.lua e chiama L('key')
attempt to index a nil value su Locales[...] Carica i file locales prima del codice che li legge
La chiave grezza mostra sullo schermo La chiave manca nella lingua scelta e in en
Lingua sbagliata usata Controlla Config.Locale e la convar di locale
ox_lib locale() restituisce la chiave Chiama lib.locale() prima e includi locales/*.json in files
NUI ancora inglese Passa le stringhe tradotte alla pagina

Risposte rapide

Dove dovrei mettere le traduzioni in uno script FiveM?

In una cartella locales/ con un file per lingua, come en.lua e es.lua, caricati prima del codice che li usa. Lo script quindi chiede una chiave, mai una stringa letterale.

ox_lib ha un sistema locale?

Sì. Legge i file locales e ti dà locale('key') dopo aver chiamato lib.locale(). Controlla i documenti di ox_lib per il formato di file attuale e l'impostazione che sceglie la lingua.

Come scelgo la lingua?

Con un valore Config.Locale nel tuo config, o con una convar che il tuo framework o ox_lib legge. Ritorna all'inglese quando una chiave o una lingua manca.

Script senza questo problema

Mic PhoneUn telefono pieghevole che si apre in un tablet e arriva sul telefono vero del giocatore.Vedi script →Shop CreatorCrea un negozio in meno di un minuto — proprietari, dipendenti, casseforti e rapine inclusi.Vedi script →Item Creator V2Crea oggetti utilizzabili con animazioni, props, effetti e altro — senza scrivere codice.Vedi script →

Continua a leggere