
Come tradurre gli script utilizzando l'intelligenza artificiale (guida FiveM)
Gli script gratuiti vanno bene per controlli rapidi. Per server in produzione, confronta pacchetti server completi o script a pagamento mantenuti, in base al framework e al caso d'uso.
Pubblico: Proprietari di server FiveM, programmatori e manutentori che desiderano traduzioni di alta qualità senza danneggiare segnaposto o interfaccia utente.
In breve
- Centralizzare tutto il testo nei file locali (tabelle JSON o Lua). Non codificare mai le stringhe nella logica di gioco.
- Proteggi i segnaposto (ad esempio,
%s,%d,%{nome},{0},~r~,^1) durante la traduzione. - Utilizzare l'intelligenza artificiale per la traduzione di prima passata + glossario + controlli automatici → rapida revisione umana → spedizione.
- Mantieni un'unica fonte di verità (solitamente l'inglese), diff per le modifiche e rigenera solo le chiavi modificate.
Perché tradurre i tuoi script FiveM
- Accessibilità e crescita: I server localizzati attraggono più giocatori e li mantengono coinvolti.
- Professionalità: Terminologia coerente tra comandi, interfacce utente e messaggi di errore.
- Adatto ai collaboratori: Una struttura locale chiara incoraggia le relazioni pubbliche della comunità.
Se hai bisogno di un ripasso di base sulla struttura e sulle migliori pratiche, consulta: Come tradurre gli script FiveM (nel modo giusto).
Architettura: il modo giusto per localizzare
Obiettivo: Nessuna stringa visibile all'utente all'interno del codice di gioco. Instrada tutto attraverso un livello locale.
Disposizione delle risorse consigliata
my_resource/ ├─ fxmanifest.lua ├─ locales/ │ ├─ en.json # lingua sorgente (unica fonte di verità) │ ├─ de.json # tradotto (generato/modificato) │ ├─ es.json # tradotto (generato/modificato) │ └─ qa.rules.json # facoltativo: segnaposto whitelist e controlli ├─ client/ │ └─ main.lua ├─ server/ │ └─ main.lua └─ shared/ └─ i18n.lua # assistente di traduzione
fxmanifest.lua (esempio minimo)
fx_version 'cerulean' gioco 'gta5' lua54 'yes' shared_scripts { 'shared/i18n.lua', } file { 'locales/*.json' }
condiviso/i18n.lua (caricatore leggero + sostituzione segnaposto)
LOCALE locale = GetConvar('my_locale', 'en') CACHE locale = {} funzione locale loadJSON(percorso) file locale = io.open(percorso, 'r') se non è un file allora restituisci {} fine contenuto locale = file:read('*a') file:close() ok locale, dati = pcall(function() return json.decode(contenuto) fine) restituisci ok e dati o {} fine funzione locale readLocale(lang) se CACHE[lang] allora restituisci CACHE[lang] fine file locale = ('locales/%s.json'):format(lang) dizionario locale = loadJSON(file) CACHE[lang] = dizionario restituisci dizionario fine funzione locale interpolate(str, vars) se non è un file allora restituisci str fine per k, v in coppie(vars) fai str = str:gsub('%%{'..k..'}', tostring(v)) -- %{name} fine ritorno str fine funzione _U(key, vars) local dict = readLocale(LOCALE) local src = dict[key] se non è src allora -- fallback all'inglese se manca src = readLocale('en')[key] o key fine ritorno interpolate(src, vars) fine exports('Translate', _U)
Utilizzo nel codice client/server
-- Client lib.notify({ title = _U('notify_title'), description = _U('welcome_player', { name = GetPlayerName(PlayerId()) }), }) -- Server print(('[MyRes] %s'):format(_U('server_started')))
locales/en.json (fonte)
{ "notify_title": "Messaggio del server", "welcome_player": "Benvenuto, %{name}!", "server_started": "Il modulo server è pronto.", "no_permission": "Non hai l'autorizzazione.", "items_remaining": "%{count} elementi rimanenti" }
Flusso di lavoro di traduzione AI (veloce e sicuro)
- Estrai e congela la fonte
- Mantenere Inglese (o la tua fonte) come
locales/en.json. - Applicare la denominazione delle chiavi:
dominio.azione.soggetto(per esempio,inventario.rilascia.conferma).
- Creare/estendere un glossario
- Mappa CSV o JSON dei termini canonici → termini di destinazione. Esempio:
fonte,bersaglio EMS,Rettungsdienst PD,Polizei Mechanic,Mechaniker
- Proteggi segnaposto e markup
- Segnaposto:
%{nome},%s,%d,{0} - Codici colore FiveM:
~r~,~g~,~s~; codici chat:^1,^2 - Tag NUI/HTML:
<b>,<span>…
- Traduci tramite API (lotto)
- Inviare valori solo, mantieni chiavi invariato.
- Fornitura glossario E stile (tono) al modello/motore.
- Controllo qualità automatizzato
- Convalida JSON.
- Verificare parità segnaposto (ogni segnaposto nella sorgente esiste anche nella destinazione).
- Segnala le modifiche vietate (ad esempio, codici colore modificati o punteggiatura aggiunta quando non consentita).
- Controllo a campione umano (5–10 minuti)
- Esaminare i comandi, i messaggi di errore e le stringhe lunghe dell'interfaccia utente.
- Spedire e ripetere
- Mantieni un memoria di traduzione (output precedenti) per evitare di ritradurre le chiavi non modificate.
Guardrail: suggerimenti e regole che funzionano davvero
Richiesta LLM per la traduzione batch JSON
Attività: tradurre i valori JSON dall'inglese all'inglese per un contesto FiveM/GTA RP. Regole: - MANTENERE LE CHIAVI INVARIATE. - MANTENERE tutti i segnaposto esattamente: %{var}, %s, %d, {0}, ~r~, ~g~, ^1, ^2, ecc. - Mantenere invariate le maiuscole e i token di stile del codice (comandi, comandi /slash). - Non aggiungere virgolette, punteggiatura aggiuntiva o modificare il significato. - Restituire SOLO JSON valido con la stessa struttura. JSON da tradurre:
Espressione regolare che puoi usare in uno script QA
- Segnaposto:
%%\{[A-Za-z0-9_]+\} - C printf:
%(?:\d+\$)?[sdif] - Codici chat:
\^\d - Codici colore tilde:
~[rgbso]~
Esempio: tradurre con DeepL (Node.js)
Ideale per lavori una tantum o CI.
package.json (script)
{ "type": "module", "scripts": { "i18n:translate:de": "node tools/translate-deepl.js en de", "i18n:check": "node tools/i18n-check.js" } }
strumenti/traduci-deepl.js
importa fs da 'fs'; importa percorso da 'percorso'; importa assert da 'assert'; importa fetch da 'node-fetch'; const [,, srcLang, dstLang] = process.argv; const apiKey = process.env.DEEPL_API_KEY; // impostato in CI/ENV assert(apiKey, 'DEEPL_API_KEY è obbligatorio'); const src = JSON.parse(fs.readFileSync('locales/en.json', 'utf8')); const out = {}; const GLOSSARIO = { 'EMS': 'Servizio di soccorso', 'PD': 'Polizia', }; function protect(str){ // Sostituisci i segnaposto con i token che DeepL non modificherà return str .replace(/%\{([^}]+)\}/g, '⟦$1⟧') .replace(/%s/g, '⟪S⟫') .replace(/%d/g, '⟪D⟫'); } function restore(str){ return str .replace(/⟦([^⟧]+)⟧/g, '%{$1}') .replace(/⟪S⟫/g, '%s') .replace(/⟪D⟫/g, '%d'); } funzione asincrona translate(testo){ const res = await fetch('https://api.deepl.com/v2/translate', { metodo: 'POST', intestazioni: { 'Content-Type': 'application/x-www-form-urlencoded' }, corpo: new URLSearchParams({ auth_key: apiKey, testo: testo, source_lang: srcLang.toUpperCase(), target_lang: dstLang.toUpperCase(), formalità: 'prefer_more' }) }); const json = await res.json(); if (!json.translations) throw new Error(JSON.stringify(json)); return json.translations[0].text; } for (const [k, v] of Object.entries(src)) { const protectedText = protect(v); // Pre-passaggio al glossario (semplice): let glossed = protectedText; for (const [from, to] of Object.entries(GLOSSARY)) { glossed = glossed.replace(new RegExp(`\\b${from}\\b`, 'g'), to); } // Traduci // eslint-disable-next-line no-await-in-loop const tr = await translate(glossed); out[k] = restore(tr); } fs.writeFileSync(`locales/${dstLang}.json`, JSON.stringify(out, null, 2)); console.log(`Ha scritto locales/${dstLang}.json`);
strumenti/i18n-check.js (parità segnaposto)
importa fs da 'fs'; const src = JSON.parse(fs.readFileSync('locales/en.json', 'utf8')); const dst = JSON.parse(fs.readFileSync('locales/de.json', 'utf8')); const reVar = /%\{[^}]+\}/g; const reS = /%s/g; const reD = /%d/g; lascia ok = vero; per (const k di Object.keys(src)) { const a = (src[k].match(reVar)||[]).length === (dst[k]?.match(reVar)||[]).length; const b = (src[k].match(reS)||[]).length === (dst[k]?.match(reS)||[]).length; const c = (src[k].match(reD)||[]).length === (dst[k]?.match(reD)||[]).length; if (!(a && b && c)) { console.error('Segnaposto non corrispondente per la chiave:', k); ok = false; } } process.exit(ok ? 0 : 1);
Utilizzo efficace degli LLM (OpenAI/altri)
- Suddividi per argomento/dominio per un contesto migliore (ad esempio, inventario, polizia, posti di lavoro).
- Fornire brevi descrizioni per gruppo (due righe) per definire il tono e il pubblico.
- Pochi esempi sparati: 2–3 coppie tradotte correttamente con segnaposto migliorano la coerenza.
- Politica di ripetizione: rieseguire solo le chiavi non riuscite contrassegnate da
i18n-controllo.
Modello di pochi scatti (sistema + utente)
Sistema: traduci le stringhe dell'interfaccia utente del gioco FiveM per . - Mantieni le chiavi invariate, conserva i segnaposto, mantieni il tono conciso. Esempi utente: EN: "Hai %{count} multe." DE: "Hai ricevuto %{count} multe." EN: "~r~Errore:~s~ Non hai l'autorizzazione." DE: "~r~Errore:~s~ Hai ricevuto l'autorizzazione." Ora traduci i seguenti valori JSON dall'inglese a Restituisce solo JSON valido:
Traduzioni NUI (HTML/JS)
Per le interfacce utente dei browser, una libreria lato client è pratica.
Approccio consigliato
- Utilizzare un bundle JSON per lingua in
web/locali/ .json. - Carica con il tuo framework UI ed esponi un
t(chiave, variabili)aiutante. - Mantieni il stesse chiavi come impostazioni locali del server per ridurre il carico cognitivo.
Helper JS minimo
const dict = await (await fetch(`/locales/${lang}.json`)).json(); export function t(key, vars){ let s = dict[key] || key; for (const [k,v] of Object.entries(vars||{})) s = s.replace(`%{${k}}`, v); return s; }
Specifiche ESX/QBCore
- Molti script ESX vengono spediti
locales/en.lua,locales/de.luacon un_Uaiutante. - Se si utilizzano tabelle Lua per le impostazioni locali, mantenere uno stile nel tuo repository. Combinare JSON e Lua per la stessa risorsa aumenta i costi di manutenzione.
- QBCore utilizza spesso messaggi basati sulla configurazione. Migra le stringhe ripetute nei file locali per evitare divergenze.
Impostazioni locali della tabella Lua (se preferisci Lua a JSON)
Locales = Locales or {} Locales['en'] = { no_permission = 'Non hai i permessi.', Welcome_player = 'Benvenuto, %{name}!' } Locales['de'] = { no_permission = 'Du hast keine Berechtigung.', Welcome_player = 'Willkommen, %{name}!' }
Controlli di qualità prima della spedizione
- Controllo di analisi JSON/Lua in CI.
- Parità segnaposto (le espressioni regolari verificano come mostrato).
- Modifiche vietate: non consentire modifiche a
/comandi, lettere di scelta rapida, codici colore/chat. - Delta di lunghezza: flag +40% crescita per i pulsanti dell'interfaccia utente; potrebbe danneggiare il layout.
- Prova del fumo: avvia il tuo server e controlla a campione i flussi critici.
Non hai mai configurato un server per i test? Segui questo tutorial: Come creare un server FiveM.
Strategia di manutenzione
- Trattare
en.jsonCOME fonte di verità; crea un lavoro CI che differisceen.jsone aggiorna solo le chiavi modificate nei target. - Mantieni un
CHANGELOG.i18n.mdper i traduttori. - Incoraggia la comunità a contribuire tramite PR; documenta il tuo guida di stile E glossario In
/docs/i18n.md.
Errori comuni (e soluzioni)
- Segnaposto non funzionanti → Utilizzare controlli automatizzati e token di protezione.
- Terminologia incoerente → Mantenere un glossario e applicarlo nei prompt e nella pre-elaborazione.
- Locali misti nel codice → Fallimento CI se le stringhe vengono rilevate all'esterno
locali/. - lingue RTL → Assicurati che i tuoi set CSS NUI
direzione: rtl;e utilizza font con supporto RTL. - Deriva di maiuscole e minuscole e punteggiatura → Istruire l'IA in modo esplicito ed eseguire un linter per normalizzare la punteggiatura.
Risorse esterne
- API DeepL — documenti per sviluppatori: https://www.deepl.com/docs-api
- Traduzione di Google Cloud — documentazione e best practice: https://cloud.google.com/translate/docs
- Manifesto delle risorse FiveM (fxmanifest.lua) - riferimento: https://docs.fivem.net/docs/scripting-reference/resource-manifest/resource-manifest/
Risorse interne (letture correlate)
- Come tradurre gli script FiveM (nel modo giusto) — flusso di lavoro e modelli: https://fivemx.com/fivem-scripts-translation/
- Come creare un server FiveM — creare un banco di prova per il controllo qualità: https://fivemx.com/how-to-create-a-fivem-server/
Copia e incolla le checklist
Pre-traduzione
- Tutte le stringhe centralizzate in
locales/en.json(o tabella Lua) - Le chiavi seguono una convenzione di denominazione
- Glossario preparato
- Segnaposto controllati
Correre
- Traduci in batch con glossario
- Salva l'output in
locali/ .json
Controllo qualità
- JSON/Lua valido
- Parità segnaposto OK
- I token proibiti non cambiano
- Delta di lunghezza accettabili
- Controllo umano a campione effettuato
Nave
- CI verde
- Changelog aggiornato
- Invita la comunità a inviare feedback






