Cupón WELCOME disponible Usa el código WELCOME al finalizar la compra hasta el 31 de julio de 2026. WELCOME

Cómo traducir guiones con IA (Guía FiveM)

¿Estás probando un script gratuito?

Los scripts gratuitos son útiles para comprobaciones rápidas. Para servidores de producción, compare los paquetes completos para servidores o los scripts de pago con mantenimiento, teniendo en cuenta el framework y el caso de uso.

Audiencia: Propietarios de servidores, programadores y mantenedores de FiveM que desean traducciones de alta calidad sin alterar los marcadores de posición ni la interfaz de usuario.


Resumen

  • Centraliza todo el texto en archivos de configuración regional (tablas JSON o Lua). Nunca incorpores cadenas de código en la lógica del juego.
  • Proteger los marcadores de posición (por ejemplo, %s, %d, %{nombre}, {0}, ~r~, ^1) durante la traducción.
  • Utilice IA para traducción de primera pasada + glosario + controles automáticos → revisión humana rápida → envío.
  • Mantenga una única fuente de verdad (generalmente en inglés), compare los cambios y regenere solo las claves modificadas.

¿Por qué traducir tus guiones de FiveM?

  • Accesibilidad y crecimiento: Los servidores localizados atraen a más jugadores y los mantienen interesados.
  • Profesionalismo: Terminología consistente en todos los comandos, interfaces de usuario y mensajes de error.
  • Amigable para los colaboradores: Una estructura local clara invita a las relaciones públicas de la comunidad.

Si necesita un repaso básico sobre la estructura y las mejores prácticas, consulte: Cómo traducir los guiones FiveM (de la manera correcta).


Arquitectura: la forma correcta de localizar

Meta: No hay cadenas visibles para el usuario dentro del código del juego. Todo se enruta a través de una capa de configuración regional.

Diseño de recursos recomendado

my_resource/ ├─ fxmanifest.lua ├─ locales/ │ ├─ en.json # idioma de origen (fuente única de verdad) │ ├─ de.json # traducido (generado/editado) │ ├─ es.json # traducido (generado/editado) │ └─ qa.rules.json # opcional: lista blanca de marcadores de posición y comprobaciones ├─ cliente/ │ └─ main.lua ├─ servidor/ │ └─ main.lua └─ compartido/ └─ i18n.lua # ayudante de traducción

fxmanifest.lua (ejemplo mínimo)

fx_version 'cerulean' juego 'gta5' lua54 'sí' shared_scripts { 'shared/i18n.lua', } archivos { 'locales/*.json' }

compartido/i18n.lua (cargador ligero + sustitución de marcador de posición)

local LOCALE = GetConvar('my_locale', 'en') local CACHE = {} función local loadJSON(path) archivo local = io.open(path, 'r') si no es archivo entonces devuelve {} fin local contenido = archivo:read('*a') archivo:close() local ok, datos = pcall(function() return json.decode(content) end) devuelve ok y datos o {} fin local función readLocale(lang) si CACHE[lang] entonces devuelve CACHE[lang] fin local archivo = ('locales/%s.json'):format(lang) local dict = loadJSON(file) CACHE[lang] = dict return dict fin local función interpolar(str, vars) si no es vars entonces devuelve str fin para k, v en pares(vars) hacer str = str:gsub('%%{'..k..'}', tostring(v)) -- %{nombre} fin retorno str fin función _U(clave, vars) local dict = readLocale(LOCALE) local src = dict[clave] si no es src entonces -- se vuelve al inglés si falta src = readLocale('en')[clave] o clave fin retorno interpolado(src, vars) fin exportaciones('Traducir', _U)

Uso en código cliente/servidor

-- Cliente lib.notify({ título = _U('notify_title'), descripción = _U('welcome_player', { nombre = GetPlayerName(PlayerId()) }), }) -- Servidor print(('[MyRes] %s'):format(_U('server_started')))

locales/en.json (fuente)

{ "notify_title": "Mensaje del servidor", "welcome_player": "¡Bienvenido, %{name}!", "server_started": "El módulo del servidor está listo.", "no_permission": "No tienes permiso.", "items_remaining": "Quedan %{count} elementos" }

Flujo de trabajo de traducción con IA (rápido y seguro)

  1. Extraer y congelar la fuente
  • Mantener Inglés (o su fuente) como locales/en.json.
  • Hacer cumplir la denominación de clave: dominio.acción.asunto (p.ej, inventario.caída.confirmar).
  1. Crear/ampliar un glosario
  • Mapa CSV o JSON de términos canónicos → términos objetivo. Ejemplo:
