// Spanish translations
window.LANG_ES = {
  // Common
  common: {
    save: "Guardar",
    cancel: "Cancelar",
    confirm: "Confirmar",
    loading: "Cargando...",
    success: "Correcto",
    failed: "Error",
    delete: "Eliminar",
    edit: "Editar",
    add: "Añadir",
    enable: "Activar",
    disable: "Desactivar",
    enabled: "Activado",
    disabled: "Desactivado",
    yes: "Sí",
    no: "No",
    on: "Encendido",
    off: "Apagado",
    apply: "Aplicar",
    reset: "Restablecer",
    refresh: "Actualizar",
    close: "Cerrar",
    back: "Atrás",
    next: "Siguiente",
    previous: "Anterior",
    submit: "Enviar",
    action: "Acción",
    chinese: "中文",
    traditionalChinese: "繁體中文",
    english: "English",
    spanish: "Español",
    japanese: "日本語",
    korean: "한국어",
    german: "Deutsch",
    french: "Français",
    portuguese: "Português",
    russian: "Русский",
    italian: "Italiano",
    turkish: "Türkçe",
    continue: "Continuar",
    copy: "Copiar",
    copied: "Copiado"
  },

  preview: {
    flvRequired: "Active el flujo FLV.",
    flvOrHlsRequired: "Active al menos un flujo en vivo: FLV o HLS.",
    hlsUnsupportedEnableFlv: "La vista previa HLS no es compatible con este navegador. Active FLV."
  },

  play: {
    mainFlvRequired: "Debe habilitar el flujo FLV principal",
    browserFlvUnsupported: "Este navegador no admite la reproducción FLV. Use un navegador moderno como Chrome, Edge o Firefox"
  },

  // Page titles
  title: {
    ndi: "NDI",
    encoder: "Codificador H.265/H.264",
    status: "Estado",
    mainStream: "Flujo principal",
    subStream1: "Flujo secundario 1",
    subStream2: "Flujo secundario 2",
    subStream3: "Flujo secundario 3",
    videoSettings: "Configuración de vídeo",
    audioSettings: "Configuración de audio",
    advancedSettings: "Configuración avanzada",
    osdMain: "OSD - Flujo principal",
    osdSub1: "OSD - Flujo secundario 1",
    osdSub2: "OSD - Flujo secundario 2",
    osdSub3: "OSD - Flujo secundario 3",
    logoUpload: "Subida de LOGO",
    network: "Configuración de red",
    record: "Configuración de grabación",
    gb28181: "GB28181",
    wifi: "Configuración WIFI",
    password: "Configuración de contraseña",
    serial: "Transporte serie",
    update: "Actualización y copia de seguridad",
    reboot: "Reiniciar dispositivo",
    timedReboot: "Reinicio programado",
    factoryReset: "Restablecer de fábrica",
    recordFiles: "Archivos de grabación",
    netTest: "Prueba de red",
    recordSet: "Configuración de grabación",
    alirtcTokenPage: "AliRTC Token"
  },

  // Menu
  menu: {
    status: "Estado",
    encoder: "Codificador",
    mainStream: "Flujo principal",
    subStream1: "Flujo secundario 1",
    subStream2: "Flujo secundario 2",
    subStream3: "Flujo secundario 3",
    videoSettings: "Configuración de vídeo",
    audioSettings: "Configuración de audio",
    advancedSettings: "Configuración avanzada",
    osd: "OSD",
    logoUpload: "Subida de LOGO",
    system: "Sistema",
    scheduleRecord: "Grabación programada",
    network: "Red",
    record: "Grabación",
    gb28181: "GB28181",
    wifi: "WIFI",
    password: "Contraseña",
    serial: "Transporte serie",
    update: "Actualización y copia de seguridad",
    reboot: "Reiniciar",
    timedReboot: "Reinicio programado",
    factoryReset: "Restablecer de fábrica"
  },

  // Status page
  status: {
    // Device status
    deviceStatus: "Estado del dispositivo",
    runningTime: "Tiempo de funcionamiento: ",
    runtimeDayWithTime: "{0}d {1}",
    deviceTime: "Hora del dispositivo: ",
    syncTime: " (Sincronizar hora al dispositivo)",
    cpuUsage: "Uso de CPU: ",
    memoryUsage: "Uso de memoria: ",
    codecUsage: "Uso de recursos de codificación: ",
    encPpsUsage: "Uso de recursos de codificación: ",
    memoryWarning: " (Si el uso de memoria es muy alto después de 1 minuto, desactive algunos flujos HLS o reduzca el bitrate)",
    cpuWarning: " (Si el uso de CPU se mantiene por encima del 85%, desactive algunos flujos o reduzca la resolución de los subflujos)",
    networkStatus: "Estado de red: ",
    inputVideo: "Vídeo de entrada: ",
    inputBeyondCapability: "(supera la capacidad del dispositivo, configure la fuente a 1080p)",
    inputVideoStatus: "Estado de video de entrada: ",
    vgaAutoAdjust: " (Ajuste automático VGA)",
    capturedFrames: "Fotogramas de vídeo capturados: ",
    lostFrames: "Fotogramas de vídeo perdidos: ",
    audioSampleRate: "Frecuencia de muestreo de audio de entrada: ",
    inputAudioStatus: "Estado de audio de entrada: ",
    capturedAudioFrames: "Fotogramas de audio capturados: ",
    bFrameMode: "Modo de compresión avanzado: ",
    bFrameModeEnabled: "Habilitado",
    packetsSent: "Paquetes enviados: ",
    netTxRate: "Velocidad de envío de red: ",
    netTestLink: " (Prueba de red y registro del sistema)",
    packetsDropped: "Paquetes descartados: ",
    videoTcpConnections: "Conexiones de vídeo TCP: {0}",
    tcpDetailsLink: " (Detalles)",
    canAccessInternet: "Acceso a Internet",
    canAccessInternetIP: "Acceso a IP de Internet",
    lanOnly: "Solo LAN",
    localNetwork: "Red local",

    // Recording status
    recordStatus: "Estado de grabación",
    recordType: "Tipo de grabación: ",
    diskStatus: "Estado del disco: ",
    diskNotExist: "No encontrado",
    mountStatus: "Estado de montaje: ",
    notMounted: "No montado",
    mounted: "Montado",
    totalSpace: "Espacio total: ",
    freeSpace: "Espacio libre: ",
    recordingStatus: "Estado de grabación: ",
    diskFull: "Disco lleno",
    diskSlow: "Disco demasiado lento",
    recordFileList: "Lista de archivos de grabación",
    notRecording: "Sin grabación",
    recording: "Grabando",
    recordingNoVideo: " (Es posible que no se guarden archivos si no hay vídeo de entrada)",
    startRecord: "(Iniciar grabación)",
    stopRecord: "(Detener grabación)",
    usbTfCard: "USB/Tarjeta TF",

    // DHCP status
    dhcpStatus: "Estado DHCP",
    ip: "IP: ",
    subnetMask: "Máscara de subred: ",
    gateway: "Puerta de enlace: ",

    // WIFI status
    wifiStatus: "Estado WIFI",
    wifiDisabled: "WIFI: desactivado",
    wifiState: "Estado WIFI: ",
    wifiSSID: "WIFI SSID: ",
    wifiIP: "WIFI IP: ",
    wifiMAC: "WIFI MAC: ",
    wifiRSSI: "Señal WIFI (RSSI): ",
    wifiFreq: "Frecuencia WIFI: ",
    wifiConnected: "Conectado",
    wifiDisconnected: "Desconectado",
    wifiConnecting: "Conectando (si tarda demasiado, compruebe la configuración WIFI)",

    noSigPicOnly: "Only transmit no-signal image:",

    timeHour: "h",
    timeMinute: "m",
    timeSecond: "s",

    // Streams
    mainStream: "Flujo principal",
    subStream1: "Flujo secundario 1",
    subStream2: "Flujo secundario 2",
    subStream3: "Flujo secundario 3",
    streamDisabled: "Desactivado (Capacidad de codificación agotada: la suma de resolución×velocidad de fotogramas del flujo principal y los secundarios supera el límite de 1080p@90; este subflujo se desactivó automáticamente. Reduzca la resolución/velocidad de fotogramas del flujo principal o de los subflujos anteriores e inténtelo de nuevo)",
    codecType: "Códec: ",
    encodeResolution: "Resolución de codificación: ",
    videoBitrate: "Bitrate de vídeo: ",
    realTimeBitrate: "Bitrate en tiempo real: ",
    realTimeFps: "FPS en tiempo real: ",
    videoEncoded: "Vídeo codificado: ",
    reconnect: " (Reconectar)",
	    previewWebRTC: "Vista previa de vídeo (WebRTC)",
	    previewHTML5: "Vista previa de vídeo (HTML5)",
	    previewLowLatency: "Vista previa de video (baja latencia)",

    // URL related
    disabled: "Desactivado",
    connected: "Conectado",
    disconnected: "Desconectado",
    statusNormal: "Normal",
    statusNoData: "Sin datos",
    bufferPackets: "Paquetes en búfer",
    bufferPacketsLabel: "Paquetes en búfer: ",
    pushSpeed: "Velocidad de envío",
    pushSpeedLabel: "Velocidad de envío: ",
    pushed: "Enviado",
    pushedLabel: "Enviado: ",
    sendBytesLabel: "Datos enviados: ",
    memoryUsed: "Memoria usada",
    memoryUsedLabel: "Memoria usada: ",
    cacheFiles: "Archivos en caché",
    cacheFilesLabel: "Archivos en caché: ",
    multicastUrl: "URL multicast: ",
    mjpgUrl: "URL de flujo MJPG: ",
    jpgUrl: "URL de flujo JPG: ",
    tsUrl: "URL de flujo TS: ",
    flvUrl: "URL de flujo FLV: ",
    hlsTsUrl: "URL de flujo HLS TS: ",
    hlsMp4Url: "URL de flujo HLS MP4: ",
    mp4Url: "URL de flujo MP4: ",
    rtspUrl: "URL de flujo RTSP: ",
    rtmpUrl: "URL de flujo RTMP: ",
    srtListenerUrl: "URL de escucha SRT: ",
    webrtcP2pUrl: "URL de flujo WebRTC P2P: ",
    rtmpPushUrlAny: "URL de publicación RTMP(S)/RTSP {0}: ",
    rtmpPushUrlAny0: "URL de publicación RTMP(S)/RTSP 0: ",
    rtmpPushUrlAny1: "URL de publicación RTMP(S)/RTSP 1: ",
    rtmpPushUrlAny2: "URL de publicación RTMP(S)/RTSP 2: ",
    rtmpPushUrl: "URL de publicación RTMP(S) {0}: ",
    rtspPushUrl: "URL de publicación RTSP {0}: ",
    srtCallerUrl: "URL de llamada SRT: ",
    hlsPushUrl: "URL de publicación HLS: ",
    icecastPushUrl: "URL de publicación ICECAST: ",
    shoutcastPushUrl: "URL de publicación Shoutcast: ",
    whipLabel: "WHIP: ",
    viewers: "Visualizadores",
    viewersLabel: "Visualizadores: ",

    // TRTC status
    trtcRoomId: "ID de sala TRTC: ",
    inRoom: "En la sala",
    notInRoom: "Fuera de la sala",
    initializingServer: "Inicializando conexión con el servidor",
    serverDisconnected: "Servidor desconectado",
    connectingServer: "Conectando con el servidor",
    serverConnected: "Conectado al servidor",
    networkUnknown: "Estado de red desconocido",
    networkExcellent: "Red excelente",
    networkGood: "Buena red",
    networkNormal: "Red normal",
    networkPoor: "Red deficiente",
    networkBad: "Red mala",
    networkNotMeet: "La red no cumple los requisitos mínimos de TRTC",
    errorCode: "Código de error",
    errorCodeLabel: "Código de error: ",
    trtcError1: "Error general, consulte los registros para más detalles",
    trtcError100: "Error de lógica de negocio: llamada ilegal",
    trtcError101: "Error de lógica de negocio: parámetro ilegal",
    trtcError102: "No se puede leer por el momento, inténtelo de nuevo",
    trtcError103: "No se puede conectar a la red",
    trtcError200: "Fallo al entrar en la sala",
    trtcError201: "Parámetro user_sig no válido",
    trtcError202: "Formato de ID de sala no válido",
    trtcError203: "sdk_app_id no válido",
    trtcError204: "Servicio no disponible. Compruebe que los minutos de paquete > 0 y que la cuenta de Tencent Cloud no esté vencida",
    trtcError205: "El usuario fue expulsado de la sala por el servidor",

    // WHIP status
    whipInitializing: "Inicializando",
    whipConnected: "Conectado",
    whipDisconnected: "Desconectado",
    whipUnknown: "Estado desconocido",
    alirtcLabel: "AliRTC: ",
    alirtcConnecting: "Conectando",
    alirtcConnected: "Conectado",
    alirtcDisconnected: "Desconectado",
    alirtcUnknown: "Estado desconocido",
    alirtcRoomId: "ID de sala AliRTC: ",
    alirtcRoomIdLabel: "ID de sala: ",
    alirtcUserIdLabel: "ID de usuario: ",
    alirtcUserNameLabel: "Nombre de usuario: ",
    alirtcVideoBitrateLabel: "Vídeo: ",
    alirtcAudioBitrateLabel: "Audio: ",
    alirtcRttLabel: "RTT: ",

    // GB28181
    gb28181: "GB28181: ",
    gb28181Online: "En línea",
    gb28181Offline: "Fuera de línea"
  },

  // Reboot page
  tcp: {
    pageTitle: "Estado de conexiones TCP",
    subtitle: "Conexiones HTTP / HTTPS / RTSP / RTMP actuales y registros cerrados recientemente",
    refreshAria: "Estado de actualización",
    reading: "Leyendo",
    refreshNow: "Actualizar ahora",
    summaryAria: "Resumen de conexiones",
    activeConnections: "Conexiones activas",
    waitingSnapshot: "Esperando instantánea",
    tcpVideoConnections: "Conexiones de vídeo TCP",
    pendingData: "Datos pendientes",
    maxPendingPerConnection: "Máximo pendiente por conexión",
    recentlyClosed: "Cerradas recientemente",
    recentRecords: "Registros recientes conservados por la interfaz",
    stateAria: "Estado de conexión",
    allRecords: "Todos los registros",
    currentConnections: "Conexiones actuales",
    typeAria: "Tipo de conexión",
    allTypes: "Todos los tipos",
    tcpVideoOnly: "Solo vídeo TCP",
    nonVideoConnections: "Conexiones sin vídeo",
    searchPlaceholder: "Buscar IP, puerto, protocolo, solicitud, URI o ID de flujo",
    columnState: "Estado",
    columnConnection: "Conexión",
    columnClient: "Cliente",
    columnLocalService: "Servicio local",
    columnRequestStream: "Solicitud / Flujo de vídeo",
    columnSent: "Enviado",
    columnPending: "Pendiente",
    columnDropped: "Descartado",
    loadingSnapshot: "Leyendo instantánea de conexiones…",
    tableNote: "Los datos solo se leen al abrir esta página o al pulsar «Actualizar ahora». La propia solicitud de actualización puede aparecer brevemente como una conexión HTTP sin clasificar; los datos pendientes no incluyen la cola de socket del kernel.",
    lessThanSecond: "<1 s",
    durationSeconds: "{0} s",
    durationMinutesSeconds: "{0} min {1} s",
    durationHoursMinutes: "{0} h {1} min",
    durationDaysHours: "{0} d {1} h",
    unclassified: "Sin clasificar",
    dropQueuePackets: "Límite de paquetes en cola",
    dropQueueBytes: "Límite de bytes en cola",
    dropNone: "Ninguno",
    noConnections: "No hay conexiones actuales",
    pendingConnectionsSummary: "{0} conexiones con datos pendientes · {1} paquetes",
    maxPendingConnection: "Conexión #{0} · {1}",
    noPending: "Sin datos pendientes",
    stateActive: "Activa",
    stateClosed: "Cerrada",
    connectedFor: "Conectada durante {0}",
    closedDuration: "Duró {0} · cerrada hace {1}",
    unclassifiedRequest: "Solicitud sin clasificar",
    streamDescription: "Canal {0} · Grupo {1} / Flujo {2}",
    noVideoStream: "Sin flujo de vídeo",
    tcpVideo: "Vídeo TCP",
    packets: "{0} paquetes",
    packetsAndReason: "{0} paquetes · {1}",
    noMatches: "Ninguna conexión coincide con los filtros actuales",
    filterResult: "Mostrando {0} / {1}",
    invalidXml: "La respuesta no es XML válido",
    readSuccess: "Lectura correcta",
    parseFailed: "Error de análisis",
    snapshotParseFailed: "No se pudo analizar la instantánea de conexiones",
    readFailed: "Error de lectura",
    endpointReadFailed: "No se pudo leer /debug?cmd=tcp. Compruebe la conexión del dispositivo o vuelva a iniciar sesión.",
    readTimeout: "Tiempo de lectura agotado",
    timeoutMessage: "El dispositivo no devolvió una instantánea de conexiones en 10 segundos.",
    networkError: "Error de red",
    networkMessage: "No se pudo conectar con el dispositivo. Compruebe la red.",
  },

  reboot: {
    title: "Reiniciar dispositivo",
    description: "Haga clic en este botón para reiniciar el codificador.",
    button: "Reiniciar",
    success: "¡Orden de reinicio enviada!",
    failed: "¡El reinicio ha fallado!",
    confirm: "¿Seguro que desea reiniciar el dispositivo?"
  },

  // Factory reset page
  reset: {
    title: "Restablecer de fábrica",
    description: "Haga clic en este botón para restaurar todos los ajustes del codificador a los valores predeterminados de fábrica.",
    button: "Restablecer",
    success: "¡Restablecimiento de fábrica correcto! El sistema se reiniciará automáticamente, espere por favor.",
    failed: "¡El restablecimiento de fábrica ha fallado!",
    confirm: "¿Seguro que desea restablecer los valores de fábrica?"
  },

  // Scheduled reboot page
  scheduleRecord: {
    title: "Grabación programada",
    allDay: "Todo el día",
    timeRange: "Intervalo",
    segment: "Segmento",
    to: "a",
    monday: "Lun",
    tuesday: "Mar",
    wednesday: "Mié",
    thursday: "Jue",
    friday: "Vie",
    saturday: "Sáb",
    sunday: "Dom",
    nextDay: "(día sig.)",
    hint: "Cada segmento puede ser Todo el día o un Intervalo, con sus propios días activos; en un intervalo, un fin anterior al inicio significa nocturno (graba al día siguiente, según el día de inicio). Sincronice la hora (NTP) en Red primero o no se activará.",
    saveSuccess: "¡Guardado correctamente!",
    saveFailed: "¡Error al guardar!",
    invalidTime: "¡Hora no válida!",
    needWeekday: "¡Seleccione al menos un día!",
  },
  timedReboot: {
    title: "Reinicio programado",
    enable: "Reinicio programado",
    enableLabel: "Reinicio programado:",
    timeLabel: "Hora de reinicio:",
    enabled: "Activar",
    disabled: "Desactivar",
    time: "Hora de reinicio",
    weekdays: "Días de reinicio",
    everyday: "Cada día",
    monday: "Lunes",
    tuesday: "Martes",
    wednesday: "Miércoles",
    thursday: "Jueves",
    friday: "Viernes",
    saturday: "Sábado",
    sunday: "Domingo",
    save: "Guardar",
    saveSuccess: "¡Ajustes guardados!",
    saveFailed: "¡Error al guardar los ajustes!",
    invalidTime: "Valor de hora no válido."
  },

  // Network test page
  netTest: {
    title: "Prueba de red y registro del sistema",
    command: "Comando:",
    run: "Ejecutar",
    address: "Dirección:",
    result: "Resultado:",
    invalidAddr: "Por favor, introduzca una dirección válida."
  },

  // Record files page
  recordFiles: {
    title: "Lista de archivos",
    fileName: "Nombre de archivo",
    time: "Hora",
    fileSize: "Tamaño de archivo",
    action: "Acción",
    delete: "Eliminar",
    confirmDelete: "¿Seguro que desea eliminar",
    deleteSuccess: "¡Orden de eliminación enviada correctamente!",
    deleteFailed: "¡Error al eliminar!",
    noFiles: "No hay archivos de grabación",
    loadError: "Error al cargar"
  },

  // Password settings page
  password: {
    title: "Configuración de contraseña",
    oldPassword: "Contraseña antigua",
    oldPasswordLabel: "Contraseña antigua:",
    newPassword: "Contraseña nueva",
    newPasswordLabel: "Contraseña nueva:",
    confirmPassword: "Confirmar contraseña",
    confirmPasswordLabel: "Confirmar contraseña:",
    save: "Guardar",
    success: "¡Contraseña guardada correctamente!",
    failed: "Error al guardar la contraseña, compruebe si la contraseña antigua es correcta.",
    mismatch: "¡Las nuevas contraseñas no coinciden!",
    empty: "La contraseña no puede estar vacía."
  },

  // Encoding common (only actually used keys)
  encoding: {
    sameAsInput: "Misma resolución que la entrada",
    mp3Required: "¡Configure la codificación de audio a MP3!",
    choosePrimaryColor: "Elegir color principal",
    toggleTheme: "Cambiar tema"
  },

  // OSD settings
  osd: {
    title: "Ajustes OSD",
    globalSettings: "Ajustes globales de OSD",
    followVideoTransformLabel: "Seguir rotación/espejo del vídeo:",
    mainStream: "OSD de flujo principal",
    subStream1: "OSD de flujo secundario 1",
    subStream2: "OSD de flujo secundario 2",
    subStream3: "OSD de flujo secundario 3",
    alpha: "Transparencia",
    alphaLabel: "Transparencia:",
    alphaRange: "[0-255]",
    alphaError: "¡La transparencia debe ser un entero entre 0 y 255!",
    region: "Región",
    regionLabel: "Región:",
    region1: "Región 1",
    region2: "Región 2",
    region3: "Región 3",
    region4: "Región 4",
    type: "Tipo",
    typeLabel: "Tipo:",
    typeText: "Texto",
    typeImage: "Imagen",
    typeScroll: "Texto desplazable",
    typeTime: "Hora",
    typeAudioStatus: "Estado de audio",
    typeVolumeMeter: "Medidor de volumen",
    timeFormatLabel: "Formato de hora:",
    position: "Posición",
    positionLabel: "Posición:",
    speed: "Velocidad",
    speedLabel: "Velocidad:",
    xLabel: "X:",
    yLabel: "Y:",
    textLabel: "Texto:",
    fontSize: "Tamaño de fuente",
    fontSizeLabel: "Tamaño de fuente:",
    fontSizeRange: "[8-72]",
    backgroundColor: "Color de fondo",
    backgroundLabel: "Color de fondo:",
    sizeLabel: "Tamaño (An×Al):",
    sizeHint: "[px]",
    sizeError: "{0}: el tamaño (An×Al) debe ser enteros positivos válidos",
    bgTransparent: "Transparente",
    bgWhite: "Blanco",
    bgBlack: "Negro",
    fontColor: "Color de fuente",
    fontColorLabel: "Color de fuente:",
    pickColor: "Elegir color",
    closeColor: "Cerrar",
    logoLabel: "LOGO:",
    success: "¡Configuración guardada!",
    failed: "¡Error al guardar la configuración!",
    xRangeError: "¡El valor X de {0} debe ser un entero entre 0 y {1}!",
    yRangeError: "¡El valor Y de {0} debe ser un entero entre 0 y {1}!",
    textEmpty: "¡El texto de {0} no puede estar vacío!",
    fontSizeError: "¡El tamaño de fuente de {0} debe ser un entero entre 8 y 72!",
    speedRangeError: "¡La velocidad de {0} debe ser un entero entre 0 y 30!",
    positionRangeError: "¡La posición de {0} debe ser un entero entre 0 y {1}!",
    selectLogo: "¡Seleccione un LOGO para {0}!",
    webrtcPreview: "Vista previa de vídeo"
  },

  // LOGO upload
  logo: {
    title: "Subir LOGO",
    logoLabel: "LOGO:",
    upload: "Subir",
    hint: "Suba una imagen de menos de 500 KB. Formatos admitidos: PNG / JPG / BMP (para transparencia use un PNG o BMP de 32 bits con canal alfa).",
    hint2: "El nombre de archivo debe ser logo1 / logo2 / logo3 / logo4, con extensión .png / .jpg / .jpeg / .bmp.",
    hint3: "p. ej. logo1.png, logo1.jpg, logo1.jpeg, logo1.bmp",
    noFileSelected: "¡Seleccione un archivo para subir!",
    invalidFile: "¡Suba imágenes que cumplan los requisitos!",
    uploadSuccess: "¡Subida correcta!",
    uploadFailed: "¡Error al subir!",
    imageSizeExceeded: "¡El tamaño del archivo de imagen supera el límite!",
    imageResolutionExceeded: "¡La resolución de la imagen supera el límite!",
    storageInsufficient: "¡El archivo de actualización es demasiado grande, espacio de almacenamiento insuficiente!",
    listTitle: "LOGO subido",
    refresh: "Actualizar",
    preview: "Vista previa",
    logoFile: "Archivo LOGO",
    fileType: "Tipo",
    fileSize: "Tamaño",
    operation: "Operación",
    loading: "Cargando...",
    emptyList: "No hay LOGO subido",
    loadListFailed: "Error al cargar la lista de LOGO",
    confirmDelete: "¿Eliminar {0}?\nTambién se eliminarán los archivos PNG/BMP/OSD con el mismo nombre. Si este LOGO está en uso, se borrará el OSD de imagen relacionado.",
    deleteSuccess: "¡Eliminado correctamente!",
    deleteFailed: "¡Error al eliminar!"
  },

  // WIFI settings
  wifi: {
    title: "Ajustes WIFI",
    mode: "Modo",
    ap: "Modo punto de acceso",
    sta: "Modo cliente",
    ssid: "SSID",
    password: "Contraseña",
    security: "Seguridad",
    channel: "Canal",
    scan: "Escanear",
    connect: "Conectar",
    disconnect: "Desconectar",
    status: "Estado",
    connected: "Conectado",
    disconnected: "Desconectado",
    signalStrength: "Intensidad de señal",
    basicSettings: "Ajustes básicos",
    wifiModule: "Módulo Wifi:",
    wifiMode: "Modo Wifi:",
    staMode: "Modo STA",
    apMode: "Modo AP",
    mainConfig: "Configuración principal WIFI",
    backupConfig1: "Configuración de reserva WIFI 1",
    backupConfig2: "Configuración de reserva WIFI 2",
    apModeSettings: "Modo AP",
    wifiList: "Lista Wifi:",
    wifiEssid: "Wifi Essid:",
    wifiPassword: "Contraseña Wifi:",
    wifiDhcp: "Wifi DHCP:",
    wifiIp: "Wifi IP:",
    wifiNetmask: "Máscara de subred Wifi:",
    wifiGateway: "Puerta de enlace predeterminada Wifi:",
    backupEnable1: "Configuración de reserva 1:",
    backupEnable2: "Configuración de reserva 2:",
    wifiBand: "Banda Wifi:",
    wifiChannel: "Canal Wifi:",
    refresh: "Actualizar",
    success: "¡Ajustes guardados correctamente!",
    failed: "¡Error al guardar los ajustes!",
    mainConfigEmpty: "En la configuración principal WIFI, {0} no puede estar vacío.",
    mainConfigInvalid: "En la configuración principal WIFI, el formato de {0} no es válido.",
    backupConfigEmpty: "En WIFI {0}, {1} no puede estar vacío.",
    backupConfigInvalid: "En WIFI {0}, el formato de {1} no es válido.",
    ipAddr: "Dirección IP",
    netmask: "Máscara de subred",
    gateway: "Puerta de enlace predeterminada",
    essidEmpty: "¡El nombre de la red WiFi no puede estar vacío!",
    passwordTooShort: "¡La contraseña WiFi debe tener al menos 8 caracteres!"
  },


  // Upgrade and backup
  updateBackup: {
    title: "Actualización del sistema",
    uploadTitle: "Subir firmware y configuración",
    backupTitle: "Copia de seguridad de firmware y configuración",
    systemVersion: "Versión del sistema",
    systemVersionLabel: "Versión del sistema: ",
    hardware: "Hardware",
    hardwareLabel: "Hardware: ",
    selectFile: "Seleccionar archivo",
    selectFileLabel: "Seleccionar archivo:",
    uploadHint: "Nombre de archivo a subir: up.rar o box.ini",
    uploadHintEncrypted: "Nombre de archivo a subir: up.bin o box.ini",
    uploadWarning: "No suba varios archivos a la vez y no apague el equipo durante la subida.",
    upload: "Subir",
    backupFirmware: "Copia de firmware",
    backupConfig: "Copia de configuración",
    noFileSelected: "¡Seleccione un archivo para subir!",
    uploadSuccess: "¡Subida correcta, reinicie el sistema!",
    uploadFailed: "¡Error al subir!",
    kernelUpdating: "La actualización del kernel tarda unos minutos; no apague el dispositivo. El dispositivo se reiniciará automáticamente al finalizar; no es necesario reiniciarlo manualmente.",
    kernelUpdatingBin: "La actualización del kernel tarda unos minutos; no apague el dispositivo. El dispositivo se reiniciará automáticamente al finalizar. ¡No es necesario reiniciarlo manualmente!",
    imageSizeExceeded: "¡El tamaño del archivo de imagen supera el límite!",
    imageResolutionExceeded: "¡La resolución de la imagen supera el límite!",
    storageInsufficient: "¡El archivo de actualización es demasiado grande, espacio de almacenamiento insuficiente!"
  },

  // Serial transport settings
  serial: {
    title: "Transporte serie",
    frpTitle: "Ajustes del cliente FRP",
    serialTitle: "Transparencia de puerto serie",
    enable: "Activar",
    disable: "Desactivar",
    enableLabel: "Activar:",
    serverAddr: "Dirección del servidor",
    serverAddrLabel: "Dirección del servidor:",
    serverPort: "Puerto del servidor",
    serverPortLabel: "Puerto del servidor:",
    serverToken: "Token del servidor",
    serverTokenLabel: "Token del servidor:",
    channel: "Canal",
    channel1: "Canal 1",
    channel2: "Canal 2",
    channel3: "Canal 3",
    channel4: "Canal 4",
    protocolLabel: "Protocolo:",
    localPort: "Puerto local",
    localPortLabel: "Puerto local:",
    remotePort: "Puerto remoto",
    remotePortLabel: "Puerto remoto:",
    serialMode: "Modo serie",
    serialModeLabel: "Modo de trabajo:",
    server: "Servidor",
    client: "Cliente",
    baudRate: "Velocidad en baudios",
    baudRateLabel: "Baudios:",
    listenPort: "Puerto de escucha",
    listenPortLabel: "Puerto de escucha:",
    save: "Guardar",
    success: "¡Ajustes guardados, reinicie el dispositivo!",
    failed: "¡Error al guardar los ajustes!",
    emptyError: "¡Los ajustes no pueden estar vacíos!",
    remoteAddrError: "¡La dirección del servidor remoto no es válida (introduzca una IP o nombre de host válido)!",
    portRangeError: "¡El puerto de escucha TCP debe ser un entero entre 1 y 65535!",
    frpAddrEmpty: "¡La dirección del servidor FRP no puede estar vacía!",
    frpPortError: "¡El puerto del servidor FRP debe ser un entero entre 1 y 65535!"
  },

  // Advanced Settings
  advanced: {
    title: "Ajustes avanzados",
    // Section titles
    videoInput: "Entrada de vídeo",
    avTransmission: "Transmisión de audio/vídeo",
    recordSettings: "Ajustes de grabación",
    hlsSettings: "Ajustes HLS",
    networkTransmission: "Ajustes de transmisión de flujo",
    serviceSettings: "Ajustes de servicio",
    logSettings: "Ajustes de registro",
    encoderParams: "Parámetros del codificador",
    imageEnhancement: "Mejora de imagen",
    autoRestart: "Reinicio automático",
    // Video Input
    edidSelect: "Selección EDID:",
    colorGamut: "Gama de color:",
    colorRange: "Rango de color:",
    bFrameMode: "Advanced compression mode:",

    interlaceMode: "Modo de entrelazado:",
    noSignal: "Sin señal:",
    noSigPicOnly: "Only transmit no-signal image:",

    vgaAutoAdjust: "Ajuste automático VGA al arrancar:",
    interlaceWeaving: "Combinar dos campos en un fotograma (Weaving)",
    interlaceBottom: "Conservar solo campo inferior",
    interlaceTop: "Conservar solo campo superior",
    interlaceBobbing: "Campo a fotograma (Bobbing)",
    noSignalHide: "No mostrar",
    noSignalImage: "Show no-signal image",
    noSignalColor: "Mostrar color sólido",
    // A/V Transmission
    videoOnly: "Solo transmitir vídeo:",
    audioOnly: "Solo transmitir audio:",
    avSync: "Sincronización A/V:",
    audioDelay: "Retardo de audio (ms):",
    syncAuto: "Automático",
    syncResample: "Remuestrear",
    audioDelayHint: "Valores negativos adelantan el audio, positivos lo retrasan. Úselo solo para ajustar la sincronización A/V.",
    // Recording Settings
    recordType: "Tipo de grabación:",
    cycleRecord: "Grabación cíclica:",
    diskOverwriteOldest: "Eliminar los más antiguos al llenarse:",
    noRecordNoSig: "Sin grabación sin señal:",
    recordSplitTime: "Tiempo de segmentación de grabación (s):",
    // HLS Settings
    hlsSplitTime: "Tiempo de segmento HLS (s):",
    hlsBufferNum: "Número de segmentos HLS:",
    hlsIndexUri: "URI de índice global HLS:",
    // Network Transmission
    tsMuxer: "Empaquetado TS:",
    sliceNumber: "SLICE Number:",

    netDropThreshold: "Umbral de pérdida de paquetes:",
    tsOnce: "Paquetes TS por envío:",
    rtspPackType: "Tipo de encapsulado RTSP:",
    multicastType: "Tipo de multidifusión:",
    enableSap: "Habilitar SAP:",
    mtuSize: "MTU Size:",
    ethSpeed: "Ethernet speed:",

    natAddr: "NAT mapped address:",

    udpTtl: "UDP TTL:",
    udpSockBuf: "UDP SOCKET_BUF_SIZE:",
    rtpH264PacketMode: "Empaquetado RTP H264:",
    packetizeByAccessUnit: "packetize_by_access_unit",
    packetizeByNalu: "packetize_by_nalu",
    vlcCompat: "Compatible con VLC",
    ffmpegCompat: "Compatible con FFMPEG",
    esStream: "Flujo ES",
    tsStream: "Flujo TS",
    // Service Settings
    tsRtspAuth: "TS/RTSP requiere autenticación:",
    httpNoAuth: "Acceso web sin contraseña:",
    netCheck: "Comprobación de estado de red:",
    telnetService: "Servicio Telnet:",
    sshService: "Servicio SSH:",
    ndiService: "Servicio NDI:",
    sambaService: "Servicio Samba:",
    onvifService: "Servicio ONVIF:",
    onvifLocation: "ONVIF Location:",
    onvifMode: "Modo ONVIF:",
    onvifModeLegacy: "Legacy XML (puerto HTTP/ONVIF compartido)",
    onvifModeProfileST: "Profile S/T (puerto ONVIF dedicado)",
    onvifModeProfileSCompat: "Profile S compatible con Hikvision (puerto ONVIF dedicado)",
    onvifPassword: "ONVIF password required:",

    rtspDefaultStream: "Flujo RTSP por defecto:",
    vmixCompat: "Compatible con VMix:",
    readOnlyConfig: "Lock all settings:",

    telnetLan: "Solo LAN",
    // Log Settings
    localLog: "Servicio de registro local:",
    trtcLogLevel: "Nivel de registro del SDK TRTC:",
    alirtcLogLevel: "Nivel de registro del SDK AliRTC:",
    sdkLogDebug: "Depuración",
    sdkLogInfo: "Información",
    sdkLogWarning: "Advertencia",
    sdkLogError: "Error",
    sdkLogFatal: "Fatal",
    sdkLogNone: "Ninguno",
    lokiAddr: "Dirección del servidor Loki:",
    lokiPort: "Puerto del servidor Loki:",
    // Encoder Parameters
    sliceSplit: "División SLICE:",
    sliceBytes: "Bytes SLICE:",
    minQp: "MIN_QP:",
    maxQp: "MAX_QP:",
    deblocking: "Deblocking filter:",
    deblockingAlpha: "Deblocking alpha:",
    deblockingBeta: "Deblocking beta:",



    debreath: "Eliminar efecto de respiración:",
    sar: "PAR:",
    cbrOnlyHint: "Solo efectivo cuando el modo de control de tasa está en CBR",
    // Image Enhancement
    contrastEnhance: "Mejora de contraste:",
    sharpnessEnhance: "Mejora de nitidez:",
    lumaSfStrength: "Denoise espacial de luminancia:",
    lumaTfStrength: "Denoise temporal de luminancia:",
    chromaSfStrength: "Denoise espacial de crominancia:",
    chromaTfStrength: "Denoise temporal de crominancia:",
    // Auto Restart
    kickAllOnChange: "Desconectar usuarios al cambiar entrada:",
    noVideoReboot: "Reinicio automático sin vídeo:",
    noAudioReboot: "Reinicio automático sin audio:",
    picStillRestart: "Restart on frozen video:",

    // Button
    save: "Guardar",
    // Messages
    success: "¡Ajustes guardados, reinicie el dispositivo!",
    failed: "¡Error al guardar los ajustes!",
    emptyError: "¡Los ajustes no pueden estar vacíos!",
    netDropError: "El umbral de pérdida de paquetes debe ser un entero entre 50 y 50000.",
    tsOnceError: "TS packets per send must be an integer between 3-128!",
    sliceError: "SLICE Number must be an integer between 1-255!",
    minQpError: "MIN_QP debe ser un entero entre 1 y 35.",
    maxQpError: "MAX_QP debe ser mayor que MIN_QP y como máximo 50.",
    udpTtlError: "UDP TTL debe ser un entero entre 1 y 254.",
    contrastError: "La mejora de contraste debe ser un entero entre 0 y 63.",
    sharpnessError: "La mejora de nitidez debe ser un entero entre 0 y 16.",
    lumaSfError: "El denoise espacial de luminancia debe ser un entero entre 0 y 255.",
    lumaTfError: "El denoise temporal de luminancia debe ser un entero entre 0 y 63.",
    chromaSfError: "El denoise espacial de crominancia debe ser un entero entre 0 y 255.",
    chromaTfError: "El denoise temporal de crominancia debe ser un entero entre 0 y 32.",
    hlsSplitError: "El tiempo de segmento HLS debe ser un entero entre 3 y 10.",
    hlsBufferError: "El número de segmentos HLS debe ser un entero entre 3 y 10.",
    hlsUriError: "La URI de índice global HLS no es válida.",
    udpSockBufError: "UDP SOCKET_BUF_SIZE debe ser un entero entre 0 y 20971520.",
    mtuError: "El tamaño MTU debe ser un entero entre 500 y 1500.",
    deblockingAlphaError: "Deblocking alpha must be an integer between -6 and 6!",
    deblockingBetaError: "Deblocking beta must be an integer between -6 and 6!",


    audioCacheError: "El retardo de audio debe ser un entero entre -2000 y 2000.",
    recordSplitError: "El tiempo de segmentación de grabación debe ser un entero entre 60 y 7200.",
    lokiPortError: "El puerto del servidor Loki debe estar entre 1 y 65535."
  },

  // Audio Encoding Settings
  audioEnc: {
    blkInput: "Entrada",
    blkEncode: "Codificación",
    blkVolume: "Volumen",
    blkVolumeNote: "Ganancia fija manual",
    blkAgc: "Ganancia automática",
    blkAgcNote: "Nivela automáticamente el volumen variable al objetivo",
    blkDenoise: "Reducción de ruido",
    blkDenoiseNote: "Suprime el ruido de fondo; alto uso de CPU, normalmente desactivado",
    mute: "Silencio",
    gain0: "0 dB (sin cambios)",
    agcLevel: "Nivel objetivo AGC (dBFS):",
    agc: "Control automático de ganancia:",
    agcLevelError: "El nivel objetivo de AGC debe estar entre -42 y -12 dBFS.",
    title: "Ajustes de audio",
    // Tabs
    tabAudio: "Ajustes de audio",
    tabOnvif: "Audio ONVIF",
    // Tips
    tipAudio: "No ajuste la ganancia de volumen digital demasiado alta, ya que puede causar distorsión o introducir ruido.<br>En la mayoría de los casos, establezca la ganancia en 0.<br>Ajuste el volumen general desde los controles del reproductor frontal.",
    tipVolVsAgc: "<b>Ganancia de volumen vs. ganancia automática (AGC)</b><br>La ganancia de volumen es una ganancia fija ajustada manualmente: los valores positivos amplifican y los negativos atenúan. No cambia con la señal de entrada, por lo que es adecuada para fuentes con un nivel estable y previsible.<br>La ganancia automática (AGC) ajusta la ganancia según el nivel en tiempo real de la señal de entrada, mantiene la salida cerca del nivel objetivo y suaviza el audio que varía entre fuerte y suave.<br>Con el AGC activado, mantenga la ganancia de volumen en 0 dB para que el AGC controle el nivel por sí solo y evite superponer dos controles.",
    tipAgcLevel: "<b>Nivel objetivo del AGC (dBFS)</b><br>Define la referencia de nivel final. Cuanto más cerca esté el objetivo de 0 dBFS, más alta será la salida, pero menor será el margen para los picos transitorios y más fácilmente se producirá recorte.<br>• -18 dBFS (recomendado): equilibrio entre volumen y margen, adecuado para la mayoría de los casos.<br>• -12 dBFS: la opción más alta, ideal para transmisiones en directo y otros escenarios de alto volumen; pero con solo 12 dB de margen, los sonidos fuertes repentinos se recortan con facilidad.<br>• -20 ~ -24 dBFS: adecuado para voz, actuaciones en directo y otras entradas con grandes variaciones de pico.<br>• -30 ~ -42 dBFS: adecuado para entradas de micrófono de alta ganancia o entornos ruidosos.",
    tipOnvif: "Para conectar a un NVR, establezca la codificación RTSP G711 en \"Activar y remuestrear a 8K\".",
    // Audio Settings
    audioInput: "Entrada de audio:",
    sampleRate: "Frecuencia de muestreo:",
    codec: "Códec:",
    channel: "Canales:",
    bitrate: "Bitrate:",
    digitalGain: "Ganancia de volumen digital:",
    analogGain: "Ganancia de volumen analógico:",
    denoise: "Reducción de ruido:",
    denoiseStrength: "Intensidad de reducción de ruido (dB):",
    pteG711: "Flujo PTE G711:",
    // Audio Input Options
    inputDigital: "Digital",
    inputAnalog: "Analógica",
    inputMixed: "Mixta",
    // Sample Rate Options
    sampleSameAsInput: "Igual que la entrada",
    // ONVIF Audio
    rtspG711: "Codificación RTSP G711:",
    rtspG711Resample: "Activar y remuestrear a 8K",
    g711Codec: "Códec G711:",
    // Buttons and Messages
    save: "Guardar",
    success: "¡Configuración guardada!",
    failed: "¡Error al guardar la configuración!",
    emptyError: "¡La configuración no puede estar vacía!",
    bitrateError: "¡El bitrate debe ser un entero entre {0}-{1}!",
    gainError: "¡La ganancia de volumen digital debe ser un entero entre -20 y 10!",
    denoiseError: "¡La intensidad de reducción de ruido debe ser un entero entre 1 y 100!",
    analogVolEmpty: "¡La ganancia de volumen analógico no puede estar vacía!",
    analogVolError: "¡La ganancia de volumen analógico debe ser un entero entre {0} y {1}!"
  },

  // Recording Settings Page
  recordSet: {
    title: "Ajustes de grabación",
    // Card titles
    statusTitle: "Estado de grabación",
    settingsTitle: "Ajustes de grabación",
    // Status
    recordType: "Tipo de grabación:",
    diskStatus: "Estado del disco:",
    currentAddr: "Dirección actual:",
    mountDevice: "Dispositivo montado:",
    mountStatus: "Estado de montaje:",
    totalSpace: "Espacio total:",
    freeSpace: "Espacio libre:",
    recordStatus: "Estado de grabación:",
    recordFiles: "Archivos de grabación:",
    fileList: "Lista de archivos",
    // Disk status
    diskNotExist: "No presente",
    diskFull: "Disco lleno",
    diskSlow: "Disco demasiado lento",
    mounted: "Montado",
    unmounted: "Desmontado",
    notRecording: "Sin grabación",
    recording: "Grabando",
    noVideoWarning: " (Es posible que no se guarden archivos si no hay entrada de vídeo)",
    // Actions
    startRecord: "(Iniciar grabación)",
    stopRecord: "(Detener grabación)",
    mountDisk: "(Montar disco)",
    unmountDisk: "(Desmontar disco)",
    deleteAll: "(Eliminar todas las grabaciones)",
    // Settings
    storageType: "Tipo de almacenamiento:",
    partition: "Partición:",
    partitionInfo: "Información de partición:",
    diskInfo: "Información de disco:",
    formatDisk: "(Reparticionar y formatear disco)",
    exampleAddr: "Dirección de ejemplo:",
    storageAddr: "Dirección de almacenamiento:",
    username: "Usuario:",
    password: "Contraseña:",
    // Storage Types
    storageDisabled: "Desactivado",
    storageUsb: "USB/Tarjeta TF",
    storageNfs: "NFS",
    storageSamba: "SAMBA/CIFS",
    // Format Dialog
    formatTitle: "Información del disco",
    formatDevice: "Dispositivo:",
    formatType: "Tipo:",
    formatModel: "Modelo:",
    formatRemovable: "Extraíble:",
    formatPartTable: "Tabla de particiones:",
    formatCapacity: "Capacidad:",
    formatPartitions: "Información de particiones",
    formatPartition: "Partición",
    formatAvailable: "(disponible)",
    formatTotal: "(total)",
    formatConfirm: "¿Continuar con el formateo del disco?",
    formatDanger: "Advertencia: El formateo reparticionará el disco y se perderán todos los datos. ¿Desea continuar?",
    formatContinue: "Continuar",
    formatCancel: "Cancelar",
    formatConfirmBtn: "Confirmar",
    formatting: "Formateando...",
    // Buttons and Messages
    save: "Guardar",
    yes: "Sí",
    no: "No",
    success: "¡Configuración guardada!",
    failed: "¡Error al guardar la configuración!",
    formatSuccess: "¡Formateo correcto!",
    formatFailed: "¡Error al formatear!",
    deleteSuccess: "¡Se envió la orden de borrado!",
    deleteFailed: "¡Error al borrar!",
    confirmDeleteAll: "¿Eliminar todos los archivos de grabación?",
    recordingWarning: "Actualmente se está grabando. Detenga la grabación antes de desmontar.",
    diskMountedWarning: "El disco está montado. Desmóntelo antes de formatear.",
    diskMountedSettingWarning: "El disco está montado. Desmóntelo antes de cambiar los ajustes.",
    storageLockedHint: "Bloqueado mientras está montado; desmonte el disco para cambiarlo.",
    partitionNotExist: "La partición no existe",
    partitionRemoved: " (Eliminada)",
    unpartitioned: " (sin particiones)",
    unpartitionedHint: "El disco no tiene particiones, primero reparticione y formatee el disco",
    // Address Validation
    addrEmpty: "¡La dirección de almacenamiento no puede estar vacía!",
    addrNfsFormat: "Formato de dirección no válido, debe contener el separador ':'.",
    addrIpError: "Formato de dirección IP no válido.",
    addrPathSlash: "La ruta debe comenzar por '/'.",
    addrPathInvalid: "La ruta contiene caracteres no válidos.",
    addrSambaStart: "La dirección debe comenzar por '\\\\'.",
    addrSambaFormat: "Dirección no válida, debe contener IP y ruta separados por '\\\\'.",
    addrPathEmpty: "La ruta no puede estar vacía.",
    addrPathChars: "La ruta contiene caracteres no válidos, solo se permiten letras, números, guiones y guiones bajos.",
    // Disk size info "{available} / {total}"
    diskSizeInfo: "{0} (disponible) / {1} (total)"
  },

  // GB28181 Settings
  gb28181: {
    title: "GB28181 Settings",
    basicSettings: "Basic Settings",
    heartbeatSettings: "Heartbeat Settings",
    sipServerSettings: "SIP Server Settings",
    authSettings: "Authentication Settings",
    enable: "Enable:",
    disabled: "Disabled",
    enabled: "Enabled",
    localSipPort: "Local SIP Port:",
    videoChannelId: "Video Channel ID:",
    streamSelect: "Stream Select:",
    mainStream: "Main Stream",
    subStream1: "Sub Stream 1",
    subStream2: "Sub Stream 2",
    subStream3: "Sub Stream 3",
    regExpiry: "Registration Expiry:",
    heartbeatCycle: "Heartbeat Cycle:",
    maxHeartbeatTimeout: "Max Heartbeat Timeout:",
    sipServerId: "SIP Server ID:",
    sipServerDomain: "SIP Server Domain:",
    sipServerAddr: "SIP Server Address:",
    sipServerPort: "SIP Server Port:",
    sipUserId: "SIP User ID:",
    sipPassword: "SIP Password:",
    emptyError: "¡La configuración no puede estar vacía!",
    localPortError: "¡El puerto SIP local debe ser un entero entre 1-65535!",
    serverPortError: "¡El puerto del servidor SIP debe ser un entero entre 1-65535!",
    regExpiryError: "¡El tiempo de expiración del registro debe ser un entero entre 100-100000!",
    heartbeatError: "¡El ciclo de latido debe ser un entero entre 5-3600!",
    maxTimeoutError: "¡El tiempo máximo de espera de latido debe ser un entero entre 3-255!",
    success: "¡Configuración guardada correctamente!",
    failed: "¡Error en la configuración!"
  },

  // Video Source Settings
  videoSource: {
    title: "Ajustes de fuente de vídeo",
    videoInput: "Ajustes de entrada de vídeo",
    brightAdjust: "Ajuste de brillo de entrada",
    videoOutput: "Ajustes de salida de vídeo",
    inputFormat: "Formato de entrada de vídeo:",
    yuv422: "YUV422",
    yuv420: "YUV420 (soporta rotación)",
    rotation: "Ángulo de rotación:",
    flipMirror: "Volteo/Espejo:",
    flipDisable: "Desactivado",
    mirror: "Espejo",
    flip: "Voltear",
    flipAndMirror: "Espejo y voltear",
    cropEnable: "Recorte de vídeo:",
    cropLeft: "Punto inicial de recorte (Left):",
    cropTop: "Punto inicial de recorte (Top):",
    cropWidth: "Anchura tras recorte (Width):",
    cropHeight: "Altura tras recorte (Height):",
    monochrome: "Monocromo:",
    colorMode: "Modo de color de entrada:",
    unknown: "Desconocido",
    brightEnable: "Ajuste de brillo:",
    gain: "Ganancia:",
    gainHint: "[10-1000], por defecto 100",
    offset: "Desplazamiento:",
    offsetHint: "[0-100], por defecto 0",
    note: "Nota:",
    brightNote1: "1. Brillo = (Brillo original * Ganancia / 100) + Desplazamiento",
    brightNote2: "2. El ajuste de brillo solo es efectivo cuando el modo de color de entrada es RGB",
    outputRes: "Resolución de salida de vídeo:",
    auto: "Auto",
    cscEnable: "Ajuste CSC:",
    luminance: "Luminancia:",
    contrast: "Contraste:",
    hue: "Tono:",
    saturation: "Saturación:",
    cscHint: "[0-100], por defecto 50",
    rotateHint: "Las rotaciones de 180° y 270° se pueden obtener combinando una rotación de 0°/90° con voltear/espejar.",
    emptyError: "¡La configuración no puede estar vacía!",
    gainError: "¡La ganancia debe ser un entero entre 10 y 1000!",
    offsetError: "¡El desplazamiento debe ser un entero entre 0 y 100!",
    leftError: "¡El valor Left debe ser un entero entre 0-{0}!",
    topError: "¡El valor Top debe ser un entero entre 0-{0}!",
    widthError: "¡El valor Width debe ser un entero entre 400-{0}!",
    heightError: "¡El valor Height debe ser un entero entre 400-{0}!",
    luminanceError: "¡La luminancia debe ser un entero entre 0 y 100!",
    contrastError: "¡El contraste debe ser un entero entre 0 y 100!",
    hueError: "¡El tono debe ser un entero entre 0 y 100!",
    saturationError: "¡La saturación debe ser un entero entre 0 y 100!",
    success: "¡Configuración guardada!",
    failed: "¡Error al guardar la configuración!"
  },

  // Network Settings
  network: {
    title: "Ajustes de red",
    ipv4Title: "Ajustes IPv4",
    ipv6Status: "Estado IPv6",
    ipv6Title: "Ajustes IPv6",
    ipv6TypeGlobal: "IP global",
    ipv6TypeLinkLocal: "IP de enlace local",
    ipv6TypeUniqueLocal: "IP local",
    ipv6TypeMulticast: "IP multicast",
    ipv6TypeGeneric: "IP",
    ipv6StatusGateway: "Puerta de enlace",
    dnsTitle: "Ajustes DNS",
    ntpTitle: "Ajustes NTP",
    portTitle: "Ajustes de puertos",
    httpsTitle: "Ajustes HTTPS",
    hostnameTitle: "Ajustes de HOSTNAME",
    dhcp: "DHCP:",
    dhcpHint: "Después de activar DHCP, el dispositivo puede encontrarse con herramientas de búsqueda compatibles con ONVIF.",
    ipAddr: "Dirección IP:",
    netmask: "Máscara de subred:",
    gateway: "Puerta de enlace cableada:",
    macAddr: "Dirección MAC:",
    defaultGateway: "Puerta de enlace predeterminada:",
    lanFirst: "Cableado primero",
    wifiFirst: "WIFI primero",
    g4First: "4G/5G primero",
    ipv6Mode: "Modo:",
    ipv6Disable: "Desactivado",
    ipv6Auto: "Configuración automática",
    ipv6Manual: "Configuración manual",
    ipv6Addr: "Dirección IPv6:",
    ipv6Prefix: "Longitud de prefijo IPv6:",
    ipv6Gateway: "Puerta de enlace predeterminada IPv6:",
    dns1: "DNS1:",
    dns2: "DNS2:",
    ntpSync: "Sincronización NTP:",
    ntpServer: "Servidor:",
    timezone: "Zona horaria:",
    httpPort1: "Puerto HTTP 1:",
    httpPort2: "Puerto HTTP 2:",
    rtspPort1: "Puerto RTSP 1:",
    rtspPort2: "Puerto RTSP 2:",
    onvifPort: "Puerto ONVIF:",
    sadpProtocol: "Puerto SADP:",
    httpsService: "Servicio HTTPS:",
    httpsPort1: "Puerto HTTPS 1:",
    httpsPort2: "Puerto HTTPS 2:",
    httpsPrivatePass: "Contraseña de clave privada HTTPS:",
    socks5Title: "SOCKS5 Proxy",
    socks5Enable: "SOCKS5 Proxy:",
    socks5Host: "Proxy Host:",
    socks5Port: "Proxy Port:",
    socks5User: "Username:",
    socks5Pass: "Password:",
    socks5AuthHint: "(Optional authentication, username and password must both be set)",
    privatePassHint: "(Dejar vacío si la clave privada no tiene contraseña)",
    uploadCert: "Subir certificado:",
    uploadCertHint: "(El nombre del archivo debe ser private.key o public.crt. No subir varios a la vez ni apagar durante la carga)",
    uploadBtn: "Subir certificado",
    deleteCert: "Eliminar certificado",
    hostname: "HOSTNAME:",
    mdnsService: "Servicio mDNS:",
    mdnsAddr: "Dirección de acceso mDNS:",
    portRange: "[1-65535]",
    prefixRange: "[0-128]",
    emptyError: "¡La configuración no puede estar vacía!",
    ipError: "¡Formato de dirección IP no válido!",
    netmaskError: "¡Formato de máscara de subred no válido!",
    gatewayError: "¡Formato de puerta de enlace no válido!",
    dns1Error: "¡Formato de DNS primario no válido!",
    dns2Error: "¡Formato de DNS secundario no válido!",
    macError: "¡Formato de dirección MAC no válido!",
    ipv6Error: "¡Formato de dirección IPv6 no válido!",
    ipv6PrefixError: "¡Longitud de prefijo IPv6 no válida (1-128)!",
    ipv6GatewayError: "¡Formato de puerta de enlace IPv6 no válido!",
    httpPort1Error: "¡El puerto HTTP 1 debe ser un entero entre 1 y 65535!",
    httpPort2Error: "¡El puerto HTTP 2 debe ser un entero entre 1 y 65535!",
    rtspPort1Error: "¡El puerto RTSP 1 debe ser un entero entre 1 y 65535!",
    rtspPort2Error: "¡El puerto RTSP 2 debe ser un entero entre 1 y 65535!",
    httpsPort1Error: "¡El puerto HTTPS 1 debe ser un entero entre 1 y 65535!",
    httpsPort2Error: "¡El puerto HTTPS 2 debe ser un entero entre 1 y 65535!",
    onvifPortError: "¡El puerto ONVIF debe ser un entero entre 1 y 65535!",
    sadpPortError: "¡El puerto SADP debe ser un entero entre 1 y 65535!",
    httpBothDisableError: "¡Los puertos HTTP 1 y 2 no pueden estar ambos desactivados!",
    httpsBothDisableError: "Cuando HTTPS está activado, los puertos 1 y 2 no pueden estar ambos desactivados.",
    socks5HostError: "Invalid SOCKS5 proxy host!",
    socks5PortError: "SOCKS5 proxy port must be an integer between 1-65535!",
    socks5AuthPairError: "SOCKS5 username and password must both be set or both be empty!",
    socks5AuthLengthError: "SOCKS5 username and password must not exceed 255 characters!",
    ntpEmptyError: "¡El servidor NTP no puede estar vacío!",
    ntpFormatError: "¡Dirección de servidor NTP no válida!",
    hostnameEmptyError: "¡HOSTNAME no puede estar vacío!",
    hostnameFormatError: "¡HOSTNAME no válido!\n\n1. HOSTNAME no debe superar los 63 caracteres.\n2. Solo se permiten letras (a-z), números (0-9), guiones (-) y guiones bajos (_).\n3. '-' y '_' no pueden aparecer consecutivamente, solos ni al principio o final.",
    deleteCertConfirm: "¿Seguro que desea eliminar el certificado HTTPS subido?",
    selectFile: "¡Seleccione un archivo para subir!",
    uploadSuccess: "¡Subida correcta!",
    uploadFailed: "¡Error al subir!",
    fileSizeError: "¡El tamaño del archivo de imagen supera el límite!",
    fileResError: "¡La resolución de la imagen supera el límite!",
    spaceError: "¡El archivo de actualización es demasiado grande, espacio de almacenamiento insuficiente!",
    deleteSuccess: "¡Eliminado correctamente!",
    deleteFailed: "¡Error al eliminar!",
    successReboot: "¡Configuración guardada, reinicie el dispositivo!",
    failed: "¡Error al guardar la configuración!"
  },

  // Output Settings Page (Stream Settings)
  output: {
    // Tab names
    tabs: {
      ndi: "NDI",
      encode: "Codificación",
      ts: "TS/Multicast",
      mjpeg: "MJPEG",
      rtsp: "RTSP",
      rtmp: "RTMP",
      srt: "SRT",
      webrtc: "WebRTC",
      trtc: "TRTC",
      alirtc: "AliRTC",
      hls: "HLS",
      other: "MP4/FLV/Otros"
    },

    // Encoding settings
    encode: {
      codecType: "Tipo de códec:",
      frameRate: "Tasa de fotogramas:",
      sameAsInput: "Igual que la tasa de entrada",
      auto: "Auto",
      customFrameRate: "Tasa de fotogramas personalizada",
      customFrameRateLabel: "Tasa de fotogramas personalizada:",
      gopInterval: "Intervalo GOP (fotogramas):",
      bitrate: "Bitrate (kbit):",
      qualityRange: "Rango de calidad:",
      qualityStrict: "Estricto (Alta)",
      qualityTight: "Ajustado (Casi Alta~Alta)",
      qualityNormal: "Normal (Media~Alta)",
      qualityLoose: "Flexible (Casi Baja~Alta)",
      qualityWide: "Amplio (Baja~Alta)",
      mjpegQuality: "Calidad MJPEG:",
      outputResolution: "Resolución de salida:",
      h264Profile: "Perfil H.264:",
      bitrateControl: "Control de bitrate:",
      cbrStableRange: "CBR Stability Range:",
      cbrStableMin: "min",
      cbrStableMax: "max",
      bFramesMode: "B-Frame Mode:",
      bFramesDisable: "Disabled",
      bFramesIbp: "IBP",
      bFramesIbbp: "IBBP",
      // Tips
      tipCodec: "H.265 ofrece mejor calidad de vídeo que H.264. Úselo si su decodificador lo soporta.",
      tipVbr: "En modo VBR, el bitrate se regula mediante \"Rango de calidad\"; este rango limita los valores de QP.<br>Seleccionar \"Casi Alta~Alta\" o \"Alta\" produce un bitrate muy alto, haciendo que el valor configurado de bitrate pierda sentido;<br>Solo cuando el rango es \"Casi Baja~Alta\" el valor de bitrate tiene referencia.",
      tipCbr: "\"CBR fuerte\" se usa en sistemas CATV para asegurar un bitrate TS estable. Con \"CBR fuerte\" a 1080P, el bitrate no debería ser menor de 5000 kbit/s, se recomiendan 8000 kbit/s.",
      tipGop: "Suponiendo que la tasa de fotogramas de entrada es n (por ejemplo 60, 50, 30, 25);<br>El intervalo GOP normalmente se ajusta a n * 2, valores típicos: 120, 100, 60, 50;<br>Cuando la tasa de fotogramas está en Auto, si n > 30, la codificación usa n/2; en caso contrario usa n."
    },

    // TS/Multicast settings
    ts: {
      tsUri: "URL de flujo TS:",
      multicastIp: "IP multicast:",
      multicastPort: "Puerto multicast:",
      sapName: "Nombre SAP:",
      tsVideoPid: "PID de vídeo TS:",
      tsAudioPid: "PID de audio TS:",
      tsTransportStreamId: "ID de flujo de transporte TS:",
      tsOriginalNetworkId: "ID de red original TS:",
      tsPmtStartPid: "PID inicial PMT TS:",
      tsStartPid: "PID inicial TS:",
      tsTablesVersion: "Versión de tablas TS:",
      tsServiceId: "ID de servicio TS:",
      tsServiceName: "Nombre de servicio TS:",
      tsProviderName: "Nombre de proveedor TS:",
      tsPcrPeriod: "Periodo PCR TS (ms):",
      conformSystemB: "Cumplir sistema B (DVB):",
      tsNullPacket: "Paquetes nulos TS:",
      noInsert: "No insertar",
      insert12: "Insertar (1.2x)",
      insert13: "Insertar (1.3x)",
      insert15: "Insertar (1.5x)",
      insert20: "Insertar (2x)",
      insert25: "Insertar (2.5x)",
      tsTdt: "TS TDT:",
      // Tips
      tipMulticast: "La dirección multicast también puede ser broadcast o unicast, el sistema la detectará automáticamente.",
      tipVlc: "Si VLC no puede reproducir multicast, compruebe si su PC tiene varias interfaces de red y pruebe con otra.",
      tipSap: "El nombre SAP puede verse en dispositivos compatibles, por ejemplo en VLC: lista de reproducción -> Red local.",
      tipAdvanced: "Normalmente los parámetros avanzados TS no necesitan ajuste.",
      tipIptv: "Al conectar a sistemas IPTV, los paquetes nulos TS deben ajustarse a 1.3x; el dispositivo insertará paquetes nulos para asegurar un bitrate estable.<br>Este ajuste solo se aplica en modo \"CBR fuerte\"."
    },

    // MJPEG settings

    mjpeg: {

      jpgUri: "JPG Image URL:",

      mjpgUri: "MJPG Stream URL:",

      // Tips

      tipJpg: "JPG is a still image; MJPG is a motion image.",

      tipMjpg: "Both can be opened directly in a browser."

    },


    // RTSP settings
    rtsp: {
      rtspUri: "URL de flujo RTSP:",
      enableMulticast: "Activar (Multicast)",
      enableTcpOnly: "Activar (solo TCP)",
      multicastIp: "IP multicast RTSP:",
      multicastPort: "Puerto multicast RTSP:",
      // Tips
      tipEnable: "Si se activa, el transporte real (UDP o TCP) lo decide el cliente. Por ejemplo, en VLC puede marcar \"RTP over RTSP(TCP)\" para usar TCP.",
      tipTcpOnly: "Seleccionar \"Activar (solo TCP)\" fuerza al dispositivo a usar TCP.",
      tipUdp: "Con UDP pueden perderse paquetes ocasionalmente por problemas de red. Si todos los clientes lo soportan, se recomienda TCP.",
      tipMulticast: "Al activar Multicast, se usarán 4 puertos consecutivos a partir del \"Puerto multicast RTSP\"."
    },

    // RTMP settings
    rtmp: {
      rtmpUri: "URL de flujo RTMP:",
      publishUri0: "URL de publicación RTMP(S)/RTSP 0:",
      publishUri1: "URL de publicación RTMP(S)/RTSP 1:",
      publishUri2: "URL de publicación RTMP(S)/RTSP 2:",
      mode: "Modo de transmisión RTMP:",
      modeStandard: "Standard (Enhanced RTMP)",
      modeLegacy: "Legacy (CodecID 12)",
      // Tips
      tipPublish: "Las URL de publicación 0-2 se usan para enviar flujo a otros servidores RTMP/RTSP en LAN o Internet, soportando H.265/H.264.",
      tipBuiltin: "Este dispositivo tiene un servidor RTMP integrado compatible con recepción H.264/H.265;<br>Si la URL del flujo RTMP se establece en \"/live/0\", PotPlayer puede reproducir vía http://IP-del-dispositivo/live/0.",
      tipMode: "El modo de transmisión RTMP solo tiene efecto con H.265 y también afecta al flujo FLV;"
    },

    // SRT settings
    srt: {
      listenerUri: "URL de escucha SRT:",
      callerUri: "URL de llamada SRT:",
      // Tips
      tipListener: "El modo SRT Listener escucha en un puerto local para que los reproductores tiren del flujo.<br>Por ejemplo: srt://0.0.0.0:9000;<br>VLC puede reproducir \"srt://IP-del-dispositivo:9000\".<br>Ejemplo con streamid:<br>srt://0.0.0.0:9000?streamid=channel100<br>Ejemplo con contraseña (mínimo 10 caracteres):<br>srt://0.0.0.0:9000?passphrase=0123456789<br>Ejemplo con streamid y contraseña:<br>srt://0.0.0.0:9000?streamid=channel100&passphrase=0123456789",
      tipCaller: "El modo SRT Caller envía el flujo a otro servidor, por ejemplo:<br>srt://live.example.com:9000?streamid=channel100&latency=120&maxbw=8000000",
      tipParams: "Parámetros SRT soportados (ver protocolo SRT):<br>streamid - identificador de flujo para multiplexación<br>passphrase - contraseña de cifrado, SRT requiere 10-79 caracteres<br>pbkeylen - longitud de clave: 16 (AES-128), 24 (AES-192), 32 (AES-256)<br>latency - latencia en ms (20-8000ms)<br>maxbw - ancho de banda máximo en bytes/s<br>rcvbuf - tamaño del búfer de recepción<br>sndbuf - tamaño del búfer de envío<br>ipttl - valor TTL IP<br>conntimeo - tiempo de espera de conexión en ms"
    },

    ndi: {
      enable: "Salida NDI:",
      name: "Nombre de la fuente:",
      mainStream: "Stream de calidad completa:",
      previewStream: "Stream de vista previa (fijo 640x360):",
      groups: "Grupos NDI:",
      tipScope: "Con NDI activado, los receptores de la LAN (NDI Studio Monitor, vMix, OBS, etc.) detectan esta fuente automáticamente; aparece como: NombreDelDispositivo (Nombre de la fuente).",
      tipPreview: "NDI requiere un stream de calidad completa más un stream de vista previa de 640 píxeles de ancho. Al activarlo, la resolución del stream de vista previa seleccionado se fija en 640x360.",
      unlicensed: "Introduzca un código de licencia para activar.",
      unlicensedHint: "Versión sin licencia, limitada a 30 minutos. ",
      licenseCode: "Código de licencia:",
      activate: "Activar",
      deviceId: "ID del dispositivo:",
      deviceTypeLabel: "Tipo de dispositivo:",
      globalTitle: "Ajustes globales (se aplican a todos los puertos)",
      tabGlobal: "Ajustes globales",
      gotoLicense: "Ir a la activación",
      discoveryEnable: "Discovery Server:",
      discoveryServer: "Dirección del servidor:",
      serverHint: "El puerto predeterminado del Discovery Server es 5959.",
      sendMode: "Modo de envío de datos:",
      sendModeAuto: "Automático (unidifusión)",
      sendModeMulticast: "Multidifusión",
      multicastAddr: "Prefijo de dirección de multidifusión:",
      multicastMask: "Máscara de multidifusión:",
      tipDiscovery: "Con Discovery Server activado, este dispositivo deja de usar mDNS; los receptores deben configurar la misma dirección del Discovery Server para encontrar las fuentes. Adecuado para redes enrutadas o sin multidifusión. Separe varios servidores con comas.",
      tipMulticast: "El envío por multidifusión permite que muchos receptores compartan un mismo flujo, pero requiere IGMP snooping correctamente configurado en los switches; activarlo en una red no preparada puede saturarla. Úselo solo en redes gestionadas."
    },
    // WebRTC settings
    webrtc: {
      previewTitle: "Vista previa web",
      previewNote: "(vista previa de baja latencia en la página de estado)",
      whipTitle: "Publicación WHIP",
      whipNote: "(enviar a un servidor, para muchos espectadores)",
      p2pTitle: "P2P remoto",
      p2pNote: "(NAT traversal, para pocos espectadores remotos)",
      optional: "opcional",
      preview: "Vista previa web",
      whipServer: "URL de envío",
      whipToken: "Token Bearer",
      p2pServer: "URL del servidor de señalización",
      p2pUuid: "UUID del dispositivo",
      p2pToken: "Token de autenticación P2P:",
      p2pAuthToken: "Token de autorización",
      regenerate: "Regenerar",
      // Tips
      tipPreview: "La vista previa WebRTC en navegadores modernos soporta vídeo H.264 y audio Opus/G.711.<br>Usar Opus ofrece mejores resultados. Si no se configura, se usa G.711 8K por defecto.",
      tipWhip: "El envío WHIP conecta con servidores WHIP estándar. Copie la URL desde su servidor.<br>El token Bearer puede quedar vacío.",
      tipP2p: "Tras activar el servidor P2P, la URL de visualización aparece en la página de estado.<br>El token de autenticación P2P puede quedar vacío.",
      tipP2pNote: "P2P puede no conectarse en entornos de intranet complejos."
    },

    // TRTC settings
    trtc: {
      roomId: "ID de sala TRTC:",
      userId: "Usuario TRTC:",
      roomKey: "Clave de sala TRTC:",
      userSig: "TRTC UserSig:",
      sdkAppId: "TRTC SDKAppID:",
      roomIdType: "Tipo de ID de sala TRTC:",
      roomIdNumber: "Número",
      roomIdString: "Cadena",
      // Short labels
      number: "Número",
      string: "Cadena",
      // Tips
      tipTrtc: "Envía el flujo al servidor TRTC de Tencent. Copie los parámetros desde su servidor.<br>Actualmente TRTC solo soporta H.264."
    },

    alirtc: {
      roomId: "ID de sala AliRTC:",
      userId: "ID de usuario AliRTC:",
      userName: "Nombre de usuario AliRTC:",
      region: "Región AliRTC:",
      token: "AliRTC Token:",
      tipAliRtcToken: "Envía streams a Alibaba Cloud RTC con soporte para H.265/H.264.<br>Puede introducir directamente el token proporcionado por el servicio, o hacer clic en AliRTC Token para generar un token con AppID/AppKey en la página independiente.<br>Si el token está vacío, el dispositivo intentará generarlo automáticamente al iniciar usando el AppID/AppKey guardado en la página independiente.<br>Si cambian el ID de sala, el ID de usuario o el nombre de usuario, es posible que deba generar el token de nuevo."
    },

    alirtcTokenPage: {
      title: "AliRTC Token",
      roomId: "ID de sala AliRTC:",
      userId: "ID de usuario AliRTC:",
      userName: "Nombre de usuario AliRTC:",
      appId: "AliRTC AppID:",
      appKey: "AliRTC AppKey:",
      token: "AliRTC Token:",
      generate: "Generar y guardar token",
      appFieldsRequired: "AliRTC AppID y AppKey son obligatorios.",
      identityRequired: "El ID de sala, el ID de usuario y el nombre de usuario de AliRTC son obligatorios en la configuración de salida del flujo actual.",
      generateSuccess: "El token de AliRTC se generó y guardó.",
      generateFailed: "No se pudo generar el token de AliRTC.",
      unavailable: "AliRTC no está disponible en este dispositivo."
    },

    // HLS settings
    hls: {
      hlsTsUri: "URL de flujo HLS TS:",
      hlsMp4Uri: "URL de flujo HLS MP4:",
      hlsPushUri: "URL de publicación HLS:",
      hlsPushUrl: "URL de publicación HLS:",
      // Tips
      tipHls: "Cuando HLS TS/MP4 está habilitado, el dispositivo almacena datos en memoria según el tiempo y número de segmentos configurados en Ajustes avanzados.<br>Configurar ambos valores a 3 reduce el uso de memoria.",
      tipPush: "La URL de publicación HLS se usa para enviar flujo a servidores como YouTube."
    },

    // MP4/FLV/Other settings
    other: {
      mp4Uri: "URL de flujo MP4:",
      flvUri: "URL de flujo FLV:",
      icecastUri: "URL de publicación ICECAST:",
      icecastPushUrl: "URL de publicación ICECAST:",
      shoutcastUri: "URL de publicación Shoutcast:",
      shoutcastPushUrl: "URL de publicación Shoutcast:",
      // Tips
      tipMp4: "Cuando el flujo MP4 está activado, puede reproducirse directamente en el navegador.<br>El flujo FLV en este dispositivo soporta H.265/H.264, pero VLC y otros reproductores suelen soportar solo H.264.<br>ICECAST/Shoutcast solo soportan MP3, para envío a servidores de audio.",
      tipShoutcast: "Shoutcast soporta v1 y v2;<br>Ejemplos:<br>http://password@shoutcast_server:8000<br>http://password@shoutcast_server:8000?sid=100<br>http://password@shoutcast_server:8000?icy-name=Stream&icy-genre=Pop<br>Formato:<br>http://password@IP-servidor:puerto-escucha[?parámetros...]; el usuario puede omitirse (por defecto \"source\").<br>Use el \"puerto de escucha\" del servidor; el dispositivo se conectará automáticamente al puerto source (puerto de escucha + 1).<br>Parámetros soportados:<br>sid: ID de flujo Shoutcast v2 (por defecto 1)<br>icy-name: nombre de flujo (opcional)<br>icy-genre: género (opcional)<br>icy-url: URL del sitio web (opcional)<br>icy-pub: público 0/1 (opcional)"
    },

    // Common
    common: {
      save: "Guardar",
      disabled: "Desactivado",
      enabled: "Activado"
    },

    // Error and success messages
    messages: {
      success: "¡Configuración guardada!",
      failed: "¡Error al guardar la configuración!",
      emptyError: "¡La configuración no puede estar vacía!",
      trtcH264Only: "Cuando TRTC está activado, solo se permite codificación H.264. Se ha ajustado automáticamente.",
      mp3Required: "¡Configure la codificación de audio a MP3!",
      subStreamDisabled: "Sub-stream settings are disabled.",
      // Encoding validation
      frameRateError: "¡La tasa de fotogramas debe ser un entero entre 5 y 60!",
      gopError: "¡El intervalo GOP debe ser un entero entre 5 y 300!",
      mjpegQualityError: "¡La calidad MJPEG debe ser un entero entre 10 y 99!",
      hlsBitrateWarning: "El bitrate no está en el rango 32~8000, se desactivan los flujos HLS TS/MP4/PUSH.",
      trtcCodecWarning: "El códec no es H.264, se desactiva TRTC.",
      alirtcFieldsRequired: "Cuando AliRTC está habilitado, AppID, AppKey, ID de sala, ID de usuario y nombre de usuario son obligatorios.",
      alirtcIdentityRequired: "Cuando AliRTC está habilitado, el ID de sala, el ID de usuario y el nombre de usuario son obligatorios.",
      hlsBitrateError: "El bitrate no está en el rango 32~8000, no se pueden activar los flujos HLS TS/MP4/PUSH.",
      // SRT validation
      srtListenerPortError: "¡El puerto SRT Listener debe ser un entero entre 1 y 65535!",
      srtListenerFormatError: "¡Formato de URL SRT Listener no válido!",
      srtCallerFormatError: "¡Formato de URL SRT Caller no válido!",
      srtPasswordLengthError: "¡La contraseña SRT decodificada de la URL debe tener entre 10 y 79 bytes!",
      srtLatencyError: "¡La latencia SRT debe ser un entero entre 1 y 10000!",
      srtBandwidthError: "¡El ancho de banda SRT debe ser un entero entre 0 y 102400!",
      // RTMP validation
      rtmpFormatError: "La URL de publicación debe comenzar por rtmp://, rtmps://, rtsp:// o rtmpt://",
      // HLS validation
      hlsFormatError: "¡Formato de URL de publicación HLS no válido!",
      // RTSP validation
      rtspMulticastIpError: "¡Formato de IP multicast RTSP no válido!",
      rtspMulticastPortError: "¡El puerto multicast RTSP debe ser un entero entre 1 y 65535!",
      // TS validation
      multicastIpError: "¡Formato de IP multicast no válido!",
      multicastPortError: "¡El puerto multicast debe ser un entero entre 1 y 65535!",
      tsTransportIdError: "¡El ID de flujo de transporte TS debe ser un entero entre 1 y 65535!",
      tsNetworkIdError: "¡El ID de red original TS debe ser un entero entre 1 y 65535!",
      tsPmtPidError: "¡El PID inicial PMT TS debe ser un entero entre 32 y 8186!",
      tsStartPidError: "¡El PID inicial TS debe ser un entero entre 32 y 3840!",
      tsPidConflict: "¡El PID inicial TS y el PID inicial PMT TS deben ser diferentes!",
      tsVersionError: "¡La versión de tablas TS debe ser un entero entre 0 y 31!",
      tsServiceIdError: "¡El ID de servicio TS debe ser un entero entre 1 y 65535!",
      tsVideoPidError: "¡El PID de vídeo TS debe ser un entero entre 16 y 8190!",
      tsAudioPidError: "¡El PID de audio TS debe ser un entero entre 16 y 8190!",
      tsPcrPeriodError: "¡El período PCR TS debe ser un entero entre 0 y 100 (0=automático)!",
      tsVideoPidConflict: "¡El PID de vídeo TS y el PID de audio TS deben ser diferentes!",
      tsAudioPmtConflict: "¡El PID de audio TS y el PID inicial PMT TS deben ser diferentes!",
      tsVideoPmtConflict: "¡El PID de vídeo TS y el PID inicial PMT TS deben ser diferentes!",
      // Other validation
      icecastFormatError: "¡Formato de URL de publicación Icecast no válido!",
      shoutcastFormatError: "¡Formato de URL de publicación Shoutcast no válido!",
      ndiNameEmpty: "¡El nombre de la fuente NDI no puede estar vacío!",
      ndiSameStream: "¡El stream principal y el de vista previa de NDI deben ser diferentes!",
      ndiLicenseOk: "¡Licencia activada correctamente!",
      ndiLicenseFail: "¡Código de licencia no válido!",
      ndiDiscoveryServerEmpty: "¡La dirección del Discovery Server no puede estar vacía!",
      ndiMulticastAddrError: "¡Dirección o máscara de multidifusión no válida!"
    }
  }
};
