Locales de script em FiveM: scripts traduzíveis com en.lua, ox_lib e ESX
Torne seu script FiveM traduzível: uma pasta locales com en.lua e es.lua, uma função locale simples, sistema de locale de ox_lib, ESX TranslateCap e uma configuração de idioma.
Seu script tem 'You have no money' codificado em quarenta lugares. Um dono de servidor em Madrid ou Berlin quer em seu idioma, e a única maneira é editar o código. A solução é uma camada locale: strings vivem em arquivos por idioma, o código pede por chaves. Este guia mostra uma versão simples em Lua simples, depois o sistema de ox_lib e ESX.
A ideia
Em vez de:
ESX.ShowNotification('You have no money')o código escreve:
ESX.ShowNotification(L('no_money'))e um arquivo de idioma fornece o texto para no_money. Tradutores então mudam arquivos, nunca código, e arquivos de locale abertos podem ser enviados sem criptografia (veja escrow_ignore).
Uma função locale simples em Lua
Layout de pasta:
my_script/
fxmanifest.lua
config.lua
locales/
en.lua
es.lua
shared/locale.lualocales/en.lua:
Locales = Locales or {}
Locales['en'] = {
no_money = 'You have no money',
bought = 'You bought %s for $%s',
}locales/es.lua:
Locales = Locales or {}
Locales['es'] = {
no_money = 'No tienes dinero',
bought = 'Compraste %s por $%s',
}shared/locale.lua, a função que procura uma chave:
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
endManifesto, com as locales primeiro e a configuração antes da função:
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 em config.lua:
Config = {}
Config.Locale = 'en'Uso, com placeholders %s preenchidos por string.format:
print(L('bought', 'bread', 5)) -- You bought bread for $5Os fallbacks importam: uma chave faltando em es volta para en, e uma chave faltando em qualquer lugar retorna a chave em si, então você vê no_money na tela em vez de um erro. Um buraco em uma tradução então aparece como uma chave visível, não uma falha.
Dica: mantenha as mesmas chaves em cada arquivo de idioma. Um pequeno script que compara as chaves
encom cada outro arquivo captura traduções faltando antes do lançamento.
Sistema de locale de ox_lib
Se seu script já depende de ox_lib, você pode usar seus locales integrados em vez de escrever L(). A forma é: carregue ox_lib no manifesto, coloque suas traduções em uma pasta locales/ (ox_lib usa arquivos .json nomeados por idioma, como locales/en.json), inclua-os com files, e chame lib.locale() uma vez:
-- fxmanifest.lua
shared_script '@ox_lib/init.lua'
files { 'locales/*.json' }{
"no_money": "You have no money",
"bought": "You bought %s for $%s"
}lib.locale() -- load the language
lib.notify({ description = locale('no_money'), type = 'error' })
print(locale('bought', 'bread', 5))Verifique os docs de ox_lib para o formato atual e para como o idioma é escolhido (uma convar do servidor), porque o layout de arquivo e nomes de opção mudaram entre versões. Se você vê ox_lib/init.lua não encontrado, corrija primeiro: ox_lib init.lua not found.
ESX e TranslateCap
Scripts ESX têm seu próprio padrão de locale. Arquivos de locale preenchem uma tabela Locales e o framework fornece uma função de tradução:
-- fxmanifest.lua
shared_scripts {
'@es_extended/imports.lua',
'@es_extended/locale.lua',
'locales/*.lua',
'config.lua',
}-- locales/en.lua
Locales['en'] = {
['no_money'] = 'You have no money',
}TriggerEvent('esx:showNotification', TranslateCap('no_money'))Scripts antigos usam _U('no_money') para a mesma coisa. TranslateCap é o nome atual em ESX Legacy recente, e o idioma é selecionado por Config.Locale ou configuração própria do framework. Como com ox_lib, verifique os docs da versão ESX que você executa para os nomes de arquivo exatos e qual das duas funções espera.
QBCore tem um módulo Lang similar (locales/en.lua usando Lang:t('key')) que funciona da mesma forma: uma tabela por idioma e uma função que resolve chaves.
Escolhendo o idioma
Ofereça uma linha de configuração, perto do topo de config.lua:
Config.Locale = 'en' -- 'en', 'es', 'fr'...Se seu script é uma mistura de cliente, servidor e NUI, lembre-se de que texto NUI precisa de suas próprias traduções: envie as strings para a página uma vez quando ela abre, em vez de escrever inglês no HTML. Veja FiveM NUI with React and Vite para passar dados para a página.
Lista de verificação
| Sintoma | Solução |
|---|---|
| Texto inglês codificado em código | Mova para locales/en.lua e chame L('key') |
attempt to index a nil value em Locales[...] |
Carregue arquivos de locale antes do código que os lê |
| Chave bruta mostra na tela | A chave está faltando no idioma escolhido e em en |
| Idioma errado usado | Verifique Config.Locale e a convar de locale |
ox_lib locale() retorna a chave |
Chame lib.locale() primeiro e inclua locales/*.json em files |
| NUI ainda em inglês | Passe as strings traduzidas para a página |
Respostas rápidas
Onde devo colocar traduções em um script FiveM?
Em uma pasta locales/ com um arquivo por idioma, como en.lua e es.lua, carregados antes do código que os usa. O script então pede por uma chave, nunca por uma string literal.
ox_lib tem um sistema de locale?
Sim. Ele lê arquivos de locale e oferece locale('key') após você chamar lib.locale(). Verifique os docs de ox_lib para o formato de arquivo atual e a configuração que escolhe o idioma.
Como escolho o idioma?
Com um valor Config.Locale em sua configuração, ou com uma convar que seu framework ou ox_lib lê. Volte para inglês quando uma chave ou um idioma estiver faltando.
Scripts sem esse problema
Mic PhoneUm celular dobrável que abre em tablet e chega ao celular de verdade do jogador.Ver script →
Shop CreatorMonte uma loja em menos de um minuto — donos, funcionários, cofres e assaltos inclusos.Ver script →
Item Creator V2Crie itens usáveis com animações, props, efeitos e muito mais — sem escrever código.Ver script →