fuente, destino EMS, Rettungsdienst PD, Polizei Mechanic, Mechaniker

  1. Proteger marcadores de posición y marcado
  • Marcadores de posición: %{nombre}, %s, %d, {0}
  • Códigos de color FiveM: ~r~, ~g~, ~s~; códigos de chat: ^1, ^2
  • Etiquetas NUI/HTML: <b>, <span>
  1. Traducir mediante API (lote)
  • Enviar valores solamente, mantén llaves sin alterar.
  • Suministrar glosario y estilo (tono) al modelo/motor.
  1. Control de calidad automatizado
  • Validar JSON.
  • Verificar paridad de marcador de posición (cada marcador de posición en el origen existe en el destino).
  • Marcar cambios prohibidos (por ejemplo, códigos de colores alterados o puntuación agregada cuando no están permitidos).
  1. Control humano aleatorio (5–10 minutos)
  • Revise comandos, mensajes de error y cadenas de interfaz de usuario largas.
  1. Enviar e iterar
  • Mantener un memoria de traducción (salidas anteriores) para evitar volver a traducir claves sin cambios.

Barandillas: indicaciones y reglas que realmente funcionan

Solicitud de LLM para traducción por lotes de JSON

Tarea: Traducir valores JSON del inglés al Para un contexto de FiveM/GTA RP. Reglas: - MANTENER LAS CLAVES INALTERADAS. - CONSERVAR todos los marcadores de posición exactamente: %{var}, %s, %d, {0}, ~r~, ~g~, ^1, ^2, etc. - Mantener las mayúsculas y los tokens de estilo de código (comandos, comandos /slash) sin cambios. - No añadir comillas, puntuación adicional ni cambiar el significado. - Devolver SOLO JSON válido con la misma estructura. JSON para traducir:

Expresiones regulares que puedes usar en un script de control de calidad

  • Marcadores de posición: %%\{[A-Za-z0-9_]+\}
  • C printf: %(?:\d+\$)?[sdif]
  • Códigos de chat: \^\d
  • Códigos de colores de tilde: ~[rgbso]~

Ejemplo: traducir con DeepL (Node.js)

Funciona muy bien para trabajos puntuales o CI.

paquete.json (scripts)

{ "tipo": "módulo", "scripts": { "i18n:translate:de": "node tools/translate-deepl.js en de", "i18n:check": "node tools/i18n-check.js" } }

herramientas/translate-deepl.js

importar fs desde 'fs'; importar ruta desde 'ruta'; importar afirmación desde 'assert'; importar búsqueda desde 'nodo-fetch'; const [,, srcLang, dstLang] = proceso.argv; const apiKey = proceso.env.DEEPL_API_KEY; // establecer en CI/ENV assert(apiKey, 'DEEPL_API_KEY es obligatorio'); const src = JSON.parse(fs.readFileSync('locales/en.json', 'utf8')); const salida = {}; const GLOSARIO = { 'EMS': 'Servicio de atención médica', 'PD': 'Polizai', }; función protect(str){ // Reemplazar marcadores de posición con tokens que DeepL no alterará return str .replace(/%\{([^}]+)\}/g, '⟦$1⟧') .replace(/%s/g, '⟪S⟫') .replace(/%d/g, '⟪D⟫'); } función restore(str){ return str .replace(/⟦([^⟧]+)⟧/g, '%{$1}') .replace(/⟪S⟫/g, '%s') .replace(/⟪D⟫/g, '%d'); } función asíncrona translate(texto){ const res = await fetch('https://api.deepl.com/v2/translate', { método: 'POST', encabezados: { 'Tipo-De-Contenido': 'application/x-www-form-urlencoded' }, cuerpo: new URLSearchParams({ clave_de_autenticación: apiKey, texto: texto, idioma_de_origen: srcLang.toUpperCase(), idioma_de_destino: dstLang.toUpperCase(), formalidad: 'preferir_más' }) }); const json = await res.json(); si (!json.translations) generar un nuevo Error(JSON.stringify(json)); devolver json.translations[0].texto; } para (const [k, v] de Object.entries(src)) { const protectedText = protect(v); // Glosario pre-pass (simple): let glossed = protectedText; para (const [desde, hasta] de Object.entries(GLOSSARY)) { glossed = glossed.replace(new RegExp(`\\b${desde}\\b`, 'g'), hasta); } // Traducir // 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(`Wrote locales/${dstLang}.json`);

herramientas/i18n-check.js (paridad de marcador de posición)

importar fs desde '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; let ok = true; para (const k de 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('Desajuste del marcador de posición para la clave:', k); ok = false; } } process.exit(ok ? 0 : 1);

Uso eficaz de LLMs (OpenAI/otros)

  • Fragmentos por tema/dominio para un mejor contexto (por ejemplo, inventario, policía, trabajos).
  • Proporcionar descripciones breves por grupo (dos líneas) para definir tono y audiencia.
  • Algunos ejemplos:2 o 3 pares traducidos correctamente con marcadores de posición mejoran la consistencia.
  • Política de reintentos: vuelva a ejecutar solo las claves fallidas marcadas por verificación i18n.

