fix(webui): stabilize streaming output and settings i18n

This commit is contained in:
Xubin Ren
2026-06-01 00:00:37 +08:00
parent 31722120b7
commit 34386fe676
13 changed files with 1164 additions and 1048 deletions
+144 -144
View File
@@ -57,45 +57,45 @@
"apps": "Apps"
},
"settings": {
"backToChat": "Retour à la discussion",
"backToChat": "Retour au chat",
"sidebar": {
"title": "Paramètres",
"ariaLabel": "Sections des paramètres"
"title": "Réglages",
"ariaLabel": "Sections des réglages"
},
"nav": {
"general": "Général",
"byok": "BYOK",
"overview": "Overview",
"appearance": "Appearance",
"models": "Models",
"providers": "Providers",
"image": "Image",
"browser": "Web",
"overview": "Aperçu",
"appearance": "Apparence",
"models": "Modèles",
"providers": "Fournisseurs",
"image": "Images",
"browser": "Internet",
"runtime": "Système",
"advanced": "Security",
"advanced": "Sécurité",
"cliApps": "Apps CLI",
"mcp": "MCP",
"apps": "Apps"
"apps": "Applications"
},
"sections": {
"interface": "Interface",
"ai": "IA",
"interface": "Interface utilisateur",
"ai": "AI",
"system": "Système",
"status": "Status",
"localPreferences": "Local preferences",
"presets": "Presets",
"imageGeneration": "Génération d'images",
"status": "État",
"localPreferences": "Préférences locales",
"presets": "Préréglages",
"imageGeneration": "Génération dimages",
"imageDefaults": "Valeurs par défaut",
"webSearch": "Web search",
"webBehavior": "Behavior",
"identity": "Identity",
"webuiSafety": "Web safety",
"webSearch": "Recherche web",
"webBehavior": "Comportement",
"identity": "Identité",
"webuiSafety": "Sécurité WebUI",
"capabilities": "Capacités",
"cliApps": "Apps CLI",
"cliApps": "Applications CLI",
"mcp": "Services MCP",
"apps": "Apps",
"nativeHost": "App",
"hostSafety": "App safety"
"apps": "Applications",
"nativeHost": "Hôte natif",
"hostSafety": "Sécurité de lapp"
},
"rows": {
"theme": "Thème",
@@ -103,119 +103,119 @@
"provider": "Fournisseur",
"model": "Modèle",
"restart": "Redémarrer nanobot",
"configPath": "Chemin de configuration",
"activePreset": "Active preset",
"gateway": "Gateway",
"restartState": "Restart state",
"configPath": "Chemin de config",
"activePreset": "Préréglage actif",
"gateway": "Passerelle",
"restartState": "État du redémarrage",
"pendingChanges": "Modifications en attente",
"selectedPreset": "Selected preset",
"presetModel": "Preset model",
"density": "Density",
"activityMode": "Activity detail",
"codeWrap": "Code wrapping",
"maxResults": "Max results",
"timeout": "Timeout",
"jinaReader": "Jina reader",
"imageGeneration": "Génération d'images",
"imageProvider": "Fournisseur d'images",
"selectedPreset": "Préréglage sélectionné",
"presetModel": "Modèle du préréglage",
"density": "Densité",
"activityMode": "Détail dactivité",
"codeWrap": "Retour à la ligne du code",
"maxResults": "Résultats max.",
"timeout": "Délai dattente",
"jinaReader": "Lecteur Jina",
"imageGeneration": "Génération dimages",
"imageProvider": "Fournisseur dimages",
"imageProviderStatus": "État du fournisseur",
"imageProviderBase": "Base du fournisseur",
"imageModel": "Modèle d'image",
"defaultAspectRatio": "Format par défaut",
"imageModel": "Modèle dimage",
"defaultAspectRatio": "Ratio par défaut",
"defaultImageSize": "Taille par défaut",
"maxImagesPerTurn": "Nombre max. d'images par tour",
"imageSaveDir": "Répertoire de sauvegarde",
"botName": "Bot name",
"botIcon": "Bot icon",
"timezone": "Timezone",
"maxImagesPerTurn": "Images max. par tour",
"imageSaveDir": "Dossier denregistrement",
"botName": "Nom du bot",
"botIcon": "Icône du bot",
"timezone": "Fuseau horaire",
"workspacePath": "Espace de travail par défaut",
"localServiceAccess": "Local services",
"webuiDefaultAccess": "Default access",
"localServiceAccess": "Services locaux",
"webuiDefaultAccess": "Accès par défaut",
"currentModel": "Configuration actuelle",
"brandLogos": "Logos de marque",
"cliAppsCatalog": "Catalogue d'apps CLI",
"cliAppsFilter": "Filtre des apps CLI",
"cliAppsCatalog": "Catalogue",
"cliAppsFilter": "Filtre",
"engine": "Moteur",
"logs": "Journaux",
"diagnostics": "Diagnostics",
"contextWindow": "Context window"
"diagnostics": "Diagnostic",
"contextWindow": "Fenêtre de contexte"
},
"help": {
"theme": "Basculer entre les apparences claire et sombre.",
"language": "Choisissez la langue utilisée par le WebUI.",
"provider": "Sélectionnez le fournisseur des nouvelles requêtes de modèle.",
"model": "Définissez le nom du modèle par défaut utilisé par nanobot.",
"theme": "Basculer entre lapparence claire et sombre.",
"language": "Choisissez la langue utilisée par WebUI.",
"provider": "Sélectionnez le fournisseur à utiliser pour les nouvelles requêtes de modèle.",
"model": "Définissez le nom du modèle utilisé par défaut par nanobot.",
"configPath": "Le fichier de configuration actuellement utilisé par la passerelle.",
"selectedPreset": "Named presets are read-only here; edit them in config.json.",
"presetModel": "Switch to Default to edit model and provider from the WebUI.",
"density": "Stored only in this browser.",
"activityMode": "Choose how much agent activity chrome to show by default.",
"codeWrap": "Keep long code lines readable on smaller screens.",
"maxResults": "Results returned by each web_search call.",
"timeout": "Seconds before a search provider request times out.",
"jinaReader": "Use Jina Reader for web_fetch when available.",
"imageGeneration": "Expose generate_image dans les chats lorsquun fournisseur dimages configuré est disponible.",
"imageProvider": "Choisissez le fournisseur du registre utilisé par generate_image.",
"imageProviderStatus": "La génération dimages réutilise les identifiants de Fournisseurs.",
"selectedPreset": "Les préréglages nommés sont en lecture seule ici ; modifiez-les dans config.json.",
"presetModel": "Passez à Default pour modifier le modèle et le fournisseur depuis WebUI.",
"density": "Enregistré seulement dans ce navigateur.",
"activityMode": "Choisissez le niveau de détail dactivité agent affiché par défaut.",
"codeWrap": "Garde les longues lignes de code lisibles sur les petits écrans.",
"maxResults": "Résultats renvoyés par chaque appel web_search.",
"timeout": "Nombre de secondes avant lexpiration dune requête de recherche.",
"jinaReader": "Utilise Jina Reader pour web_fetch lorsque disponible.",
"imageGeneration": "Expose generate_image dans les chats lorsquun fournisseur dimage configuré est disponible.",
"imageProvider": "Choisissez le fournisseur inscrit utilisé par generate_image.",
"imageProviderStatus": "La génération dimages réutilise les identifiants des fournisseurs.",
"imageModel": "Nom du modèle envoyé au fournisseur dimages sélectionné.",
"defaultAspectRatio": "Utilisé lorsque le prompt ne choisit pas de format.",
"defaultImageSize": "Indication de taille envoyée aux fournisseurs qui la prennent en charge.",
"defaultAspectRatio": "Utilisé lorsque le prompt ne choisit pas de ratio.",
"defaultImageSize": "Indication de taille envoyée aux fournisseurs compatibles.",
"maxImagesPerTurn": "Limite supérieure pour une requête generate_image.",
"botName": "Affiché partout où nanobot utilise un nom visible.",
"botName": "Affiché où nanobot utilise un nom visible.",
"botIcon": "Emoji ou texte court affiché avec le nom du bot.",
"timezone": "Utilisé pour les planifications et les réponses sensibles à lheure.",
"localServiceAccess": "Allow Full Access shell commands to reach localhost services.",
"webuiDefaultAccess": "Used by web chats without a project-specific permission.",
"securityManagedControls": "Web fetches always protect local, private, and metadata services. Core channel safety stays in config.json.",
"currentModel": "Choisissez la configuration de modèle que nanobot utilisera pour les prochaines réponses.",
"timezone": "Utilisé pour les horaires et les réponses tenant compte du temps.",
"localServiceAccess": "Autorise les commandes shell Full Access à atteindre les services localhost.",
"webuiDefaultAccess": "Utilisé par les chats web sans permission propre au projet.",
"securityManagedControls": "Les récupérations web protègent toujours les services locaux, privés et de métadonnées. La sécurité des canaux principaux reste gérée dans config.json.",
"currentModel": "Utilisée pour les nouvelles réponses.",
"selectedModelProvider": "Défini par le modèle sélectionné.",
"selectedModelValue": "Défini par le modèle sélectionné.",
"brandLogos": "Les logos sont chargés depuis les domaines des marques avec une icône locale en secours.",
"cliAppsCatalog": "Parcourez les CLIs d'apps que nanobot peut exécuter localement.",
"brandLogos": "Affiche les logos de fournisseurs tiers et CLI dans les Réglages.",
"cliAppsCatalog": "Installe uniquement les adaptateurs CLI dapps que nanobot peut exécuter localement ; les apps natives restent inchangées.",
"cliAppsFilter": "Recherchez par app, catégorie ou capacité.",
"logs": "Ouvrir le dossier des journaux du moteur natif.",
"diagnostics": "Exporter un petit rapport runtime pour le support.",
"localServiceAccessNative": "Allow Full Access shell commands to reach services on this Mac.",
"webuiDefaultAccessNative": "Used by native chats without a project-specific permission.",
"contextWindow": "Choose the default context budget for this model configuration."
"logs": "Ouvre le dossier des journaux du moteur natif.",
"diagnostics": "Exporte un petit rapport dexécution pour le support.",
"localServiceAccessNative": "Autorise les commandes shell Full Access à atteindre les services sur ce Mac.",
"webuiDefaultAccessNative": "Utilisé par les chats natifs sans permission propre au projet.",
"contextWindow": "Choisissez le budget de contexte par défaut pour cette configuration de modèle."
},
"values": {
"light": "Clair",
"dark": "Sombre",
"notAvailable": "Indisponible",
"enabled": "Enabled",
"disabled": "Disabled",
"enabled": "Activé",
"disabled": "Désactivé",
"restartPending": "Redémarrage en attente",
"ready": "Prêt",
"comfortable": "Comfortable",
"compact": "Compact",
"auto": "Auto",
"expanded": "Expanded",
"on": "On",
"off": "Off",
"defaultPermission": "Default Permission",
"fullAccess": "Full Access",
"configured": "Configured",
"notConfigured": "Not configured",
"comfortable": "Confortable",
"compact": "Compacte",
"auto": "Automatique",
"expanded": "Développé",
"on": "Activé",
"off": "Désactivé",
"defaultPermission": "Autorisation par défaut",
"fullAccess": "Accès complet",
"configured": "Configuré",
"notConfigured": "Non configuré",
"pending": "En attente",
"restartingEngine": "Redémarrage"
},
"status": {
"loading": "Chargement des paramètres...",
"loadError": "Impossible de charger les paramètres",
"loading": "Chargement des réglages...",
"loadError": "Impossible de charger les réglages",
"unsaved": "Modifications non enregistrées.",
"upToDate": "À jour.",
"savedRestart": "Enregistré. Redémarrez nanobot pour appliquer.",
"restartAfterSaving": "Enregistrez les modifications, puis redémarrez lorsque vous êtes prêt.",
"savedRestartApply": "Enregistré. Redémarrez lorsque vous êtes prêt.",
"imageProviderRestart": "Modifications du fournisseur dimages enregistrées. Redémarrez lorsque vous êtes prêt.",
"hostRestartAfterSaving": "Enregistrez les changements et nanobot redémarrera son moteur.",
"hostRestartPending": "Enregistré. Redémarrage du moteur quand il sera prêt.",
"hostApiUnavailable": "Host actions are only available inside the native app.",
"logsOpened": "Opened logs folder.",
"logsOpenFailed": "Could not open logs folder.",
"diagnosticsExported": "Diagnostics exported to {{path}}.",
"diagnosticsExportFailed": "Could not export diagnostics."
"restartAfterSaving": "Enregistrez les changements, puis redémarrez quand vous êtes prêt.",
"savedRestartApply": "Enregistré. Redémarrez quand vous êtes prêt.",
"imageProviderRestart": "Changements du fournisseur dimage enregistrés. Redémarrez quand vous êtes prêt.",
"hostRestartAfterSaving": "En enregistrant, nanobot redémarrera son moteur.",
"hostRestartPending": "Enregistré. Le moteur redémarrera lorsquil sera prêt.",
"hostApiUnavailable": "Les actions de lhôte ne sont disponibles que dans lapp native.",
"logsOpened": "Dossier des journaux ouvert.",
"logsOpenFailed": "Impossible douvrir le dossier des journaux.",
"diagnosticsExported": "Diagnostic exporté vers {{path}}.",
"diagnosticsExportFailed": "Impossible dexporter le diagnostic."
},
"actions": {
"save": "Enregistrer",
@@ -224,8 +224,8 @@
"cancel": "Annuler",
"open": "Ouvrir",
"export": "Exporter",
"opening": "Opening...",
"exporting": "Exporting..."
"opening": "Ouverture...",
"exporting": "Exportation..."
},
"byok": {
"description": "Utilisez vos propres clés de fournisseur. Nanobot lit ces valeurs depuis la configuration actuelle, et seuls les fournisseurs configurés peuvent être sélectionnés dans Général.",
@@ -250,7 +250,7 @@
"tabs": {
"ariaLabel": "Type d'identifiants BYOK",
"llm": "LLM",
"webSearch": "Web Search"
"webSearch": "Recherche web"
},
"webSearch": {
"provider": "Fournisseur de recherche",
@@ -270,53 +270,53 @@
}
},
"overview": {
"model": "Current model",
"providers": "Providers",
"configuredCount": "{{count}} configured",
"totalProviders": "{{count}} available",
"webSearch": "Web search",
"imageGeneration": "Génération d'images",
"workspace": "Workspace"
"model": "Modèle actuel",
"providers": "Fournisseurs",
"configuredCount": "{{count}} configurés",
"totalProviders": "{{count}} disponibles",
"webSearch": "Recherche web",
"imageGeneration": "Génération dimages",
"workspace": "Espace de travail"
},
"providers": {
"searchPlaceholder": "Search providers",
"noMatches": "No providers match this search.",
"searchPlaceholder": "Rechercher des fournisseurs",
"noMatches": "Aucun fournisseur ne correspond.",
"saveProvider": "Enregistrer le fournisseur"
},
"image": {
"selectProvider": "Sélectionner un fournisseur",
"selectAspect": "Sélectionner un format",
"selectSize": "Sélectionner une taille",
"selectProvider": "Choisir un fournisseur",
"selectAspect": "Choisir un ratio",
"selectSize": "Choisir une taille",
"configureProvider": "Configurer le fournisseur",
"missingCredential": "Configurez ce fournisseur avant dactiver la génération dimages."
"missingCredential": "Configura este proveedor antes de activar la generación de imágenes."
},
"models": {
"selectModel": "Sélectionner un modèle",
"selectModel": "Choisir un modèle",
"addConfiguration": "Ajouter une configuration",
"newConfiguration": "Nouvelle configuration de modèle",
"newConfigurationHelp": "Enregistrez un fournisseur et un modèle comme option en un clic.",
"newConfigurationHelp": "Enregistre un fournisseur et un modèle comme option en un clic.",
"configurationName": "Nom de la configuration",
"configurationNameHelp": "Renommez cette configuration de modèle enregistrée.",
"configurationNameHelp": "Renomme cette configuration de modèle enregistrée.",
"configurationNamePlaceholder": "Rédaction rapide",
"searchModels": "Rechercher ou saisir lID du modèle",
"searchModels": "Rechercher ou saisir un ID de modèle",
"useCustomModel": "Utiliser",
"loadingModels": "Chargement des modèles...",
"searchCatalog": "Recherchez dans le catalogue du fournisseur pour choisir un modèle.",
"searchCatalog": "Rechercher dans le catalogue du fournisseur pour choisir un modèle.",
"modelsAvailable": "disponibles",
"noModelResults": "Aucun modèle correspondant.",
"loadFailed": "Liste des modèles indisponible.",
"unsupportedModelList": "Saisissez manuellement un ID de modèle.",
"providerNotConfigured": "Configurez ce fournisseur avant de charger les modèles.",
"autoProviderCustomOnly": "Le mode fournisseur automatique utilise des ID de modèle personnalisés."
"autoProviderCustomOnly": "Le mode fournisseur automatique utilise des IDs de modèle personnalisés."
},
"timezone": {
"select": "Sélectionner un fuseau horaire",
"select": "Choisir un fuseau horaire",
"search": "Rechercher un fuseau horaire",
"empty": "Aucun fuseau horaire correspondant."
},
"cliApps": {
"allCategories": "Toutes les catégories",
"availableCount": "{{count}} apps",
"availableCount": "{{count}} applications",
"installedCount": "{{count}} installées",
"summary": "{{installed}} CLIs installées sur {{total}}",
"filterAll": "Tout",
@@ -402,7 +402,7 @@
"thirdPartyBrands": "Les noms, logos et marques de produits appartiennent à leurs propriétaires respectifs. Leur utilisation sert uniquement à l'identification et n'implique aucune approbation."
},
"apps": {
"description": "Ajoutez des CLI dapps et des services MCP que nanobot peut utiliser dans le chat.",
"description": "Ajoutez des CLI dapps et services MCP utilisables par nanobot depuis le chat.",
"cliLabel": "CLI",
"mcpLabel": "MCP",
"filterAll": "Tout",
@@ -411,22 +411,22 @@
"enabledSummary": "{{count}} activés",
"caption": "{{cli}} CLI · {{mcp}} MCP",
"searchPlaceholder": "Rechercher des apps",
"featured": "En vedette",
"featured": "À la une",
"loading": "Chargement des apps...",
"empty": "Aucune app ne correspond à ce filtre."
"empty": "Aucune app ne correspond."
},
"oauth": {
"authentication": "OAuth authentication",
"signIn": "Sign in",
"signingIn": "Signing in...",
"signInAgain": "Sign in again",
"signOut": "Sign out",
"signedInAs": "Signed in as {{account}}",
"signInHelp": "Sign in from this device; no API key is stored in config.",
"signInRequired": "Sign in required",
"signInBeforeSaving": "Sign in before saving this OAuth provider as the active model provider.",
"signedIn": "Signed in",
"notSignedIn": "Not signed in"
"authentication": "Authentification OAuth",
"signIn": "Se connecter",
"signingIn": "Connexion...",
"signInAgain": "Se reconnecter",
"signOut": "Se déconnecter",
"signedInAs": "Connecté en tant que {{account}}",
"signInHelp": "Inicia sesión desde este dispositivo; no se guarda API key en config.",
"signInRequired": "Connexion requise",
"signInBeforeSaving": "Inicia sesión antes de guardar este proveedor OAuth como proveedor activo.",
"signedIn": "Connecté",
"notSignedIn": "Non connecté"
}
},
"chat": {