// French translations
window.LANG_FR = {
  // Common
  common: {
    save: "Enregistrer",
    cancel: "Annuler",
    confirm: "Confirmer",
    loading: "Chargement...",
    success: "Succès",
    failed: "Échec",
    delete: "Supprimer",
    edit: "Modifier",
    add: "Ajouter",
    enable: "Activer",
    disable: "Désactiver",
    enabled: "Activé",
    disabled: "Désactivé",
    yes: "Oui",
    no: "Non",
    on: "Marche",
    off: "Arrêt",
    apply: "Appliquer",
    reset: "Réinitialiser",
    refresh: "Actualiser",
    close: "Fermer",
    back: "Retour",
    next: "Suivant",
    previous: "Précédent",
    submit: "Soumettre",
    action: "Action",
    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: "Continuer",
    copy: "Copier",
    copied: "Copié"
  },

  preview: {
    flvRequired: "Veuillez activer le flux FLV.",
    flvOrHlsRequired: "Veuillez activer au moins un flux en direct : FLV ou HLS.",
    hlsUnsupportedEnableFlv: "L'aperçu HLS n'est pas pris en charge par ce navigateur. Veuillez activer FLV."
  },

  play: {
    mainFlvRequired: "Le flux FLV principal doit être activé",
    browserFlvUnsupported: "Ce navigateur ne prend pas en charge la lecture FLV. Veuillez utiliser un navigateur moderne comme Chrome, Edge ou Firefox"
  },

  // Page titles
  title: {
    encoder: "Encodeur H.265/H.264",
    status: "État",
    mainStream: "Flux principal",
    subStream1: "Flux secondaire 1",
    subStream2: "Flux secondaire 2",
    subStream3: "Flux secondaire 3",
    videoSettings: "Paramètres vidéo",
    audioSettings: "Paramètres audio",
    advancedSettings: "Paramètres avancés",
    osdMain: "OSD - Flux principal",
    osdSub1: "OSD - Flux secondaire 1",
    osdSub2: "OSD - Flux secondaire 2",
    osdSub3: "OSD - Flux secondaire 3",
    logoUpload: "Téléchargement du logo",
    network: "Paramètres réseau",
    record: "Paramètres d'enregistrement",
    gb28181: "GB28181",
    wifi: "Paramètres WiFi",
    g4: "Paramètres 4G/5G",
    password: "Paramètres du mot de passe",
    serial: "Transport série",
    update: "Mise à jour et sauvegarde",
    reboot: "Redémarrer l'appareil",
    timedReboot: "Redémarrage programmé",
    factoryReset: "Réinitialisation d'usine",
    recordFiles: "Fichiers d'enregistrement",
    netTest: "Test réseau",
    recordSet: "Paramètres d'enregistrement"
  },

  // Menu
  menu: {
    status: "État",
    encoder: "Encodeur",
    mainStream: "Flux principal",
    subStream1: "Flux secondaire 1",
    subStream2: "Flux secondaire 2",
    subStream3: "Flux secondaire 3",
    videoSettings: "Paramètres vidéo",
    audioSettings: "Paramètres audio",
    advancedSettings: "Paramètres avancés",
    osd: "OSD",
    logoUpload: "Téléchargement du logo",
    system: "Système",
    network: "Réseau",
    record: "Enregistrement",
    gb28181: "GB28181",
    wifi: "WiFi",
    g4: "4G/5G",
    password: "Mot de passe",
    serial: "Transport série",
    update: "Mise à jour et sauvegarde",
    reboot: "Redémarrage",
    timedReboot: "Redémarrage programmé",
    factoryReset: "Réinitialisation d'usine"
  },

  // Status page
  status: {
    // Device status
    deviceStatus: "État de l'appareil",
    runningTime: "Temps de fonctionnement : ",
    runtimeDayWithTime: "{0}j {1}",
    deviceTime: "Heure de l'appareil : ",
    syncTime: " (Synchroniser l'heure avec l'appareil)",
    cpuUsage: "Utilisation CPU : ",
    cpuTemp: "Température CPU : ",
    memoryUsage: "Utilisation mémoire : ",
    encPpsUsage: "Utilisation des ressources d'encodage : ",
    memoryWarning: " (Si l'utilisation mémoire est trop élevée après 1 minute de démarrage, veuillez désactiver certains flux HLS ou réduire le débit)",
    cpuWarning: " (Si l'utilisation CPU reste au-dessus de 85%, veuillez désactiver certains flux ou réduire la résolution des flux secondaires)",
    networkStatus: "État du réseau : ",
    inputVideo: "Vidéo d'entrée : ",
    vgaAutoAdjust: " (Ajustement auto VGA)",
    capturedFrames: "Images vidéo capturées : ",
    lostFrames: "Images vidéo perdues : ",
    audioSampleRate: "Taux d'échantillonnage audio d'entrée : ",
    capturedAudioFrames: "Images audio capturées : ",
    packetsSent: "Paquets envoyés : ",
    netTestLink: " (Test réseau & Journal système)",
    packetsDropped: "Paquets perdus : ",
    canAccessInternet: "Accès Internet",
    canAccessInternetIP: "Accès IP Internet",
    lanOnly: "LAN uniquement",
    localNetwork: "Réseau local",

    // Recording status
    recordStatus: "État d'enregistrement",
    recordType: "Type d'enregistrement : ",
    diskStatus: "État du disque : ",
    diskNotExist: "Non trouvé",
    mountStatus: "État du montage : ",
    notMounted: "Non monté",
    mounted: "Monté",
    totalSpace: "Espace total : ",
    freeSpace: "Espace libre : ",
    recordingStatus: "État d'enregistrement : ",
    diskFull: "Disque plein",
    diskSlow: "Disque trop lent",
    recordFileList: "Liste des fichiers d'enregistrement",
    notRecording: "Pas d'enregistrement",
    recording: "Enregistrement en cours",
    recordingNoVideo: " (Les fichiers peuvent ne pas être sauvegardés sans entrée vidéo)",
    startRecord: "(Démarrer l'enregistrement)",
    stopRecord: "(Arrêter l'enregistrement)",
    usbTfCard: "USB/Carte TF",

    // DHCP status
    dhcpStatus: "État DHCP",
    ip: "IP : ",
    subnetMask: "Masque de sous-réseau : ",
    gateway: "Passerelle : ",

    // WIFI status
    wifiStatus: "État WiFi",
    wifiDisabled: "WiFi : Désactivé",
    wifiState: "État WiFi : ",
    wifiSSID: "SSID WiFi : ",
    wifiIP: "IP WiFi : ",
    wifiMAC: "MAC WiFi : ",
    wifiRSSI: "Signal WiFi (RSSI) : ",
    wifiFreq: "Fréquence WiFi : ",
    wifiConnected: "Connecté",
    wifiDisconnected: "Déconnecté",
    wifiConnecting: "Connexion en cours (Si la connexion prend trop de temps, veuillez vérifier les paramètres WiFi)",

    // 4G/5G status
    g4Status: "État 4G/5G",
    g4Disabled: "4G/5G : Désactivé",
    status: "État : ",
    imei: "IMEI : ",
    mode: "Mode : ",
    signalStrength: "Puissance du signal : ",
    noSignal: "Pas de signal",
    gpsTime: "Heure GPS : ",
    gpsLocation: "Position GPS : ",
    gpsHeight: "Altitude GPS : ",
    onlineTime: "Temps en ligne : ",
    receivedBytes: "Reçu : ",
    sentBytes: "Envoyé : ",
    g4Connected: "Connecté",
    g4Connecting: "Connexion en cours",
    g4Disconnected: "Déconnecté",
    timeHour: "h",
    timeMinute: "m",
    timeSecond: "s",

    // Streams
    mainStream: "Flux principal",
    subStream1: "Flux secondaire 1",
    subStream2: "Flux secondaire 2",
    subStream3: "Flux secondaire 3",
    streamDisabled: "Désactivé (Les flux secondaires sont désactivés quand le flux principal est à 31-60 fps)",
    codecType: "Codec : ",
    encodeResolution: "Résolution d'encodage : ",
    videoBitrate: "Débit vidéo : ",
    realTimeBitrate: "Débit en temps réel : ",
    realTimeFps: "FPS en temps réel : ",
    videoEncoded: "Vidéo encodée : ",
    reconnect: " (Reconnecter)",
	    previewWebRTC: "Aperçu vidéo (WebRTC)",
	    previewHTML5: "Aperçu vidéo (HTML5)",

    // URL related
    disabled: "Désactivé",
    connected: "Connecté",
    disconnected: "Déconnecté",
    bufferPackets: "Paquets en buffer",
    bufferPacketsLabel: "Paquets en buffer : ",
    pushSpeed: "Vitesse d'envoi",
    pushSpeedLabel: "Vitesse d'envoi : ",
    pushed: "Envoyé",
    pushedLabel: "Envoyé : ",
    memoryUsed: "Mémoire utilisée",
    memoryUsedLabel: "Mémoire utilisée : ",
    cacheFiles: "Fichiers en cache",
    cacheFilesLabel: "Fichiers en cache : ",
    multicastUrl: "URL Multicast : ",
    mjpgUrl: "URL flux MJPG : ",
    jpgUrl: "URL flux JPG : ",
    tsUrl: "URL du flux TS : ",
    flvUrl: "URL flux FLV : ",
    hlsTsUrl: "URL flux HLS TS : ",
    hlsMp4Url: "URL flux HLS MP4 : ",
    mp4Url: "URL flux MP4 : ",
    rtspUrl: "URL flux RTSP : ",
    rtmpUrl: "URL flux RTMP : ",
    srtListenerUrl: "URL SRT Listener : ",
    webrtcP2pUrl: "URL flux WebRTC P2P : ",
    rtmpPushUrlAny: "URL publication RTMP(S)/RTSP {0} : ",
    rtmpPushUrlAny0: "URL publication RTMP(S)/RTSP 0 : ",
    rtmpPushUrlAny1: "URL publication RTMP(S)/RTSP 1 : ",
    rtmpPushUrlAny2: "URL publication RTMP(S)/RTSP 2 : ",
    rtmpPushUrl: "URL publication RTMP(S) {0} : ",
    rtspPushUrl: "URL publication RTSP {0} : ",
    srtCallerUrl: "URL SRT Caller : ",
    hlsPushUrl: "URL PUSH HLS : ",
    icecastPushUrl: "URL PUSH ICECAST : ",
    shoutcastPushUrl: "URL PUSH Shoutcast : ",
    whipLabel: "WHIP : ",
    viewers: "Spectateurs",
    viewersLabel: "Spectateurs : ",

    // TRTC status
    trtcRoomId: "ID de salle TRTC : ",
    inRoom: "Dans la salle",
    notInRoom: "Pas dans la salle",
    initializingServer: "Initialisation de la connexion serveur",
    serverDisconnected: "Serveur déconnecté",
    connectingServer: "Connexion au serveur",
    serverConnected: "Connecté au serveur",
    networkUnknown: "État du réseau inconnu",
    networkExcellent: "Excellent réseau",
    networkGood: "Bon réseau",
    networkNormal: "Réseau normal",
    networkPoor: "Réseau médiocre",
    networkBad: "Mauvais réseau",
    networkNotMeet: "Le réseau ne répond pas aux exigences minimales TRTC",
    errorCode: "Code d'erreur",
    errorCodeLabel: "Code d'erreur : ",
    trtcError1: "Erreur générale, vérifiez les fichiers journaux",
    trtcError100: "Erreur de logique métier : appel illégal",
    trtcError101: "Erreur de logique métier : paramètre illégal",
    trtcError102: "Impossible de lire actuellement, veuillez réessayer",
    trtcError103: "Impossible de se connecter au réseau",
    trtcError200: "Échec d'entrée dans la salle",
    trtcError201: "Paramètre user_sig invalide",
    trtcError202: "Format d'ID de salle invalide",
    trtcError203: "sdk_app_id invalide",
    trtcError204: "Service indisponible. Vérifiez si les minutes du forfait > 0 et que le compte Tencent Cloud n'est pas en retard",
    trtcError205: "L'utilisateur a été expulsé de la salle par le serveur",

    // WHIP status
    whipInitializing: "Initialisation",
    whipConnected: "Connecté",
    whipDisconnected: "Déconnecté",
    whipUnknown: "État inconnu",

    // GB28181
    gb28181: "GB28181 : ",
    gb28181Online: "En ligne",
    gb28181Offline: "Hors ligne"
  },

  // Reboot page
  reboot: {
    title: "Redémarrer l'appareil",
    description: "Cliquez sur ce bouton pour redémarrer l'encodeur.",
    button: "Redémarrer",
    success: "Commande de redémarrage envoyée !",
    failed: "Échec du redémarrage !",
    confirm: "Êtes-vous sûr de vouloir redémarrer l'appareil ?"
  },

  // Factory reset page
  reset: {
    title: "Réinitialisation d'usine",
    description: "Cliquez sur ce bouton pour restaurer tous les paramètres de l'encodeur à leur état d'usine par défaut.",
    button: "Réinitialiser",
    success: "Réinitialisation d'usine réussie ! Le système redémarrera automatiquement, veuillez patienter.",
    failed: "Échec de la réinitialisation d'usine !",
    confirm: "Êtes-vous sûr de vouloir restaurer les paramètres d'usine ?"
  },

  // Scheduled reboot page
  timedReboot: {
    title: "Redémarrage programmé",
    enable: "Redémarrage programmé",
    enableLabel: "Redémarrage programmé :",
    timeLabel: "Heure de redémarrage :",
    enabled: "Activer",
    disabled: "Désactiver",
    time: "Heure de redémarrage",
    weekdays: "Jours de redémarrage",
    everyday: "Tous les jours",
    monday: "Lundi",
    tuesday: "Mardi",
    wednesday: "Mercredi",
    thursday: "Jeudi",
    friday: "Vendredi",
    saturday: "Samedi",
    sunday: "Dimanche",
    save: "Enregistrer",
    saveSuccess: "Paramètres enregistrés !",
    saveFailed: "Échec des paramètres !",
    invalidTime: "Valeur de temps invalide !"
  },

  // Network test page
  netTest: {
    title: "Test réseau & Journal système",
    command: "Commande :",
    run: "Exécuter",
    address: "Adresse :",
    result: "Résultat :",
    invalidAddr: "Veuillez entrer une adresse valide !"
  },

  // Record files page
  recordFiles: {
    title: "Liste des fichiers",
    fileName: "Nom du fichier",
    time: "Heure",
    fileSize: "Taille du fichier",
    action: "Action",
    delete: "Supprimer",
    confirmDelete: "Êtes-vous sûr de vouloir supprimer",
    deleteSuccess: "Commande de suppression envoyée avec succès !",
    deleteFailed: "Échec de la suppression !",
    noFiles: "Aucun fichier d'enregistrement",
    loadError: "Échec du chargement"
  },

  // Password settings page
  password: {
    title: "Paramètres du mot de passe",
    oldPassword: "Ancien mot de passe",
    oldPasswordLabel: "Ancien mot de passe :",
    newPassword: "Nouveau mot de passe",
    newPasswordLabel: "Nouveau mot de passe :",
    confirmPassword: "Confirmer le mot de passe",
    confirmPasswordLabel: "Confirmer le mot de passe :",
    save: "Enregistrer",
    success: "Paramètres enregistrés !",
    failed: "Échec du paramétrage du mot de passe, veuillez vérifier l'ancien mot de passe !",
    mismatch: "Les nouveaux mots de passe ne correspondent pas !",
    empty: "Le mot de passe ne peut pas être vide !"
  },

  // Encoding common (only actually used keys)
  encoding: {
    sameAsInput: "Identique à la résolution d'entrée",
    mp3Required: "Veuillez régler l'encodage audio sur MP3 !",
    choosePrimaryColor: "Choisir la couleur principale",
    toggleTheme: "Changer de thème"
  },

  // OSD settings
  osd: {
    title: "Paramètres OSD",
    mainStream: "OSD Flux principal",
    subStream1: "OSD Flux secondaire 1",
    subStream2: "OSD Flux secondaire 2",
    subStream3: "OSD Flux secondaire 3",
    alpha: "Transparence",
    alphaLabel: "Transparence :",
    alphaRange: "[0-255]",
    alphaError: "La transparence doit être un entier entre 0-255 !",
    region: "Région",
    regionLabel: "Région :",
    region1: "Région 1",
    region2: "Région 2",
    region3: "Région 3",
    region4: "Région 4",
    type: "Type",
    typeLabel: "Type :",
    typeText: "Texte",
    typeImage: "Image",
    typeScroll: "Texte défilant",
    typeTime: "Heure",
    position: "Position",
    positionLabel: "Position :",
    speed: "Vitesse",
    speedLabel: "Vitesse :",
    xLabel: "X :",
    yLabel: "Y :",
    textLabel: "Texte :",
    fontSize: "Taille de police",
    fontSizeLabel: "Taille de police :",
    fontSizeRange: "[8-72]",
    backgroundColor: "Couleur d'arrière-plan",
    backgroundLabel: "Couleur d'arrière-plan :",
    bgTransparent: "Transparent",
    bgWhite: "Blanc",
    bgBlack: "Noir",
    fontColor: "Couleur de police",
    fontColorLabel: "Couleur de police :",
    pickColor: "Choisir la couleur",
    closeColor: "Fermer",
    logoLabel: "LOGO :",
    success: "Paramètres enregistrés avec succès !",
    failed: "Échec des paramètres !",
    xRangeError: "{0} La valeur X doit être un entier entre 0-{1} !",
    yRangeError: "{0} La valeur Y doit être un entier entre 0-{1} !",
    textEmpty: "{0} Le texte ne peut pas être vide !",
    fontSizeError: "{0} La taille de police doit être un entier entre 8-72 !",
    speedRangeError: "{0} La vitesse doit être un entier entre 0-30 !",
    positionRangeError: "{0} La position doit être un entier entre 0-{1} !",
    selectLogo: "Veuillez sélectionner un LOGO pour {0} !",
    webrtcPreview: "Aperçu vidéo"
  },

  // LOGO upload
  logo: {
    title: "Téléchargement du logo",
    logoLabel: "LOGO :",
    upload: "Télécharger",
    hint: "Veuillez télécharger une image PNG ou BMP 24 bits inférieure à 500 Ko (0xF1F1F1 est transparent),",
    hint2: "nom de fichier : logo1.bmp / logo2.bmp / logo3.bmp / logo4.bmp,",
    hint3: "ou logo1.png / logo2.png / logo3.png / logo4.png",
    noFileSelected: "Veuillez sélectionner un fichier à télécharger !",
    invalidFile: "Veuillez télécharger les images selon les exigences !",
    uploadSuccess: "Téléchargement réussi !",
    uploadFailed: "Échec du téléchargement !",
    imageSizeExceeded: "La taille du fichier image dépasse la limite !",
    imageResolutionExceeded: "La résolution du fichier image dépasse la limite !",
    storageInsufficient: "Fichier de mise à jour trop volumineux, espace de stockage insuffisant !"
  },

  // WIFI settings
  wifi: {
    title: "Paramètres WiFi",
    mode: "Mode",
    ap: "Point d'accès",
    sta: "Mode client",
    ssid: "SSID",
    password: "Mot de passe",
    security: "Sécurité",
    channel: "Canal",
    scan: "Scanner",
    connect: "Connecter",
    disconnect: "Déconnecter",
    status: "État",
    connected: "Connecté",
    disconnected: "Déconnecté",
    signalStrength: "Puissance du signal",
    basicSettings: "Paramètres de base",
    wifiModule: "Module WiFi :",
    wifiMode: "Mode WiFi :",
    staMode: "Mode STA",
    apMode: "Mode AP",
    mainConfig: "Config principale WiFi",
    backupConfig1: "Config de secours WiFi 1",
    backupConfig2: "Config de secours WiFi 2",
    apModeSettings: "Mode AP",
    wifiList: "Liste WiFi :",
    wifiEssid: "ESSID WiFi :",
    wifiPassword: "Mot de passe WiFi :",
    wifiDhcp: "DHCP WiFi :",
    wifiIp: "IP WiFi :",
    wifiNetmask: "Masque réseau WiFi :",
    wifiGateway: "Passerelle WiFi :",
    backupEnable1: "Config de secours 1 :",
    backupEnable2: "Config de secours 2 :",
    wifiBand: "Bande WiFi :",
    wifiChannel: "Canal WiFi :",
    refresh: "Actualiser",
    success: "Paramètres enregistrés avec succès !",
    failed: "Échec de l'enregistrement des paramètres !",
    mainConfigEmpty: "Config principale WiFi : {0} ne peut pas être vide !",
    mainConfigInvalid: "Config principale WiFi : {0} format invalide !",
    backupConfigEmpty: "WiFi {0} : {1} ne peut pas être vide !",
    backupConfigInvalid: "WiFi {0} : {1} format invalide !",
    ipAddr: "Adresse IP",
    netmask: "Masque réseau",
    gateway: "Passerelle",
    essidEmpty: "Le nom WiFi ne peut pas être vide !",
    passwordTooShort: "Le mot de passe WiFi doit avoir au moins 8 caractères !"
  },

  // 4G/5G settings
  cellular: {
    title: "Paramètres 4G/5G",
    enable: "Activer",
    apn: "APN",
    username: "Nom d'utilisateur",
    password: "Mot de passe",
    status: "État",
    signalStrength: "Puissance du signal",
    operator: "Opérateur",
    connected: "Connecté",
    disconnected: "Déconnecté",
    connecting: "Connexion...",
    module: "Module 4G/5G :",
    apnLabel: "APN :",
    usernameLabel: "Nom d'utilisateur :",
    passwordLabel: "Mot de passe :",
    authType: "Type d'authentification :",
    dnsOrder: "Ordre DNS 4G/5G :",
    authNone: "Aucun",
    authPap: "PAP",
    authChap: "CHAP",
    authChapPap: "CHAP+PAP",
    success: "Paramètres enregistrés avec succès !",
    failed: "Échec de l'enregistrement des paramètres !"
  },

  // Upgrade and backup
  updateBackup: {
    title: "Mise à jour système",
    uploadTitle: "Télécharger le firmware et la configuration",
    backupTitle: "Sauvegarder le firmware et la configuration",
    systemVersion: "Version système",
    systemVersionLabel: "Version système : ",
    hardware: "Matériel",
    hardwareLabel: "Matériel : ",
    selectFile: "Sélectionner un fichier",
    selectFileLabel: "Sélectionner un fichier :",
    uploadHint: "Nom du fichier à télécharger : up.rar ou box.ini",
    uploadWarning: "Ne pas télécharger simultanément. Ne pas éteindre pendant le téléchargement.",
    upload: "Télécharger",
    backupFirmware: "Sauvegarder le firmware",
    backupConfig: "Sauvegarder la configuration",
    noFileSelected: "Veuillez sélectionner un fichier à télécharger !",
    uploadSuccess: "Téléchargement réussi, veuillez redémarrer le système !",
    uploadFailed: "Échec du téléchargement !",
    kernelUpdating: "La mise à jour du noyau prendra quelques minutes. Veuillez ne pas redémarrer le système. L'appareil redémarrera automatiquement une fois terminé.",
    kernelUpdatingBin: "La mise à jour du noyau prendra quelques minutes. Veuillez ne pas redémarrer le système. L'appareil redémarrera automatiquement une fois terminé !",
    imageSizeExceeded: "La taille du fichier image dépasse la limite !",
    imageResolutionExceeded: "La résolution du fichier image dépasse la limite !",
    storageInsufficient: "Fichier de mise à jour trop volumineux, espace de stockage insuffisant !"
  },

  // Serial transport settings
  serial: {
    title: "Transport série",
    frpTitle: "Paramètres client FRP",
    serialTitle: "Passthrough port série",
    enable: "Activer",
    disable: "Désactiver",
    enableLabel: "Activer :",
    serverAddr: "Adresse du serveur",
    serverAddrLabel: "Adresse du serveur :",
    serverPort: "Port du serveur",
    serverPortLabel: "Port du serveur :",
    serverToken: "Token du serveur",
    serverTokenLabel: "Token du serveur :",
    channel: "Canal",
    channel1: "Canal 1",
    channel2: "Canal 2",
    channel3: "Canal 3",
    channel4: "Canal 4",
    protocolLabel: "Protocole :",
    localPort: "Port local",
    localPortLabel: "Port local :",
    remotePort: "Port distant",
    remotePortLabel: "Port distant :",
    serialMode: "Mode série",
    serialModeLabel: "Mode :",
    server: "Serveur",
    client: "Client",
    baudRate: "Débit en bauds",
    baudRateLabel: "Débit en bauds :",
    listenPort: "Port d'écoute",
    listenPortLabel: "Port d'écoute :",
    save: "Enregistrer",
    success: "Paramètres enregistrés, veuillez redémarrer l'appareil !",
    failed: "Échec des paramètres !",
    emptyError: "Les paramètres ne peuvent pas être vides !",
    portRangeError: "Le port d'écoute TCP doit être un entier entre 1-65500 !",
    frpAddrEmpty: "L'adresse du serveur FRP ne peut pas être vide !",
    frpPortError: "Le port du serveur FRP doit être un entier entre 1-65500 !"
  },

  // Advanced Settings
  advanced: {
    title: "Paramètres avancés",
    // Section titles
    videoInput: "Entrée vidéo",
    avTransmission: "Transmission A/V",
    recordSettings: "Paramètres d'enregistrement",
    hlsSettings: "Paramètres HLS",
    networkTransmission: "Transmission de flux",
    serviceSettings: "Paramètres de service",
    logSettings: "Paramètres de journal",
    encoderParams: "Paramètres d'encodeur",
    imageEnhancement: "Amélioration d'image",
    autoRestart: "Redémarrage auto",
    // Video Input
    edidSelect: "Sélection EDID :",
    colorGamut: "Gamme de couleurs :",
    colorRange: "Plage de couleurs :",
    interlaceMode: "Mode entrelacé :",
    noSignal: "Pas de signal :",
    vgaAutoAdjust: "Ajustement auto VGA au démarrage :",
    interlaceWeaving: "Tissage (fusionner les champs)",
    interlaceBottom: "Champ inférieur uniquement",
    interlaceTop: "Champ supérieur uniquement",
    interlaceBobbing: "Bobbing (champ vers image)",
    noSignalHide: "Masquer",
    noSignalImage: "Afficher une image",
    noSignalColor: "Afficher une couleur unie",
    // A/V Transmission
    videoOnly: "Vidéo uniquement :",
    audioOnly: "Audio uniquement :",
    avSync: "Sync A/V :",
    audioDelay: "Délai audio (ms) :",
    syncAuto: "Auto",
    syncResample: "Rééchantillonnage",
    audioDelayHint: "Les valeurs négatives avancent l'audio, les positives le retardent. À utiliser uniquement pour le réglage de la sync A/V.",
    // Recording Settings
    recordType: "Type d'enregistrement :",
    cycleRecord: "Enregistrement cyclique :",
    recordSplitTime: "Temps de division d'enregistrement (sec) :",
    // HLS Settings
    hlsSplitTime: "Temps de segment HLS (sec) :",
    hlsBufferNum: "Nombre de segments HLS :",
    hlsIndexUri: "URI d'index global HLS :",
    // Network Transmission
    tsMuxer: "Muxeur TS :",
    netDropThreshold: "Seuil de perte de paquets :",
    tsOnce: "Paquets TS par envoi :",
    rtspPackType: "Encapsulation RTSP :",
    multicastType: "Type multicast :",
    enableSap: "Activer SAP :",
    mtuSize: "Taille MTU :",
    udpTtl: "TTL UDP :",
    udpSockBuf: "UDP SOCKET_BUF_SIZE :",
    vlcCompat: "Compatible VLC",
    ffmpegCompat: "Compatible FFMPEG",
    esStream: "Flux ES",
    tsStream: "Flux TS",
    // Service Settings
    tsRtspAuth: "Auth TS/RTSP requise :",
    httpNoAuth: "Accès web sans auth :",
    netCheck: "Vérification état réseau :",
    telnetService: "Service Telnet :",
    sambaService: "Service Samba :",
    onvifService: "Service ONVIF :",
    onvifLocation: "ONVIF Location:",
    rtspDefaultStream: "Flux RTSP par défaut :",
    vmixCompat: "Compatible VMix :",
    telnetLan: "LAN uniquement",
    // Log Settings
    localLog: "Service de journal local :",
    lokiAddr: "Adresse serveur Loki :",
    lokiPort: "Port serveur Loki :",
    // Encoder Parameters
    sliceSplit: "Division SLICE :",
    sliceBytes: "Octets SLICE :",
    minQp: "MIN_QP :",
    maxQp: "MAX_QP :",
    debreath: "Debreathing :",
    sar: "SAR :",
    cbrOnlyHint: "Effectif uniquement quand le mode de contrôle de débit est CBR",
    // Image Enhancement
    contrastEnhance: "Amélioration du contraste :",
    sharpnessEnhance: "Amélioration de la netteté :",
    lumaSfStrength: "Débruitage spatial luma :",
    lumaTfStrength: "Débruitage temporel luma :",
    chromaSfStrength: "Débruitage spatial chroma :",
    chromaTfStrength: "Débruitage temporel chroma :",
    // Auto Restart
    kickAllOnChange: "Déconnecter les utilisateurs au changement d'entrée :",
    noVideoReboot: "Redémarrage auto sans vidéo :",
    noAudioReboot: "Redémarrage auto sans audio :",
    // Button
    save: "Enregistrer",
    // Messages
    success: "Paramètres enregistrés, veuillez redémarrer l'appareil !",
    failed: "Échec des paramètres !",
    emptyError: "Les paramètres ne peuvent pas être vides !",
    netDropError: "Le seuil de perte de paquets doit être un entier entre 50-50000 !",
    tsOnceError: "Les paquets TS par envoi doivent être un entier entre 1-128 !",
    sliceError: "Les octets SLICE doivent être un entier entre 128-65535 !",
    minQpError: "MIN_QP doit être un entier entre 1-35 !",
    maxQpError: "MAX_QP doit être supérieur à MIN_QP et au maximum 50 !",
    udpTtlError: "TTL UDP doit être un entier entre 1-254 !",
    contrastError: "L'amélioration du contraste doit être un entier entre 0-63 !",
    sharpnessError: "L'amélioration de la netteté doit être un entier entre 0-16 !",
    lumaSfError: "Le débruitage spatial luma doit être un entier entre 0-255 !",
    lumaTfError: "Le débruitage temporel luma doit être un entier entre 0-63 !",
    chromaSfError: "Le débruitage spatial chroma doit être un entier entre 0-255 !",
    chromaTfError: "Le débruitage temporel chroma doit être un entier entre 0-32 !",
    hlsSplitError: "Le temps de segment HLS doit être un entier entre 3-20 !",
    hlsBufferError: "Le nombre de segments HLS doit être un entier entre 3-20 !",
    hlsUriError: "Le format de l'URI d'index global HLS est invalide !",
    udpSockBufError: "UDP SOCKET_BUF_SIZE doit être un entier entre 0-20971520 !",
    mtuError: "La taille MTU doit être un entier entre 500-1500 !",
    audioCacheError: "Le délai audio doit être un entier entre -2000 et 2000 !",
    recordSplitError: "Le temps de division d'enregistrement doit être un entier entre 60-7200 !",
    lokiPortError: "Le port serveur Loki doit être entre 1-65500"
  },

  // Audio Encoding Settings
  audioEnc: {
    title: "Paramètres audio",
    // Tabs
    tabAudio: "Paramètres audio",
    tabOnvif: "Audio ONVIF",
    // Tips
    tipAudio: "Ne réglez pas le gain de volume numérique trop haut, cela peut causer des distorsions ou du bruit.<br>Dans la plupart des cas, réglez le gain sur 0.<br>Ajustez le volume global avec les contrôles frontaux.",
    tipOnvif: "Pour se connecter à un NVR, réglez l'encodage RTSP G711 sur 'Activer et rééchantillonner à 8K'",
    // Audio Settings
    audioInput: "Entrée audio :",
    sampleRate: "Taux d'échantillonnage :",
    codec: "Codec :",
    channel: "Canaux :",
    bitrate: "Débit :",
    digitalGain: "Gain de volume numérique :",
    analogGain: "Gain de volume analogique :",
    denoise: "Débruitage :",
    denoiseStrength: "Force de débruitage (dB) :",
    pteG711: "Flux PTE G711 :",
    // Audio Input Options
    inputDigital: "Numérique",
    inputAnalog: "Analogique",
    inputMixed: "Mixte",
    // Sample Rate Options
    sampleSameAsInput: "Identique à l'entrée",
    // ONVIF Audio
    rtspG711: "Encodage RTSP G711 :",
    rtspG711Resample: "Activer et rééchantillonner à 8K",
    g711Codec: "Codec G711 :",
    // Buttons and Messages
    save: "Enregistrer",
    success: "Paramètres enregistrés !",
    failed: "Échec des paramètres !",
    emptyError: "Les paramètres ne peuvent pas être vides !",
    bitrateError: "Le débit doit être un entier entre {0}-{1} !",
    gainError: "Le gain de volume numérique doit être un entier entre -50 et 50 !",
    denoiseError: "La force de débruitage doit être un entier entre 1-100 !",
    analogVolEmpty: "Le gain de volume analogique ne peut pas être vide !",
    analogVolError: "Le gain de volume analogique doit être un entier entre {0} et {1} !"
  },

  // Recording Settings Page
  recordSet: {
    title: "Paramètres d'enregistrement",
    // Card Titles
    statusTitle: "État d'enregistrement",
    settingsTitle: "Paramètres d'enregistrement",
    // Status
    recordType: "Type d'enregistrement :",
    diskStatus: "État du disque :",
    currentAddr: "Adresse actuelle :",
    mountDevice: "Périphérique de montage :",
    mountStatus: "État du montage :",
    totalSpace: "Espace total :",
    freeSpace: "Espace libre :",
    recordStatus: "État d'enregistrement :",
    recordFiles: "Fichiers d'enregistrement :",
    fileList: "Liste des fichiers",
    // Disk Status
    diskNotExist: "Non présent",
    diskFull: "Disque plein",
    diskSlow: "Disque trop lent",
    mounted: "Monté",
    unmounted: "Non monté",
    notRecording: "Pas d'enregistrement",
    recording: "Enregistrement en cours",
    noVideoWarning: " (Les fichiers peuvent ne pas être sauvegardés sans entrée vidéo)",
    // Action Links
    startRecord: "(Démarrer l'enregistrement)",
    stopRecord: "(Arrêter l'enregistrement)",
    mountDisk: "(Monter le disque)",
    unmountDisk: "(Démonter le disque)",
    deleteAll: "(Supprimer tous les enregistrements)",
    // Settings
    storageType: "Type de stockage :",
    partition: "Partition :",
    partitionInfo: "Info partition :",
    diskInfo: "Info disque :",
    formatDisk: "(Reformater le disque)",
    exampleAddr: "Adresse exemple :",
    storageAddr: "Adresse de stockage :",
    username: "Nom d'utilisateur :",
    password: "Mot de passe :",
    // Storage Type Options
    storageDisabled: "Désactivé",
    storageUsb: "USB/Carte TF",
    storageNfs: "NFS",
    storageSamba: "SAMBA/CIFS",
    // Format Dialog
    formatTitle: "Information du disque",
    formatDevice: "Périphérique :",
    formatType: "Type :",
    formatModel: "Modèle :",
    formatRemovable: "Amovible :",
    formatPartTable: "Table de partition :",
    formatCapacity: "Capacité :",
    formatPartitions: "Information des partitions",
    formatPartition: "Partition",
    formatAvailable: "(disponible)",
    formatTotal: "(total)",
    formatConfirm: "Continuer le formatage du disque ?",
    formatDanger: "Attention : Le formatage va repartitionner et toutes les données seront perdues. Continuer ?",
    formatContinue: "Continuer",
    formatCancel: "Annuler",
    formatConfirmBtn: "Confirmer",
    formatting: "Formatage...",
    // Buttons and Messages
    save: "Enregistrer",
    yes: "Oui",
    no: "Non",
    success: "Paramètres enregistrés !",
    failed: "Échec des paramètres !",
    formatSuccess: "Formatage réussi !",
    formatFailed: "Échec du formatage !",
    deleteSuccess: "Commande de suppression envoyée !",
    deleteFailed: "Échec de la suppression !",
    confirmDeleteAll: "Supprimer tous les fichiers d'enregistrement ?",
    recordingWarning: "Enregistrement en cours. Arrêtez l'enregistrement avant de démonter.",
    diskMountedWarning: "Le disque est monté. Démontez avant de formater.",
    diskMountedSettingWarning: "Le disque est monté. Démontez avant de modifier les paramètres.",
    partitionNotExist: "La partition n'existe pas",
    partitionRemoved: " (Supprimée)",
    // Address Validation
    addrEmpty: "L'adresse de stockage ne peut pas être vide !",
    addrNfsFormat: "Format d'adresse invalide, doit contenir le séparateur ':'",
    addrIpError: "Format d'adresse IP invalide",
    addrPathSlash: "Le chemin doit commencer par '/'",
    addrPathInvalid: "Le chemin contient des caractères invalides",
    addrSambaStart: "L'adresse doit commencer par '\\\\'",
    addrSambaFormat: "Adresse invalide, doit contenir IP et chemin séparés par '\\'",
    addrPathEmpty: "Le chemin ne peut pas être vide",
    addrPathChars: "Le chemin contient des caractères invalides, seuls les lettres, chiffres, tirets bas et tirets sont autorisés",
    // Disk size info "{available} / {total}"
    diskSizeInfo: "{0} (disponible) / {1} (total)"
  },
  // GB28181 Settings
  gb28181: {
    title: "Paramètres GB28181",
    basicSettings: "Paramètres de base",
    heartbeatSettings: "Paramètres de battement de cœur",
    sipServerSettings: "Paramètres du serveur SIP",
    authSettings: "Paramètres d'authentification",
    enable: "Activer :",
    disabled: "Désactivé",
    enabled: "Activé",
    localSipPort: "Port SIP local :",
    videoChannelId: "ID du canal vidéo :",
    streamSelect: "Sélection du flux :",
    mainStream: "Flux principal",
    subStream1: "Flux secondaire 1",
    subStream2: "Flux secondaire 2",
    subStream3: "Flux secondaire 3",
    regExpiry: "Expiration d'enregistrement :",
    heartbeatCycle: "Cycle de battement de cœur :",
    maxHeartbeatTimeout: "Timeout max de battement de cœur :",
    sipServerId: "ID du serveur SIP :",
    sipServerDomain: "Domaine du serveur SIP :",
    sipServerAddr: "Adresse du serveur SIP :",
    sipServerPort: "Port du serveur SIP :",
    sipUserId: "ID utilisateur SIP :",
    sipPassword: "Mot de passe SIP :",
    emptyError: "Les paramètres ne peuvent pas être vides !",
    localPortError: "Le port SIP local doit être un entier entre 1-65500 !",
    serverPortError: "Le port du serveur SIP doit être un entier entre 1-65500 !",
    regExpiryError: "L'expiration d'enregistrement doit être un entier entre 100-100000 !",
    heartbeatError: "Le cycle de battement de cœur doit être un entier entre 5-3600 !",
    maxTimeoutError: "Le timeout max de battement de cœur doit être un entier entre 3-255 !",
    success: "Paramètres enregistrés avec succès !",
    failed: "Échec des paramètres !"
  },
  // Video Source Settings
  videoSource: {
    title: "Paramètres de source vidéo",
    videoInput: "Paramètres d'entrée vidéo",
    brightAdjust: "Ajustement de luminosité d'entrée",
    videoOutput: "Paramètres de sortie vidéo",
    inputFormat: "Format d'entrée vidéo :",
    yuv422: "YUV422",
    yuv420: "YUV420 (Rotation supportée)",
    rotation: "Angle de rotation :",
    flipMirror: "Retournement/Miroir :",
    flipDisable: "Désactivé",
    mirror: "Miroir",
    flip: "Retournement",
    flipAndMirror: "Miroir et Retournement",
    cropEnable: "Recadrage vidéo :",
    cropLeft: "Point de départ du recadrage (Gauche) :",
    cropTop: "Point de départ du recadrage (Haut) :",
    cropWidth: "Largeur de recadrage :",
    cropHeight: "Hauteur de recadrage :",
    colorMode: "Mode couleur d'entrée :",
    unknown: "Inconnu",
    brightEnable: "Ajustement de luminosité :",
    gain: "Gain :",
    gainHint: "[10-1000], défaut 100",
    offset: "Décalage :",
    offsetHint: "[0-100], défaut 0",
    note: "Note :",
    brightNote1: "1. Luminosité = (Luminosité originale * Gain / 100) + Décalage",
    brightNote2: "2. L'ajustement de luminosité ne fonctionne qu'en mode couleur d'entrée RVB",
    outputRes: "Résolution de sortie vidéo :",
    auto: "Auto",
    cscEnable: "Ajustement CSC :",
    luminance: "Luminance :",
    contrast: "Contraste :",
    hue: "Teinte :",
    saturation: "Saturation :",
    cscHint: "[0-100], défaut 50",
    rotateHint: "La rotation n'est supportée que lorsque le format d'entrée vidéo est YUV420.",
    emptyError: "Les paramètres ne peuvent pas être vides !",
    gainError: "Le gain doit être un entier entre 10-1000 !",
    offsetError: "Le décalage doit être un entier entre 0-100 !",
    leftError: "La valeur gauche doit être un entier entre 0-{0} !",
    topError: "La valeur haut doit être un entier entre 0-{0} !",
    widthError: "La valeur de largeur doit être un entier entre 400-{0} !",
    heightError: "La valeur de hauteur doit être un entier entre 400-{0} !",
    luminanceError: "La luminance doit être un entier entre 0-100 !",
    contrastError: "Le contraste doit être un entier entre 0-100 !",
    hueError: "La teinte doit être un entier entre 0-100 !",
    saturationError: "La saturation doit être un entier entre 0-100 !",
    success: "Paramètres enregistrés avec succès !",
    failed: "Échec des paramètres !"
  },
  // Network Settings
  network: {
    title: "Paramètres réseau",
    ipv4Title: "Paramètres IPv4",
    ipv6Status: "État IPv6",
    ipv6Title: "Paramètres IPv6",
    ipv6TypeGlobal: "IP globale",
    ipv6TypeLinkLocal: "IP lien-local",
    ipv6TypeUniqueLocal: "IP locale",
    ipv6TypeMulticast: "IP multicast",
    ipv6TypeGeneric: "IP",
    ipv6StatusGateway: "Passerelle",
    dnsTitle: "Paramètres DNS",
    ntpTitle: "Paramètres NTP",
    portTitle: "Paramètres de port",
    httpsTitle: "Paramètres HTTPS",
    hostnameTitle: "Paramètres HOSTNAME",
    dhcp: "DHCP :",
    dhcpHint: "Après avoir activé DHCP, l'appareil peut être trouvé par les outils de recherche compatibles ONVIF.",
    ipAddr: "Adresse IP :",
    netmask: "Masque de sous-réseau :",
    gateway: "Passerelle filaire :",
    macAddr: "Adresse MAC :",
    defaultGateway: "Passerelle par défaut :",
    lanFirst: "Filaire d'abord",
    wifiFirst: "WiFi d'abord",
    g4First: "4G/5G d'abord",
    ipv6Mode: "Mode :",
    ipv6Disable: "Désactivé",
    ipv6Auto: "Configuration auto",
    ipv6Manual: "Configuration manuelle",
    ipv6Addr: "Adresse IPv6 :",
    ipv6Prefix: "Longueur du préfixe IPv6 :",
    ipv6Gateway: "Passerelle par défaut IPv6 :",
    dns1: "DNS1 :",
    dns2: "DNS2 :",
    ntpSync: "Synchronisation NTP :",
    ntpServer: "Serveur :",
    timezone: "Fuseau horaire :",
    httpPort1: "Port HTTP 1 :",
    httpPort2: "Port HTTP 2 :",
    rtspPort1: "Port RTSP 1 :",
    rtspPort2: "Port RTSP 2 :",
    onvifPort: "Port ONVIF:",
    httpsService: "Service HTTPS :",
    httpsPort1: "Port HTTPS 1 :",
    httpsPort2: "Port HTTPS 2 :",
    httpsPrivatePass: "Mot de passe clé privée HTTPS :",
    privatePassHint: "(Laisser vide si pas de mot de passe)",
    uploadCert: "Télécharger le certificat :",
    uploadCertHint: "(Le nom de fichier doit être private.key ou public.crt. Ne pas télécharger simultanément ou éteindre pendant le téléchargement)",
    uploadBtn: "Télécharger le certificat",
    deleteCert: "Supprimer le certificat",
    hostname: "HOSTNAME :",
    mdnsService: "Service mDNS :",
    mdnsAddr: "Adresse d'accès mDNS :",
    portRange: "[1-65500]",
    prefixRange: "[0-128]",
    emptyError: "Les paramètres ne peuvent pas être vides !",
    ipError: "Format d'adresse IP invalide !",
    netmaskError: "Format de masque de sous-réseau invalide !",
    gatewayError: "Format de passerelle invalide !",
    dns1Error: "Format de DNS primaire invalide !",
    dns2Error: "Format de DNS secondaire invalide !",
    macError: "Format d'adresse MAC invalide !",
    httpPort1Error: "Le port HTTP 1 doit être un entier entre 1-65500 !",
    httpPort2Error: "Le port HTTP 2 doit être un entier entre 1-65500 !",
    rtspPort1Error: "Le port RTSP 1 doit être un entier entre 1-65500 !",
    rtspPort2Error: "Le port RTSP 2 doit être un entier entre 1-65500 !",
    httpsPort1Error: "Le port HTTPS 1 doit être un entier entre 1-65500 !",
    httpsPort2Error: "Le port HTTPS 2 doit être un entier entre 1-65500 !",
    onvifPortError: "Le port ONVIF doit être un entier entre 1-65500 !",
    httpBothDisableError: "Le port HTTP 1 et le port 2 ne peuvent pas être tous les deux désactivés !",
    httpsBothDisableError: "Quand HTTPS est activé, le port 1 et le port 2 ne peuvent pas être tous les deux désactivés !",
    ntpEmptyError: "Le serveur NTP ne peut pas être vide !",
    ntpFormatError: "Adresse du serveur NTP invalide !",
    hostnameEmptyError: "HOSTNAME ne peut pas être vide !",
    hostnameFormatError: "HOSTNAME invalide !\n\n1. HOSTNAME ne doit pas dépasser 63 caractères !\n2. Seuls les lettres (a-z), chiffres (0-9), tirets (-) et tirets bas (_) sont autorisés !\n3. '-' et '_' ne peuvent pas apparaître consécutivement, seuls, ou au début/fin !",
    deleteCertConfirm: "Êtes-vous sûr de vouloir supprimer le certificat HTTPS téléchargé ?",
    selectFile: "Veuillez sélectionner un fichier à télécharger !",
    uploadSuccess: "Téléchargement réussi !",
    uploadFailed: "Échec du téléchargement !",
    fileSizeError: "La taille du fichier image dépasse la limite !",
    fileResError: "La résolution de l'image dépasse la limite !",
    spaceError: "Fichier de mise à jour trop volumineux, espace de stockage insuffisant !",
    deleteSuccess: "Supprimé avec succès !",
    deleteFailed: "Échec de la suppression !",
    successReboot: "Paramètres enregistrés, veuillez redémarrer l'appareil !",
    failed: "Échec des paramètres !"
  },

  // Output Settings Page (Stream Settings)
  output: {
    // Tab names
    tabs: {
      encode: "Encodage",
      ts: "TS/Multicast",
      rtsp: "RTSP",
      rtmp: "RTMP",
      srt: "SRT",
      webrtc: "WebRTC",
      trtc: "TRTC",
      hls: "HLS",
      other: "MP4/FLV/Autre"
    },

    // Encoding settings
    encode: {
      codecType: "Type de codec :",
      frameRate: "Fréquence d'images :",
      sameAsInput: "Identique à l'entrée",
      auto: "Auto",
      customFrameRate: "Fréquence personnalisée",
      customFrameRateLabel: "Fréquence personnalisée :",
      gopInterval: "Intervalle GOP (images) :",
      bitrate: "Débit (kbit) :",
      qualityRange: "Plage de qualité :",
      qualityStrict: "Strict (Haut)",
      qualityTight: "Serré (Proche-Haut~Haut)",
      qualityNormal: "Normal (Moyen~Haut)",
      qualityLoose: "Souple (Proche-Bas~Haut)",
      qualityWide: "Large (Bas~Haut)",
      mjpegQuality: "Qualité MJPEG :",
      outputResolution: "Résolution de sortie :",
      h264Profile: "Profil H.264 :",
      bitrateControl: "Contrôle de débit :",
      // Tips
      tipCodec: "H.265 offre une meilleure qualité vidéo que H.264. Utilisez H.265 si votre décodeur le supporte.",
      tipVbr: "En mode VBR, le débit est régulé par \"Plage de qualité\"; La plage de qualité limite les valeurs QP;<br>Sélectionner \"Proche-Haut~Haut\" ou \"Haut\" donne un débit réel très élevé, rendant le débit défini sans signification;<br>Seul quand la plage de qualité est \"Proche-Bas~Haut\" le débit a une valeur de référence;",
      tipCbr: "\"CBR fort\" est utilisé pour les systèmes CATV pour assurer un débit TS stable. Avec \"CBR fort\" à 1080P, le débit ne doit pas être inférieur à 5000kbit/s, 8000kbit/s recommandé.",
      tipGop: "En supposant que la fréquence d'images vidéo d'entrée est n, les valeurs courantes sont 60, 50, 30, 25;<br>L'intervalle GOP est typiquement réglé à n * 2, les valeurs courantes sont 120, 100, 60, 50;<br>Quand la fréquence d'images est sur Auto, si n > 30, la fréquence d'encodage est n / 2, sinon elle égale n"
    },

    // TS/Multicast settings
    ts: {
      tsUri: "URL du flux TS :",
      multicastIp: "IP Multicast :",
      multicastPort: "Port Multicast :",
      sapName: "Nom SAP :",
      tsVideoPid: "PID vidéo TS :",
      tsAudioPid: "PID audio TS :",
      tsTransportStreamId: "ID flux transport TS :",
      tsOriginalNetworkId: "ID réseau original TS :",
      tsPmtStartPid: "PID départ PMT TS :",
      tsStartPid: "PID départ TS :",
      tsTablesVersion: "Version tables TS :",
      tsServiceId: "ID service TS :",
      tsServiceName: "Nom service TS :",
      tsProviderName: "Nom fournisseur TS :",
      tsPcrPeriod: "Période PCR TS (ms) :",
      conformSystemB: "Conforme Système B (DVB) :",
      tsNullPacket: "Paquets nuls TS :",
      noInsert: "Pas d'insertion",
      insert12: "Insérer (1.2x)",
      insert13: "Insérer (1.3x)",
      insert15: "Insérer (1.5x)",
      insert20: "Insérer (2x)",
      insert25: "Insérer (2.5x)",
      tsTdt: "TS TDT :",
      // Tips
      tipMulticast: "L'adresse multicast peut aussi accepter des adresses broadcast ou unicast, le système détecte automatiquement.",
      tipVlc: "Si VLC ne peut pas lire le multicast, vérifiez si votre ordinateur a plusieurs adaptateurs réseau, essayez d'en changer.",
      tipSap: "Le nom SAP peut être vu sur les appareils supportés, comme la playlist VLC -> Réseau local.",
      tipAdvanced: "Les paramètres avancés TS n'ont généralement pas besoin d'être ajustés.",
      tipIptv: "Lors de la connexion aux systèmes IPTV, les paquets nuls TS doivent être ajustés à 1.3x, l'appareil insère automatiquement des paquets nuls pour assurer un débit stable;<br>Ce paramètre ne s'applique qu'au mode \"CBR fort\"."
    },

    // RTSP settings
    rtsp: {
      rtspUri: "URL flux RTSP :",
      enableMulticast: "Activer (Multicast)",
      enableTcpOnly: "Activer (TCP uniquement)",
      multicastIp: "IP Multicast RTSP :",
      multicastPort: "Port Multicast RTSP :",
      // Tips
      tipEnable: "Si Activer est sélectionné, le transport réel (UDP ou TCP) est déterminé par le client. Par exemple, dans VLC vous pouvez cocher \"RTP over RTSP(TCP)\" pour utiliser TCP.",
      tipTcpOnly: "Sélectionner Activer (TCP uniquement) force l'appareil à utiliser TCP.",
      tipUdp: "UDP peut occasionnellement perdre des paquets à cause de problèmes réseau. Si tous les clients le supportent, TCP est recommandé.",
      tipMulticast: "Sélectionner Activer (Multicast) utilisera 4 ports consécutifs à partir du \"Port Multicast RTSP\"."
    },

    // RTMP settings
    rtmp: {
      rtmpUri: "URL flux RTMP :",
      publishUri0: "URL publication RTMP(S)/RTSP 0 :",
      publishUri1: "URL publication RTMP(S)/RTSP 1 :",
      publishUri2: "URL publication RTMP(S)/RTSP 2 :",
      mode: "Mode de diffusion RTMP :",
      modeStandard: "Standard (Enhanced RTMP)",
      modeLegacy: "Legacy (CodecID 12)",
      // Tips
      tipPublish: "Les URL de publication 0-2 sont pour pousser les flux vers d'autres serveurs RTMP/RTSP LAN ou publics, supportant H.265/H.264.",
      tipBuiltin: "Cet appareil intègre un serveur RTMP compatible avec la lecture en H.264/H.265;<br>Si l'URL du flux RTMP est définie sur \"/live/0\", PotPlayer peut lire via http://IP-appareil/live/0.",
      tipMode: "Le mode de diffusion RTMP s'applique uniquement au H.265 et affecte aussi le flux FLV ;"
    },

    // SRT settings
    srt: {
      listenerUri: "URL SRT Listener :",
      callerUri: "URL SRT Caller :",
      // Tips
      tipListener: "Le mode SRT Listener écoute sur un port local pour que les lecteurs puissent tirer le flux.<br>Par exemple, définir srt://0.0.0.0:9000;<br>VLC peut alors lire \"srt://IP-appareil:9000\".<br>Ajout streamid exemple:<br>srt://0.0.0.0:9000?streamid=channel100<br>Ajout mot de passe exemple (minimum 10 caractères):<br>srt://0.0.0.0:9000?passphrase=0123456789<br>Ajout streamid et mot de passe:<br>srt://0.0.0.0:9000?streamid=channel100&passphrase=0123456789",
      tipCaller: "Le mode SRT Caller pousse le flux vers un autre serveur, ex.:<br>srt://live.example.com:9000?streamid=channel100&latency=120&maxbw=8000000",
      tipParams: "Paramètres SRT supportés (voir protocole SRT pour détails):<br>streamid - identifiant de flux pour multiplexage<br>passphrase - mot de passe de chiffrement, SRT requiert 10-79 caractères<br>pbkeylen - longueur de clé: 16 (AES-128), 24 (AES-192), 32 (AES-256)<br>latency - latence en ms (20-8000ms)<br>maxbw - bande passante max en octets/sec<br>rcvbuf - taille buffer de réception<br>sndbuf - taille buffer d'envoi<br>ipttl - valeur IP TTL<br>conntimeo - timeout de connexion en ms"
    },

    // WebRTC settings
    webrtc: {
      preview: "Aperçu WebRTC :",
      whipServer: "Serveur WHIP :",
      whipToken: "Token Bearer WHIP :",
      p2pServer: "Serveur P2P :",
      p2pUuid: "UUID P2P :",
      p2pToken: "Token auth P2P :",
      p2pAuthToken: "Token auth P2P :",
      regenerate: "Régénérer",
      // Tips
      tipPreview: "L'aperçu WebRTC dans les navigateurs courants supporte l'encodage vidéo H.264 et audio Opus/G.711.<br>Régler l'audio sur Opus donne de meilleurs résultats. Si non réglé sur Opus, défaut G.711 8K.",
      tipWhip: "Le streaming WHIP se connecte aux serveurs WHIP standard. Copiez l'adresse depuis votre serveur.<br>Le token Bearer peut être vide.",
      tipP2p: "Après avoir activé le serveur P2P, l'URL de visionnage est affichée sur la page d'état.<br>Le token auth P2P peut être vide.",
      tipP2pNote: "P2P peut ne pas se connecter dans des environnements intranet complexes."
    },

    // TRTC settings
    trtc: {
      roomId: "ID de salle TRTC :",
      userId: "Nom d'utilisateur TRTC :",
      roomKey: "Clé de salle TRTC :",
      userSig: "UserSig TRTC :",
      sdkAppId: "SDKAppID TRTC :",
      roomIdType: "Type d'ID de salle TRTC :",
      roomIdNumber: "Nombre",
      roomIdString: "Chaîne",
      // Short enum labels for template use
      number: "Nombre",
      string: "Chaîne",
      // Tips
      tipTrtc: "Pousser les flux vers le serveur Tencent TRTC. Copiez l'adresse depuis le serveur.<br>Tencent TRTC ne supporte actuellement que H.264."
    },

    // HLS settings
    hls: {
      hlsTsUri: "URL flux HLS TS :",
      hlsMp4Uri: "URL flux HLS MP4 :",
      hlsPushUri: "URL PUSH HLS :",
      hlsPushUrl: "URL PUSH HLS :",
      // Tips
      tipHls: "Quand HLS TS/MP4 est activé, l'appareil met en buffer les données en mémoire selon le temps et le nombre de segments dans les paramètres avancés.<br>Régler le temps et le nombre de segments à 3 réduit l'utilisation mémoire.",
      tipPush: "L'URL de publication HLS est pour pousser vers des serveurs comme YouTube."
    },

    // MP4/FLV/Other settings
    other: {
      mp4Uri: "URL flux MP4 :",
      flvUri: "URL flux FLV :",
      icecastUri: "URL PUSH ICECAST :",
      icecastPushUrl: "URL PUSH ICECAST :",
      shoutcastUri: "URL PUSH Shoutcast :",
      shoutcastPushUrl: "URL PUSH Shoutcast :",
      // Tips
      tipMp4: "Quand le flux MP4 est activé, il peut être lu directement dans le navigateur.<br>Le flux FLV supporte H.265/H.264 sur cet appareil, mais VLC et autres lecteurs ne supportent actuellement que H.264.<br>ICECAST/Shoutcast ne supporte que MP3, pour pousser vers des serveurs audio.",
      tipShoutcast: "Shoutcast supporte v1 et v2;<br>Exemples:<br>http://motdepasse@serveur_shoutcast:8000<br>http://motdepasse@serveur_shoutcast:8000?sid=100<br>http://motdepasse@serveur_shoutcast:8000?icy-name=Stream&icy-genre=Pop<br>Format:<br>http://motdepasse@IP-serveur:port-écoute[?params...]; le nom d'utilisateur peut être omis (défaut \"source\").<br>Utilisez le \"port d'écoute\" du serveur, l'appareil se connecte automatiquement au port source (port d'écoute + 1).<br>Paramètres supportés:<br>sid: ID de flux Shoutcast v2 (défaut 1)<br>icy-name: nom du flux (optionnel)<br>icy-genre: genre (optionnel)<br>icy-url: URL du site web (optionnel)<br>icy-pub: public 0/1 (optionnel)"
    },

    // Common
    common: {
      save: "Enregistrer",
      disabled: "Désactivé",
      enabled: "Activé"
    },

    // Error and success messages
    messages: {
      success: "Paramètres enregistrés !",
      failed: "Échec des paramètres !",
      emptyError: "Les paramètres ne peuvent pas être vides !",
      trtcH264Only: "Quand TRTC est activé, seul l'encodage H.264 est supporté. Changé automatiquement.",
      mp3Required: "Veuillez régler l'encodage audio sur MP3 !",
      // Encoding validation
      frameRateError: "La fréquence d'images doit être un entier entre 5-60 !",
      gopError: "L'intervalle GOP doit être un entier entre 5-300 !",
      mjpegQualityError: "La qualité MJPEG doit être un entier entre 10-99 !",
      hlsBitrateWarning: "Débit hors plage 32~8000, flux HLS TS/MP4/PUSH désactivés.",
      trtcCodecWarning: "Le codec n'est pas H.264, TRTC désactivé.",
      hlsBitrateError: "Débit hors plage 32~8000, impossible d'activer les flux HLS TS/MP4/PUSH",
      // SRT validation
      srtListenerPortError: "Le port SRT Listener doit être un entier entre 1-65535 !",
      srtListenerFormatError: "Format d'URL SRT Listener invalide !",
      srtCallerFormatError: "Format d'URL SRT Caller invalide !",
      srtPasswordLengthError: "La longueur du mot de passe SRT doit être entre 10-32 !",
      srtLatencyError: "La latence SRT doit être un entier entre 1-10000 !",
      srtBandwidthError: "La bande passante SRT doit être un entier entre 0-102400 !",
      // RTMP validation
      rtmpFormatError: "L'URL de publication RTMP(S)/RTSP doit commencer par rtmp://, rtmps:// ou rtsp://",
      // HLS validation
      hlsFormatError: "Format d'URL de publication HLS invalide !",
      // RTSP validation
      rtspMulticastIpError: "Format d'IP multicast RTSP invalide !",
      rtspMulticastPortError: "Le port multicast RTSP doit être un entier entre 1-65535 !",
      // TS validation
      multicastIpError: "Format d'IP multicast invalide !",
      multicastPortError: "Le port multicast doit être un entier entre 1-65535 !",
      tsTransportIdError: "L'ID flux transport TS doit être un entier entre 1-65535 !",
      tsNetworkIdError: "L'ID réseau original TS doit être un entier entre 1-65535 !",
      tsPmtPidError: "Le PID départ PMT TS doit être un entier entre 16-7936 !",
      tsStartPidError: "Le PID départ TS doit être un entier entre 32-3840 !",
      tsPidConflict: "Le PID départ TS et le PID départ PMT TS doivent être différents !",
      tsVersionError: "La version tables TS doit être un entier entre 0-31 !",
      tsServiceIdError: "L'ID service TS doit être un entier entre 1-65535 !",
      tsVideoPidError: "Le PID vidéo TS doit être un entier entre 16-8190 !",
      tsAudioPidError: "Le PID audio TS doit être un entier entre 16-8190 !",
      tsVideoPidConflict: "Le PID vidéo TS et le PID audio TS doivent être différents !",
      tsAudioPmtConflict: "Le PID audio TS et le PID départ PMT TS doivent être différents !",
      tsVideoPmtConflict: "Le PID vidéo TS et le PID départ PMT TS doivent être différents !",
      // Other validation
      icecastFormatError: "Format d'URL de publication Icecast invalide !",
      shoutcastFormatError: "Format d'URL de publication Shoutcast invalide !"
    }
  }
};