Plantilla de pocas tomas (sistema + usuario)

Sistema: Traduce las cadenas de interfaz de usuario del juego FiveM para . - Mantener las claves sin cambios, conservar los marcadores de posición y mantener un tono conciso. Ejemplos de usuario: EN: "Tienes %{count} multas". DE: "Tienes %{count} Strafzettel". EN: "~r~Error:~s~ No tienes permiso". DE: "~r~Fehler:~s~ Dir fehlt die Berechtigung". Ahora traduce los siguientes valores JSON del inglés al español. Devuelve solo JSON válido:

Traducciones de NUI (HTML/JS)

Para las interfaces de usuario del navegador, una biblioteca del lado del cliente resulta práctica.

Enfoque recomendado

  • Utilice un paquete JSON por idioma en web/configuraciones locales/ .json.
  • Cargue con su marco de interfaz de usuario y exponga un t(clave, variables) ayudante.
  • Mantener el mismas llaves como configuraciones regionales del servidor para reducir la carga cognitiva.

Ayudante de JS minimalista

const dict = await (await fetch(`/locales/${lang}.json`)).json(); exportar función t(clave, vars){ dejar s = dict[clave] || clave; para (const [k,v] de Object.entries(vars||{})) s = s.replace(`%{${k}}`, v); devolver s; }

Especificaciones de ESX/QBCore

  • Muchos scripts de ESX se entregan locales/en.lua, locales/de.lua con un _U ayudante.
  • Si utiliza tablas Lua para configuraciones regionales, mantenga un estilo En todo tu repositorio. Mezclar JSON y Lua para el mismo recurso aumenta el costo de mantenimiento.
  • QBCore suele usar mensajes basados en la configuración. Migre las cadenas repetidas a los archivos de configuración regional para evitar divergencias.

Configuración regional de la tabla Lua (si prefiere Lua sobre JSON)

Locales = Locales o {} Locales['en'] = { no_permission = 'No tienes permiso.', bienvenido_player = '¡Bienvenido, %{nombre}!' } Locales['de'] = { no_permission = 'Du hast keine Berechtigung.', bienvenido_player = 'Willkommen, %{name}!' }

Puertas de calidad antes del envío

  • Comprobación de análisis de JSON/Lua en CI.
  • Paridad de marcador de posición (verificaciones de expresiones regulares como se muestra).
  • Cambios prohibidos:no permitir ediciones a /comandos, letras de combinación de teclas, códigos de color/chat.
  • Deltas de longitud:bandera +40% crecimiento para los botones de UI; puede dañar el diseño.
  • Prueba de humo:Ponga en marcha su servidor y verifique flujos críticos.

¿Es nuevo en la configuración de un servidor para pruebas? Siga esta guía: Cómo crear un servidor FiveM.


Estrategia de mantenimiento

  • Tratar en.json como fuente de verdad; crear un trabajo de CI que difiere en.json y solo actualiza las claves modificadas en los objetivos.
  • Mantener un REGISTRO DE CAMBIOS.i18n.md para traductores.
  • Incentive a la comunidad a contribuir a través de relaciones públicas; documente su guía de estilo y glosario en /docs/i18n.md.

Errores comunes (y soluciones)

  • Marcadores de posición rotos → Utilice controles automatizados y tokens de protección.
  • Terminología inconsistente → Mantener un glosario y aplicarlo en las indicaciones y el preprocesamiento.
  • Localidades mixtas en el código → Falla CI si se detectan cadenas fuera locales/.
  • Idiomas RTL → Asegúrese de que sus conjuntos CSS de NUI dirección: rtl; y utiliza fuentes con soporte RTL.
  • Desviación de mayúsculas y minúsculas y puntuación → Instruya a la IA explícitamente y ejecute un linter para normalizar la puntuación.

Recursos externos



Listas de verificación de copiar y pegar

Pretraducción

  • Todas las cadenas centralizadas en locales/en.json (o tabla Lua)
  • Las claves siguen una convención de nomenclatura
  • Glosario preparado
  • Marcadores de posición auditados

Correr

  • Traducción por lotes con glosario
  • Guardar la salida en locales/ .json

Control de calidad

  • JSON/Lua válido
  • Paridad de marcador de posición OK
  • Fichas prohibidas sin cambios
  • Deltas de longitud aceptables
  • Se realizó una verificación humana aleatoria

Barco

  • CI verde
  • Registro de cambios actualizado
  • Invitar a la comunidad a dar su opinión
Lucas
Lucas

Soy Luke, gamer y me encanta escribir sobre FiveM, GTA y juegos de rol. Dirijo una comunidad de juegos de rol y tengo unos 10 años de experiencia administrando servidores.

Artículos: 436