From ca2aaf0321c219d041e92e2c0c842a4e424732ef Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 2 Mar 2026 19:09:13 -0600 Subject: [PATCH 001/114] fix: ot terminal --- src/lib/components/chat/XTerminal.svelte | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/lib/components/chat/XTerminal.svelte b/src/lib/components/chat/XTerminal.svelte index eae497a500..e10ba02596 100644 --- a/src/lib/components/chat/XTerminal.svelte +++ b/src/lib/components/chat/XTerminal.svelte @@ -20,6 +20,7 @@ export let connected = false; export let connecting = false; let resizeObserver: ResizeObserver | null = null; + let pingInterval: ReturnType | null = null; // Resolve the active terminal server's info for the WebSocket URL const getTerminalInfo = (): { serverId: string; baseUrl: string } | null => { @@ -108,6 +109,13 @@ if (term && ws) { ws.send(JSON.stringify({ type: 'resize', cols: term.cols, rows: term.rows })); } + // Keepalive ping to prevent idle timeout from proxies/LBs + if (pingInterval) clearInterval(pingInterval); + pingInterval = setInterval(() => { + if (ws && ws.readyState === WebSocket.OPEN) { + ws.send(JSON.stringify({ type: 'ping' })); + } + }, 25000); }; ws.onmessage = (event) => { @@ -141,6 +149,10 @@ }; const disconnect = () => { + if (pingInterval) { + clearInterval(pingInterval); + pingInterval = null; + } if (ws) { ws.close(); ws = null; @@ -229,8 +241,10 @@ }); resizeObserver.observe(terminalEl); - // Auto-connect - connect(); + // Connection is handled by the reactive block below (which fires + // when `term` is set here), so we intentionally do NOT call + // connect() to avoid creating a duplicate WebSocket whose onclose + // handler would write a spurious "[Connection closed]" message. }; // Reconnect when the selected terminal changes From a36692b4a2e3ddc645d3c6419c13c9c4ceace76b Mon Sep 17 00:00:00 2001 From: Shirasawa <764798966@qq.com> Date: Thu, 5 Mar 2026 03:53:50 +0800 Subject: [PATCH 002/114] Merge pull request #22231 from ShirasawaSama/patch-10 fix: add missing beautifulsoup4 to backend requirements --- backend/requirements-min.txt | 1 + backend/requirements.txt | 1 + 2 files changed, 2 insertions(+) diff --git a/backend/requirements-min.txt b/backend/requirements-min.txt index 532a6cd714..6d28dc16d9 100644 --- a/backend/requirements-min.txt +++ b/backend/requirements-min.txt @@ -53,3 +53,4 @@ chromadb==1.4.1 black==26.1.0 pydub chardet==5.2.0 +beautifulsoup4 diff --git a/backend/requirements.txt b/backend/requirements.txt index 5c1f044d1d..76940d370e 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -73,6 +73,7 @@ unstructured==0.18.31 msoffcrypto-tool==6.0.0 nltk==3.9.2 Markdown==3.10.1 +beautifulsoup4 pypandoc==1.16.2 pandas==3.0.0 openpyxl==3.1.5 From 5af24b3ebe1587ef87792cba772d03e923d4f070 Mon Sep 17 00:00:00 2001 From: Shirasawa <764798966@qq.com> Date: Thu, 5 Mar 2026 03:54:21 +0800 Subject: [PATCH 003/114] fix: Implement archive chat handler in Chat page navbar (#22229) --- src/lib/components/chat/Chat.svelte | 22 ++++++++++++++++++- .../components/layout/Sidebar/ChatItem.svelte | 10 +++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index d3d216cf4c..50b9a0294d 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -65,6 +65,7 @@ import { AudioQueue } from '$lib/utils/audio'; import { + archiveChatById, createNewChat, getAllTags, getChatById, @@ -2585,6 +2586,25 @@ toast.error($i18n.t('Failed to move chat')); } }; + + const archiveChatHandler = async (id: string) => { + try { + await archiveChatById(localStorage.token, id); + currentChatPage.set(1); + initNewChat(); + await goto('/'); + getChatList(localStorage.token, $currentChatPage).then((chats) => { + chats.set(chats); + }); + getPinnedChatList(localStorage.token).then((pinnedChats) => { + pinnedChats.set(pinnedChats); + }); + toast.success($i18n.t('Chat archived.')); + } catch (error) { + console.error('Error archiving chat:', error); + toast.error($i18n.t('Failed to archive chat.')); + } + }; @@ -2667,7 +2687,7 @@ bind:selectedModels shareEnabled={!!history.currentId} {initNewChat} - archiveChatHandler={() => {}} + {archiveChatHandler} {moveChatHandler} onSaveTempChat={async () => { try { diff --git a/src/lib/components/layout/Sidebar/ChatItem.svelte b/src/lib/components/layout/Sidebar/ChatItem.svelte index 3a4f16e798..7134b1e94d 100644 --- a/src/lib/components/layout/Sidebar/ChatItem.svelte +++ b/src/lib/components/layout/Sidebar/ChatItem.svelte @@ -154,8 +154,14 @@ }; const archiveChatHandler = async (id) => { - await archiveChatById(localStorage.token, id); - dispatch('change'); + try { + await archiveChatById(localStorage.token, id); + dispatch('change'); + toast.success($i18n.t('Chat archived.')); + } catch (error) { + console.error('Error archiving chat:', error); + toast.error($i18n.t('Failed to archive chat.')); + } }; const moveChatHandler = async (chatId, folderId) => { From 7d45459a4784dd3a8e9e925820a8d0e349910103 Mon Sep 17 00:00:00 2001 From: Shirasawa <764798966@qq.com> Date: Thu, 5 Mar 2026 03:56:49 +0800 Subject: [PATCH 004/114] fix: keep save button spinner inline (#22227) --- src/lib/components/AddConnectionModal.svelte | 6 +++--- src/lib/components/AddToolServerModal.svelte | 6 +++--- src/lib/components/ImportModal.svelte | 6 +++--- src/lib/components/admin/Settings/Images.svelte | 6 +++--- .../admin/Settings/Models/ModelSettingsModal.svelte | 6 +++--- src/lib/components/admin/Users/Groups/EditGroupModal.svelte | 6 +++--- src/lib/components/admin/Users/UserList/AddUserModal.svelte | 6 +++--- src/lib/components/channel/WebhooksModal.svelte | 6 +++--- .../chat/Settings/Personalization/AddMemoryModal.svelte | 6 +++--- .../chat/Settings/Personalization/EditMemoryModal.svelte | 6 +++--- src/lib/components/workspace/Skills/SkillEditor.svelte | 6 +++--- src/lib/components/workspace/common/ValvesModal.svelte | 6 +++--- 12 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/lib/components/AddConnectionModal.svelte b/src/lib/components/AddConnectionModal.svelte index 8a8e269aea..76d67216f0 100644 --- a/src/lib/components/AddConnectionModal.svelte +++ b/src/lib/components/AddConnectionModal.svelte @@ -699,7 +699,7 @@ {/if} diff --git a/src/lib/components/AddToolServerModal.svelte b/src/lib/components/AddToolServerModal.svelte index db61a58e77..2f5e30a7c5 100644 --- a/src/lib/components/AddToolServerModal.svelte +++ b/src/lib/components/AddToolServerModal.svelte @@ -898,7 +898,7 @@ {/if} diff --git a/src/lib/components/ImportModal.svelte b/src/lib/components/ImportModal.svelte index fff9c12acf..2163ce26c8 100644 --- a/src/lib/components/ImportModal.svelte +++ b/src/lib/components/ImportModal.svelte @@ -104,7 +104,7 @@
+ {/if} diff --git a/src/lib/components/admin/Settings/Images.svelte b/src/lib/components/admin/Settings/Images.svelte index bf3ce6da19..5fe84d700a 100644 --- a/src/lib/components/admin/Settings/Images.svelte +++ b/src/lib/components/admin/Settings/Images.svelte @@ -1270,7 +1270,7 @@
+ {/if} diff --git a/src/lib/components/admin/Settings/Models/ModelSettingsModal.svelte b/src/lib/components/admin/Settings/Models/ModelSettingsModal.svelte index 1850940503..14b6e6d34c 100644 --- a/src/lib/components/admin/Settings/Models/ModelSettingsModal.svelte +++ b/src/lib/components/admin/Settings/Models/ModelSettingsModal.svelte @@ -436,7 +436,7 @@ diff --git a/src/lib/components/admin/Users/Groups/EditGroupModal.svelte b/src/lib/components/admin/Users/Groups/EditGroupModal.svelte index c93fc37ebd..b3290a11e4 100644 --- a/src/lib/components/admin/Users/Groups/EditGroupModal.svelte +++ b/src/lib/components/admin/Users/Groups/EditGroupModal.svelte @@ -219,7 +219,7 @@ {#if ['general', 'permissions'].includes(selectedTab)}
+ {/if} diff --git a/src/lib/components/admin/Users/UserList/AddUserModal.svelte b/src/lib/components/admin/Users/UserList/AddUserModal.svelte index 191a8b134e..84cfd4ffb6 100644 --- a/src/lib/components/admin/Users/UserList/AddUserModal.svelte +++ b/src/lib/components/admin/Users/UserList/AddUserModal.svelte @@ -285,7 +285,7 @@
+ {/if} diff --git a/src/lib/components/channel/WebhooksModal.svelte b/src/lib/components/channel/WebhooksModal.svelte index c095e38018..820a7f3cb5 100644 --- a/src/lib/components/channel/WebhooksModal.svelte +++ b/src/lib/components/channel/WebhooksModal.svelte @@ -160,7 +160,7 @@
diff --git a/src/lib/components/chat/Settings/Personalization/AddMemoryModal.svelte b/src/lib/components/chat/Settings/Personalization/AddMemoryModal.svelte index 9f52fd8c8d..570e41880a 100644 --- a/src/lib/components/chat/Settings/Personalization/AddMemoryModal.svelte +++ b/src/lib/components/chat/Settings/Personalization/AddMemoryModal.svelte @@ -76,7 +76,7 @@
+ {/if} diff --git a/src/lib/components/chat/Settings/Personalization/EditMemoryModal.svelte b/src/lib/components/chat/Settings/Personalization/EditMemoryModal.svelte index 9baa9ab27c..0f16200c1e 100644 --- a/src/lib/components/chat/Settings/Personalization/EditMemoryModal.svelte +++ b/src/lib/components/chat/Settings/Personalization/EditMemoryModal.svelte @@ -86,7 +86,7 @@
+ {/if} diff --git a/src/lib/components/workspace/Skills/SkillEditor.svelte b/src/lib/components/workspace/Skills/SkillEditor.svelte index 62927b142b..7537ec45e7 100644 --- a/src/lib/components/workspace/Skills/SkillEditor.svelte +++ b/src/lib/components/workspace/Skills/SkillEditor.svelte @@ -252,15 +252,15 @@
{#if !disabled} {/if} diff --git a/src/lib/components/workspace/common/ValvesModal.svelte b/src/lib/components/workspace/common/ValvesModal.svelte index 577ce2eb04..16f3af4b6b 100644 --- a/src/lib/components/workspace/common/ValvesModal.svelte +++ b/src/lib/components/workspace/common/ValvesModal.svelte @@ -184,7 +184,7 @@
+ {/if}
From ad275351b6689ced7ea76a0b7f46dc18eaeb2ebe Mon Sep 17 00:00:00 2001 From: Eliot GODARD Date: Wed, 4 Mar 2026 20:57:30 +0100 Subject: [PATCH 005/114] i18n(fr-FR): complete French translation pass (#22200) Adds and harmonizes French translations across the entire UI: - Translate admin pages (Images, connections, models, etc.) - Harmonize API key/URL field translations - Fix "successfully" translations consistency - Add missing translations (feedback, file, model selector) - Fix typos and improve existing translations --- src/lib/i18n/locales/fr-FR/translation.json | 680 ++++++++++---------- 1 file changed, 340 insertions(+), 340 deletions(-) diff --git a/src/lib/i18n/locales/fr-FR/translation.json b/src/lib/i18n/locales/fr-FR/translation.json index 151281ce92..3f24312660 100644 --- a/src/lib/i18n/locales/fr-FR/translation.json +++ b/src/lib/i18n/locales/fr-FR/translation.json @@ -5,46 +5,46 @@ "(e.g. `sh webui.sh --api`)": "(par exemple `sh webui.sh --api`)", "(latest)": "(dernière version)", "(leave blank for to use commercial endpoint)": "laisser vide pour l'utilisation d'un point d'extension commercial", - "[Last] dddd [at] h:mm A": "", - "[Today at] h:mm A": "", - "[Yesterday at] h:mm A": "", + "[Last] dddd [at] h:mm A": "dddd [dernier] à H[h]mm", + "[Today at] h:mm A": "[Aujourd'hui à] H[h]mm", + "[Yesterday at] h:mm A": "[Hier à] H[h]mm", "{{ models }}": "{{ models }}", "{{COUNT}} Available Tools": "{{COUNT}} outils disponibles ", "{{COUNT}} characters": "{{COUNT}} caractères", "{{COUNT}} extracted lines": "{{COUNT}} lignes extraites", - "{{COUNT}} files": "", + "{{COUNT}} files": "{{COUNT}} fichiers", "{{COUNT}} hidden lines": "Nombres de lignes cachées {{COUNT}}", - "{{COUNT}} members": "", + "{{COUNT}} members": "{{COUNT}} membres", "{{COUNT}} Replies": "{{COUNT}} réponses", - "{{COUNT}} Rows": "", + "{{COUNT}} Rows": "{{COUNT}} lignes", "{{COUNT}} Sources": "{{COUNT}} Sources", "{{COUNT}} words": "{{COUNT}} mots", - "{{COUNT}}d_time_ago": "", - "{{COUNT}}h_time_ago": "", - "{{COUNT}}m_time_ago": "", - "{{COUNT}}w_time_ago": "", - "{{COUNT}}y_time_ago": "", + "{{COUNT}}d_time_ago": "{{COUNT}}j", + "{{COUNT}}h_time_ago": "{{COUNT}}h", + "{{COUNT}}m_time_ago": "{{COUNT}}min", + "{{COUNT}}w_time_ago": "{{COUNT}}sem", + "{{COUNT}}y_time_ago": "{{COUNT}}a", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "{{LOCALIZED_DATE}} à {{LOCALIZED_TIME}}", "{{model}} download has been canceled": "Le téléchargement de {{model}} a été annulé", - "{{modelName}} profile image": "", + "{{modelName}} profile image": "Image de profil de {{modelName}}", "{{NAMES}} reacted with {{REACTION}}": "", "{{user}}'s Chats": "Conversations de {{user}}", "{{webUIName}} Backend Required": "Backend {{webUIName}} requis", - "*Prompt node ID(s) are required for image generation": "*Les ID de noeud du prompt sont nécessaires pour la génération d'images", + "*Prompt node ID(s) are required for image generation": "*Les ID de noeud du prompt sont nécessaires pour la génération d'image", "1 Source": "1 Source", - "1m_time_ago": "", - "A collaboration channel where people join as members": "", - "A discussion channel where access is controlled by groups and permissions": "", + "1m_time_ago": "1min", + "A collaboration channel where people join as members": "Un canal collaboratif où les membres rejoignent librement", + "A discussion channel where access is controlled by groups and permissions": "Un canal de discussion où l'accès est contrôlé par les groupes et les permissions", "A new version (v{{LATEST_VERSION}}) is now available.": "Une nouvelle version (v{{LATEST_VERSION}}) est disponible.", - "A private conversation between you and selected users": "", + "A private conversation between you and selected users": "Une conversation privée entre vous et les utilisateurs sélectionnés", "A task model is used when performing tasks such as generating titles for chats and web search queries": "Un modèle de tâche est utilisé lors de l'exécution de tâches telles que la génération de titres pour les conversations et les requêtes de recherche sur le web.", "a user": "un utilisateur", "About": "À propos", - "Accept Autocomplete Generation\nJump to Prompt Variable": "", + "Accept Autocomplete Generation\nJump to Prompt Variable": "Accepter l'autocomplétion\nRenseigner les variables du prompt", "Access": "Accès", "Access Control": "Contrôle d'accès", "Access Grants": "", - "Access List": "", + "Access List": "Liste des accès", "Accessible to all users": "Accessible à tous les utilisateurs", "Account": "Compte", "Account Activation Pending": "Activation du compte en attente", @@ -57,13 +57,13 @@ "Activate this command by typing \"/{{COMMAND}}\" to chat input.": "Activez cette commande en tapant \"/{{COMMAND}}\" dans l'entrée de la conversation.", "Active": "Actif", "Active Users": "Utilisateurs connectés", - "Activity": "", + "Activity": "Activité", "Add": "Ajouter", - "Add a model ID": "Ajouter un identifiant de modèle", + "Add a model ID": "Ajouter un ID de modèle", "Add a short description about what this model does": "Ajoutez une brève description de ce que fait ce modèle.", "Add a tag": "Ajouter un tag", "Add a tag...": "", - "Add Access": "", + "Add Access": "Ajouter un accès", "Add Arena Model": "Ajouter un modèle d'arène", "Add Connection": "Ajouter une connexion", "Add Content": "Ajouter du contenu", @@ -72,26 +72,26 @@ "Add Custom Prompt": "", "Add Details": "Ajouter des détails", "Add Files": "Ajouter des fichiers", - "Add Image": "", + "Add Image": "Ajouter une image", "Add Member": "", - "Add Members": "", + "Add Members": "Ajouter des membres", "Add Memory": "Ajouter un souvenir", "Add Model": "Ajouter un modèle", "Add Reaction": "Ajouter une réaction", "Add tag": "", "Add Tag": "Ajouter un tag", - "Add Terminal": "", - "Add Terminal Connection": "", + "Add Terminal": "Ajouter un terminal", + "Add Terminal Connection": "Ajouter une connexion à un terminal", "Add text content": "Ajouter du contenu textuel", - "Add to favorites": "", + "Add to favorites": "Ajouter aux favoris", "Add User": "Ajouter un utilisateur", "Add User Group": "Ajouter un groupe d'utilisateurs", - "Add webpage": "", + "Add webpage": "Ajouter une page web", "Add your Open Terminal URL and API key in Settings → Integrations.": "", "Additional Config": "Configuration supplémentaire", "Additional configuration options for marker. This should be a JSON string with key-value pairs. For example, '{\"key\": \"value\"}'. Supported keys include: disable_links, keep_pageheader_in_output, keep_pagefooter_in_output, filter_blank_pages, drop_repeated_text, layout_coverage_threshold, merge_threshold, height_tolerance, gap_threshold, image_threshold, min_line_length, level_count, default_level": "", - "Additional feedback comments": "", - "Additional Parameters": "", + "Additional feedback comments": "Commentaires supplémentaires", + "Additional Parameters": "Paramètres supplémentaires", "Adds filenames, titles, sections, and snippets into the BM25 text to improve lexical recall.": "", "Adjusting these settings will apply changes universally to all users.": "L'ajustement de ces réglages appliquera universellement les changements à tous les utilisateurs.", "admin": "administrateur", @@ -104,14 +104,14 @@ "Advanced Parameters": "Réglages avancés", "Advanced parameters for MinerU parsing (enable_ocr, enable_formula, enable_table, language, model_version, page_ranges)": "", "Advanced Params": "Réglages avancés", - "After updating or changing the embedding model, you must reindex the knowledge base for the changes to take effect. You can do this using the \"Reindex\" button below.": "", + "After updating or changing the embedding model, you must reindex the knowledge base for the changes to take effect. You can do this using the \"Reindex\" button below.": "Après avoir mis à jour ou modifié le modèle d'embedding, vous devez réindexer la base de connaissances pour que les changements prennent effet. Vous pouvez le faire en utilisant le bouton « Réindexer » ci-dessous.", "AI": "IA", "All": "Tout", "All chats have been unarchived.": "", - "All models are now hidden": "", - "All models are now visible": "", - "All models deleted successfully": "Tous les modèles ont été supprimés avec succès", - "All time": "", + "All models are now hidden": "Tous les modèles sont maintenant masqués", + "All models are now visible": "Tous les modèles sont maintenant visibles", + "All models deleted successfully": "Tous les modèles supprimés avec succès", + "All time": "Toute la période", "All Users": "", "Allow Call": "Autoriser les appels", "Allow Chat Controls": "Autoriser les contrôles de la conversation", @@ -127,8 +127,8 @@ "Allow File Upload": "Autoriser le téléversement de fichiers", "Allow Multiple Models in Chat": "Autoriser plusieurs modèles dans la conversation", "Allow non-local voices": "Autoriser les voix non locales", - "Allow Rate Response": "", - "Allow Regenerate Response": "Autoriser la régénération de la réponse", + "Allow Rate Response": "Autoriser l'évaluation de la réponse", + "Allow Regenerate Response": "Autoriser la regénération de la réponse", "Allow Sharing With Users": "", "Allow Speech to Text": "Autoriser la reconnaissance vocale", "Allow Temporary Chat": "Autoriser la conversation temporaire", @@ -154,13 +154,13 @@ "and {{COUNT}} more": "et {{COUNT}} autres", "and create a new shared link.": "et créer un nouveau lien partagé.", "Android": "Android", - "Anyone": "", + "Anyone": "Tout le monde", "API Base URL": "URL de base de l'API", "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "URL de base de l'API pour le service Datalab Marker. Par défaut : https://www.datalab.to/api/v1/marker", - "API Key": "Clé d'API", - "API Key created.": "Clé d'API générée.", + "API Key": "Clé API", + "API Key created.": "Clé API générée.", "API Key Endpoint Restrictions": "Restrictions des points de terminaison de la clé API", - "API keys": "Clés d'API", + "API keys": "Clés API", "API Keys": "", "API Mode": "", "API Timeout": "", @@ -172,21 +172,21 @@ "applies to all users with the \"user\" role": "s'applique à tous les utilisateurs ayant le rôle « utilisateur »", "April": "Avril", "Archive": "Archiver", - "Archive All": "", + "Archive All": "Tout archiver", "Archive All Chats": "Archiver toutes les conversations", "Archived Chats": "Conversations archivées", "archived-chat-export": "exportation de conversation archivée", - "Are you sure you want to archive all chats? This action cannot be undone.": "", - "Are you sure you want to clear all memories? This action cannot be undone.": "Êtes-vous certain de vouloir supprimer toutes les mémoires ? Cette action est définitive.", - "Are you sure you want to delete \"{{NAME}}\"?": "", - "Are you sure you want to delete all chats? This action cannot be undone.": "", + "Are you sure you want to archive all chats? This action cannot be undone.": "Êtes-vous sûr de vouloir archiver toutes les conversations ? Cette action est irréversible.", + "Are you sure you want to clear all memories? This action cannot be undone.": "Êtes-vous certain de vouloir supprimer toutes les mémoires ? Cette action est irréversible.", + "Are you sure you want to delete \"{{NAME}}\"?": "Êtes-vous sûr de vouloir supprimer \"{{NAME}}\" ?", + "Are you sure you want to delete all chats? This action cannot be undone.": "Êtes-vous sûr de vouloir supprimer toutes les conversations ? Cette action est irréversible.", "Are you sure you want to delete this channel?": "Êtes-vous sûr de vouloir supprimer ce canal ?", "Are you sure you want to delete this message?": "Êtes-vous sûr de vouloir supprimer ce message ?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", - "Are you sure you want to unarchive all archived chats?": "Êtes-vous sûr de vouloir désarchiver toutes les conversations archivées?", + "Are you sure you want to unarchive all archived chats?": "Êtes-vous sûr de vouloir désarchiver toutes les conversations ?", "Arena Models": "Modèles d'arène", "Artifacts": "Artéfacts", - "Asc": "", + "Asc": "Croissant", "Ask": "Demander", "Ask a question": "Posez votre question", "Assistant": "Assistant", @@ -271,12 +271,12 @@ "Change Password": "Changer le mot de passe", "Change User Role": "", "Channel": "Canal", - "Channel deleted successfully": "Le canal a été supprimée avec succès", + "Channel deleted successfully": "Canal supprimé avec succès", "Channel Name": "Nom du canal", - "Channel name cannot be empty.": "", - "Channel name must be less than 128 characters": "", - "Channel Type": "", - "Channel updated successfully": "Le canal a été mise à jour avec succès", + "Channel name cannot be empty.": "Le nom du canal ne peut pas être vide.", + "Channel name must be less than 128 characters": "Le nom du canal doit faire moins de 128 caractères", + "Channel Type": "Type de canal", + "Channel updated successfully": "Canal mis à jour avec succès", "Channels": "Canaux", "Character": "Caractère", "Character limit for autocomplete generation input": "Limite de caractères pour la génération des suggestions", @@ -287,13 +287,13 @@ "Chat Completions": "", "Chat Conversation": "Conversation par chat", "Chat direction": "Direction de la conversation", - "Chat exported successfully": "", + "Chat exported successfully": "Conversation exportée avec succès", "Chat History": "", "Chat ID": "ID de chat", - "Chat moved successfully": "La conversation a été déplacé avec succès", + "Chat moved successfully": "Conversation déplacée avec succès", "Chat Permissions": "Autorisations de la conversation", "Chat Tags Auto-Generation": "Génération automatique des tags", - "Chat unshared successfully.": "", + "Chat unshared successfully.": "Conversation non partagée avec succès.", "chats": "", "Chats": "Conversations", "Check Again": "Vérifiez à nouveau.", @@ -334,9 +334,9 @@ "Close chat controls": "", "Close citation modal": "", "Close Configure Connection Modal": "Fermer la fenêtre de configuration de la connexion", - "Close feedback": "", + "Close feedback": "Fermer la fenêtre d'évaluation", "Close modal": "Fermer la fenêtre", - "Close Modal": "", + "Close Modal": "Fermer la fenêtre", "Close settings modal": "Fermer la fenêtre des réglages", "Close Sidebar": "Fermer la barre latérale", "cloud": "", @@ -347,11 +347,11 @@ "Code Execution": "", "Code Execution Engine": "Moteur d'execution de code", "Code Execution Timeout": "Délai d'exécution du code dépassé", - "Code formatted successfully": "Le code a été formaté avec succès", + "Code formatted successfully": "Code formaté avec succès", "Code Interpreter": "Interpreteur de code", "Code Interpreter Engine": "Moteur de l'interpreteur de code", "Code Interpreter Prompt Template": "Modèle d'invite pour l'interpréteur de code", - "Collaboration channel where people join as members": "", + "Collaboration channel where people join as members": "Canal collaboratif où les membres rejoignent librement", "Collapse": "Réduire", "Collection": "Collection", "Collections": "", @@ -360,8 +360,8 @@ "ComfyUI API Key": "Clé API ComfyUI", "ComfyUI Base URL": "URL de base ComfyUI", "ComfyUI Base URL is required.": "L'URL de base ComfyUI est requise.", - "ComfyUI Workflow": "Flux de travaux de ComfyUI", - "ComfyUI Workflow Nodes": "Noeud du flux de travaux de ComfyUI", + "ComfyUI Workflow": "Workflow ComfyUI", + "ComfyUI Workflow Nodes": "Noeuds du workflow ComfyUI", "Comma separated Node Ids (e.g. 1 or 1,2)": "ID de nœud séparés par des virgules (Ex : 1 ou 1,2)", "command": "", "Command": "Commande", @@ -412,8 +412,8 @@ "Copy API Key": "", "Copy content": "", "Copy Formatted Text": "Copier le texte en gardant le format", - "Copy Last Code Block": "", - "Copy Last Response": "", + "Copy Last Code Block": "Copier le dernier bloc de code", + "Copy Last Response": "Copier la dernière réponse", "Copy link": "Copier le lien", "Copy Link": "Copier le lien", "Copy Prompt": "", @@ -423,7 +423,7 @@ "Copy URL": "", "Copying to clipboard was successful!": "La copie dans le presse-papiers a réussi !", "CORS must be properly configured by the provider to allow requests from Open WebUI.": "Le réglage CORS doit être correctement configuré par le fournisseur pour autoriser les requêtes provenant de l'Open WebUI.", - "Could not read file.": "", + "Could not read file.": "Impossible de lire le fichier.", "Create": "Créer", "Create a knowledge base": "Créer une base de connaissances", "Create a model": "Créer un modèle", @@ -432,7 +432,7 @@ "Create Admin Account": "Créer un compte administrateur", "Create Channel": "Créer un canal", "Create Folder": "Créer un dossier", - "Create Image": "", + "Create Image": "Création d'image", "Create Knowledge": "Créer une connaissance", "Create Model": "", "Create new key": "Créer une nouvelle clé", @@ -443,8 +443,8 @@ "Created at": "Créé le", "Created At": "Créé le", "Created by": "Créé par", - "Created by you": "", - "Created on {{date}}": "", + "Created by you": "Créé par vous", + "Created on {{date}}": "Créé le {{date}}", "CSV Import": "Import CSV", "Ctrl+Enter to Send": "Ctrl+Enter pour envoyer", "Current Model": "Modèle actuel", @@ -460,8 +460,8 @@ "Data Controls": "Contrôles des données", "Database": "Base de données", "Datalab Marker API": "API Datalab Marker", - "DD/MM/YYYY": "JJ/MM/AAAA", - "DDGS Backend": "", + "DD/MM/YYYY": "DD/MM/YYYY", + "DDGS Backend": "DDGS Backend", "December": "Décembre", "Decrease UI Scale": "", "Deepgram": "", @@ -472,7 +472,7 @@ "Default description enabled": "Description par défaut activée", "Default Features": "Fonctionnalités par défaut", "Default Filters": "Filtres par défaut", - "Default Group": "", + "Default Group": "Groupe par défaut", "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Le mode par défaut fonctionne avec une plus large gamme de modèles en appelant les outils une fois avant l'exécution. Le mode natif exploite les capacités d'appel d'outils intégrées du modèle, mais nécessite que le modèle prenne en charge cette fonctionnalité.", "Default Model": "Modèle standard", "Default model updated": "Modèle par défaut mis à jour", @@ -486,20 +486,20 @@ "Defaults": "", "Delete": "Supprimer", "Delete a model": "Supprimer un modèle", - "Delete All": "", + "Delete All": "Tout supprimer", "Delete All Chats": "Supprimer toutes les conversations", - "Delete all contents inside this folder": "", + "Delete all contents inside this folder": "Supprimer tout le contenu de ce dossier", "Delete Chat": "Supprimer la Conversation", "Delete chat?": "Supprimer la conversation ?", - "Delete File": "", + "Delete File": "Supprimer le fichier", "Delete folder?": "Supprimer le dossier ?", "Delete function?": "Supprimer la fonction ?", "Delete Message": "Supprimer le message", "Delete message?": "Supprimer le message ?", "Delete Model": "", - "Delete note?": "Supprimer la note?", + "Delete note?": "Supprimer la note ?", "Delete prompt?": "Supprimer le prompt ?", - "Delete skill?": "", + "Delete skill?": "Supprimer le skill ?", "delete this link": "supprimer ce lien", "Delete tool?": "Effacer l'outil ?", "Delete User": "Supprimer le compte d'utilisateur", @@ -509,7 +509,7 @@ "Deleted {{name}}": "Supprimé {{name}}", "Deleted User": "Utilisateur supprimé", "Deployment names are required for Azure OpenAI": "Les noms de déploiement sont requis pour Azure OpenAI", - "Desc": "", + "Desc": "Décroissant", "Describe the edit...": "", "Describe the image...": "", "Describe what changed...": "", @@ -521,10 +521,10 @@ "Direct": "Direct", "Direct Connections": "Direct connexions", "Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "Les connexions directes permettent aux utilisateurs de se connecter à leurs propres points d'extension API compatibles OpenAI.", - "Direct Message": "", + "Direct Message": "Message direct", "Direct Tool Servers": "Serveur d'outils directs", "Directory selection was cancelled": "La sélection du répertoire a été annulée", - "Disable All": "", + "Disable All": "Désactiver tout", "Disable Code Interpreter": "Désactiver l'interpréteur de code", "Disable Image Extraction": "Empecher l'extraction d'image", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "Désactive l'extraction d'images du PDF. Si l'option Utiliser le LLM est activée, les images seront automatiquement légendées. La valeur par défaut est False.", @@ -539,7 +539,7 @@ "Discover, download, and explore custom prompts": "Découvrez, téléchargez et explorez des prompts personnalisés", "Discover, download, and explore custom tools": "Découvrez, téléchargez et explorez des outils personnalisés", "Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préréglages de modèles", - "Discussion channel where access is based on groups and permissions": "", + "Discussion channel where access is based on groups and permissions": "Canal de discussion où l'accès est basé sur les groupes et les permissions", "Display": "Afficher", "Display chat title in tab": "Afficher le nom de la conversation dans l'onglet", "Display Emoji in Call": "Afficher les emojis pendant l'appel", @@ -550,16 +550,16 @@ "Dive into knowledge": "Plonger dans les connaissances", "Do not install functions from sources you do not fully trust.": "N'installez pas de fonctions provenant de sources auxquelles vous ne faites pas entièrement confiance.", "Do not install tools from sources you do not fully trust.": "N'installez pas d'outils provenant de sources auxquelles vous ne faites pas entièrement confiance.", - "Do you want to sync your usage stats with Open WebUI Community?": "", + "Do you want to sync your usage stats with Open WebUI Community?": "Souhaitez-vous synchroniser vos statistiques d'utilisation avec la communauté Open WebUI ?", "Docling": "Docling", "Docling Parameters": "", "Docling Server URL required.": "URL du serveur Docling requise.", "Document": "Document", - "Document Intelligence": "Intelligence documentaire", - "Document Intelligence endpoint required.": "Point de terminaison Document Intelligence requis.", - "Document Intelligence Model": "", + "Document Intelligence": "Document Intelligence", + "Document Intelligence endpoint required.": "Endpoint Document Intelligence requis.", + "Document Intelligence Model": "Modèle Document Intelligence", "Documentation": "Documentation", - "Documents": "", + "Documents": "Documents", "does not make any external connections, and your data stays securely on your locally hosted server.": "n'établit aucune connexion externe et garde vos données en sécurité sur votre serveur local.", "Domain Filter List": "Liste des domaines à filtrés", "don't fetch random pipelines from sources you don't trust.": "Ne récupérez pas des pipelines aléatoires depuis des sources non fiables.", @@ -574,10 +574,10 @@ "Download as SVG": "Télécharger au format SVG", "Download canceled": "Téléchargement annulé", "Download Database": "Télécharger la base de données", - "Downloading stats...": "", + "Downloading stats...": "Téléchargement des statistiques...", "Draw": "Match nul", "Drop any files here to upload": "Déposez des fichiers ici pour les téléverser", - "Drop files here to upload": "", + "Drop files here to upload": "Déposez des fichiers ici pour les téléverser", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "par ex. '30s', '10 min'. Les unités de temps valides sont 's', 'm', 'h'.", "e.g. 'low', 'medium', 'high'": "", @@ -608,14 +608,14 @@ "Edit Connection": "Modifier la connexion", "Edit Default Permissions": "Modifier les autorisations par défaut", "Edit Folder": "Modifier le dossier", - "Edit Image": "Modifier l'image", + "Edit Image": "Modification d'image", "Edit Last Message": "Modifier le dernier message", "Edit Memory": "Modifier la mémoire", "Edit Prompt": "", - "Edit Terminal Connection": "", + "Edit Terminal Connection": "Modifier la connexion à un terminal", "Edit User": "Modifier l'utilisateur", "Edit User Group": "Modifier le groupe d'utilisateurs", - "Edit workflow.json content": "", + "Edit workflow.json content": "Modifier le contenu de workflow.json", "edited": "édité", "Edited": "Édité", "Editing": "Édition en cours", @@ -629,7 +629,7 @@ "Embedding Concurrent Requests": "", "Embedding Model": "Modèle d'embedding", "Embedding Model Engine": "Moteur de modèle d'embedding", - "Enable All": "", + "Enable All": "Activer tout", "Enable API Keys": "Autoriser les clés API", "Enable autocomplete generation for chat messages": "Activer la génération des suggestions pour les messages", "Enable Code Execution": "Autoriser l'execution de code", @@ -653,9 +653,9 @@ "Enter a detail about yourself for your LLMs to recall": "Saisissez un détail sur vous-même que vos LLMs pourront se rappeler", "Enter a title for the pending user info overlay. Leave empty for default.": "Entrez un titre pour l'interface utilisateur en attente. Laissez vide pour le défaut.", "Enter a watermark for the response. Leave empty for none.": "Entrez un filigrane pour la réponse. Laissez vide pour aucun.", - "Enter additional headers in JSON format": "", - "Enter additional headers in JSON format (e.g. {\"X-Custom-Header\": \"value\"}": "", - "Enter additional parameters in JSON format": "", + "Enter additional headers in JSON format": "Entrez les en-têtes supplémentaires au format JSON", + "Enter additional headers in JSON format (e.g. {\"X-Custom-Header\": \"value\"}": "Entrez les en-têtes supplémentaires au format JSON (par ex. {\"X-Custom-Header\": \"value\"}", + "Enter additional parameters in JSON format": "Entrez les paramètres supplémentaires au format JSON", "Enter api auth string (e.g. username:password)": "Entrez la chaîne d'authentification de l'API (par ex. nom d'utilisateur:mot de passe)", "Enter Application DN": "Entrez le DN de l'application", "Enter Application DN Password": "Entrez le mot de passe DN de l'application", @@ -664,22 +664,22 @@ "Enter Bocha Search API Key": "Entrez la clé API Bocha Search", "Enter Brave Search API Key": "Entrez la clé API Brave Search", "Enter certificate path": "Entrez le chemin du certificat", - "Enter Chunk Min Size Target": "", + "Enter Chunk Min Size Target": "Entrez la taille minimale cible des chunks", "Enter Chunk Overlap": "Entrez le chevauchement des chunks", "Enter Chunk Size": "Entrez la taille des chunks", "Enter comma-separated \"token:bias_value\" pairs (example: 5432:100, 413:-100)": "Entrez des paires \"token:valeur_biais\" séparées par des virgules (exemple : 5432:100, 413:-100)", "Enter content for the pending user info overlay. Leave empty for default.": "Entrez le contenu pour l'interface utilisateur en attente. Laissez vide pour le défaut.", "Enter coordinates (e.g. 51.505, -0.09)": "Entrez les coordonnées (Ex : 51.505, -0.09)", - "Enter Datalab Marker API Base URL": "Saisissez l'URL de base de l'API Datalab Marker", + "Enter Datalab Marker API Base URL": "Entrez l'URL de base de l'API Datalab Marker", "Enter Datalab Marker API Key": "Entrez la clé API Datalab Marker", "Enter description": "Entrez la description", - "Enter Docling API Key": "Entrez la clé API de Docling", - "Enter Docling Server URL": "Entrez l'url du serveur Docling", - "Enter Document Intelligence Endpoint": "Entrez le point d'extension d'Intelligence documentaire", - "Enter Document Intelligence Key": "Entrez la clé du sevice d'Intelligence documentaire", - "Enter Document Intelligence Model": "", - "Enter domains separated by commas (e.g., example.com,site.org,!excludedsite.com)": "", - "Enter Exa API Key": "Entrez la clé d'api de Exa", + "Enter Docling API Key": "Entrez la clé API Docling", + "Enter Docling Server URL": "Entrez l'URL du serveur Docling", + "Enter Document Intelligence Endpoint": "Entrez l'endpoint Document Intelligence", + "Enter Document Intelligence Key": "Entrez la clé Document Intelligence", + "Enter Document Intelligence Model": "Entrez le modèle Document Intelligence", + "Enter domains separated by commas (e.g., example.com,site.org,!excludedsite.com)": "Entrez les domaines séparés par des virgules (par ex. example.com,site.org,!excludedsite.com)", + "Enter Exa API Key": "Entrez la clé API Exa", "Enter External Document Loader API Key": "Entrez la clé API du chargeur de documents externe", "Enter External Document Loader URL": "Entrez l'URL du chargeur de documents externe", "Enter External Web Loader API Key": "Entrez la clé API du chargeur Web externe", @@ -687,55 +687,55 @@ "Enter External Web Search API Key": "Entrez la clé API de la recherche Web externe", "Enter External Web Search URL": "Entrez l'URL de la recherche Web externe", "Enter Firecrawl API Base URL": "Entrez l'URL de base de l'API Firecrawl", - "Enter Firecrawl API Key": "Entrez la clé API de Firecrawl", - "Enter Firecrawl Timeout": "", + "Enter Firecrawl API Key": "Entrez la clé API Firecrawl", + "Enter Firecrawl Timeout": "Entrez le délai d'expiration Firecrawl", "Enter folder name": "Entrez le nom du dossier", - "Enter function name filter list (e.g. func1, !func2)": "", + "Enter function name filter list (e.g. func1, !func2)": "Entrez la liste de filtres de fonctions (par ex. func1, !func2)", "Enter Github Raw URL": "Entrez l'URL brute de GitHub", "Enter Google PSE API Key": "Entrez la clé API Google PSE", "Enter Google PSE Engine Id": "Entrez l'identifiant du moteur Google PSE", "Enter hex color (e.g. #FF0000)": "Entrez la couleur hexadécimale (Ex : #FF0000)", "Enter Image Size (e.g. 512x512)": "Entrez la taille de l'image (par ex. 512x512)", - "Enter Jina API Base URL": "", + "Enter Jina API Base URL": "Entrez l'URL de base de l'API Jina", "Enter Jina API Key": "Entrez la clé API Jina", - "Enter JSON config (e.g., {\"disable_links\": true})": "", + "Enter JSON config (e.g., {\"disable_links\": true})": "Entrez la configuration JSON (par ex. {\"disable_links\": true})", "Enter Jupyter Password": "Entrez le mot de passe Jupyter", "Enter Jupyter Token": "Entrez le Token Jupyter", - "Enter Jupyter URL": "Entrez l'url de Jupyter", - "Enter Kagi Search API Key": "Entrez la clé API Kagi Search", + "Enter Jupyter URL": "Entrez l'URL de Jupyter", + "Enter Kagi Search API Key": "Entrez la clé API Kagi", "Enter Key Behavior": "Comportement de la touche Entrée", "Enter language codes": "Entrez les codes de langue", - "Enter MinerU API Key": "", - "Enter Mistral API Base URL": "", - "Enter Mistral API Key": "Entrez la clé APU de Mistral", + "Enter MinerU API Key": "Entrez la clé API MinerU", + "Enter Mistral API Base URL": "Entrez l'URL de base de l'API Mistral", + "Enter Mistral API Key": "Entrez la clé API Mistral", "Enter Model ID": "Entrez l'ID du modèle", "Enter model tag (e.g. {{modelTag}})": "Entrez le tag du modèle (par ex. {{modelTag}})", "Enter Mojeek Search API Key": "Entrez la clé API Mojeek", "Enter name": "Entrez votre nom", "Enter New Password": "Entrez votre nouveau mots de passe", "Enter Number of Steps (e.g. 50)": "Entrez le nombre d'étapes (par ex. 50)", - "Enter Ollama Cloud API Key": "", - "Enter Perplexity API Key": "Entrez la clé pour l'API de Perplixity", - "Enter Perplexity Search API URL": "", + "Enter Ollama Cloud API Key": "Entrez la clé API Ollama Cloud", + "Enter Perplexity API Key": "Entrez la clé API Perplexity", + "Enter Perplexity Search API URL": "Entrez l'URL de l'API Perplexity", "Enter Playwright Timeout": "Entrez le délai d'expiration Playwright", - "Enter Playwright WebSocket URL": "Entrez l'irl du websocket Playwright", - "Enter proxy URL (e.g. https://user:password@host:port)": "Entrez l'URL du proxy (par ex. https://use:password@host:port)", + "Enter Playwright WebSocket URL": "Entrez l'URL du websocket Playwright", + "Enter proxy URL (e.g. https://user:password@host:port)": "Entrez l'URL du proxy (par ex. https://user:password@host:port)", "Enter reasoning effort": "Entrez l'effort de raisonnement", "Enter Score": "Entrez votre score", "Enter SearchApi API Key": "Entrez la clé API SearchApi", "Enter SearchApi Engine": "Entrez le moteur de recherche SearchApi", "Enter Searxng Query URL": "Entrez l'URL de la requête Searxng", - "Enter Searxng search language": "", + "Enter Searxng search language": "Entrez la langue de recherche de Searxng", "Enter Seed": "Entrez Seed", - "Enter SerpApi API Key": "Entrez la clé API SerPAI", - "Enter SerpApi Engine": "Entrez le moteur SerApi", + "Enter SerpApi API Key": "Entrez la clé API SerpApi", + "Enter SerpApi Engine": "Entrez le moteur SerpApi", "Enter Serper API Key": "Entrez la clé API Serper", "Enter Serply API Key": "Entrez la clé API Serply", "Enter Serpstack API Key": "Entrez la clé API Serpstack", "Enter server host": "Entrez l'hôte du serveur", "Enter server label": "Entrez l'étiquette du serveur", "Enter server port": "Entrez le port du serveur", - "Enter skill instructions in markdown...": "", + "Enter skill instructions in markdown...": "Entrez les instructions du skill au format markdown...", "Enter Sougou Search API sID": "Entrez le sID pour l'API Search de Sougou", "Enter Sougou Search API SK": "Entrez la SK pour l'API Search de Sougou", "Enter stop sequence": "Entrez la séquence d'arrêt", @@ -744,8 +744,8 @@ "Enter Tavily API Key": "Entrez la clé API Tavily", "Enter Tavily Extract Depth": "Entrez la profondeur d'extraction de Tavily", "Enter the public URL of your WebUI. This URL will be used to generate links in the notifications.": "Entrez l'URL publique de votre WebUI. Cette URL sera utilisée pour générer des liens dans les notifications.", - "Enter the URL of the function to import": "Entrez l'url de la fonction à importer", - "Enter the URL to import": "Entrer l'url à importer", + "Enter the URL of the function to import": "Entrez l'URL de la fonction à importer", + "Enter the URL to import": "Entrez l'URL à importer", "Enter Tika Server URL": "Entrez l'URL du serveur Tika", "Enter timeout in seconds": "Entrez le délai d'expiration en secondes", "Enter to Send": "Taper entrer pour envoyer", @@ -758,9 +758,9 @@ "Enter Yacy Password": "Entrez le mot de passe Yacy", "Enter Yacy URL (e.g. http://yacy.example.com:8090)": "Entrez l'URL Yacy (par ex. http://yacy.example.com:8090)", "Enter Yacy Username": "Entrez le nom d'utilisateur Yacy", - "Enter Yandex Web Search API Key": "", - "Enter Yandex Web Search URL": "", - "Enter You.com API Key": "", + "Enter Yandex Web Search API Key": "Entrez la clé API de Yandex Web Search", + "Enter Yandex Web Search URL": "Entrez l'URL Yandex Web Search", + "Enter You.com API Key": "Entrez la clé API You.com", "Enter your code here...": "Saisissez votre code ici...", "Enter your current password": "Entrez votre mot de passe actuel", "Enter Your Email": "Entrez votre adresse e-mail", @@ -783,10 +783,10 @@ "Error starting recording.": "Erreur lors du démarrage de l'enregistrement", "Error unloading model: {{error}}": "Erreur lors du déchargement du modèle : {{error}}", "Error uploading file: {{error}}": "Erreur de téléversement du fichier : {{error}}", - "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", - "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Erreur : l'identifiant du modèle ne peut pas être vide. Veuillez saisir un identifiant valide pour continuer.", + "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Erreur : Un modèle avec l'ID '{{modelId}}' existe déjà. Veuillez sélectionner un ID différent pour continuer.", + "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Erreur : l'ID du modèle ne peut pas être vide. Veuillez saisir un ID valide pour continuer.", "Evaluations": "Évaluations", - "Exa API Key": "Clé d'Exa API", + "Exa API Key": "Clé API Exa", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Exemple: (&(objectClass=inetOrgPerson)(uid=%s))", "Example: ALL": "Exemple: TOUS", "Example: mail": "Exemple: mail", @@ -801,7 +801,7 @@ "Experimental": "Expérimental", "Explain": "Explique", "Explore the cosmos": "Explorer le cosmos", - "Export": "Exportation", + "Export": "Exporter", "Export All Archived Chats": "Exporter toutes les conversations archivées", "Export All Chats (All Users)": "Exporter toutes les conversations (de tous les utilisateurs)", "Export chat (.json)": "Exporter la conversation (.json)", @@ -825,7 +825,7 @@ "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Échec de la connexion au serveur d'outils OpenAPI {{URL}}", - "Failed to connect to {{URL}} terminal server": "", + "Failed to connect to {{URL}} terminal server": "Échec de la connexion au serveur de terminal {{URL}}", "Failed to copy link": "Échec de la copie du lien", "Failed to create API Key.": "Échec de la création de la clé API.", "Failed to delete note": "Échec de la délétion de la note", @@ -848,7 +848,7 @@ "Failed to save connections": "Échec de la sauvegarde des connexions", "Failed to save conversation": "Échec de la sauvegarde de la conversation", "Failed to save models configuration": "Échec de la sauvegarde de la configuration des modèles", - "Failed to save terminal servers": "", + "Failed to save terminal servers": "Échec de la sauvegarde des serveurs de terminal", "Failed to unshare chat.": "", "Failed to update settings": "Échec de la mise à jour des réglages", "Failed to update status": "Échec de la mise à jour du statut", @@ -857,8 +857,8 @@ "Features Permissions": "Autorisations des fonctionnalités", "February": "Février", "Feedback": "", - "Feedback Activity": "", - "Feedback deleted successfully": "", + "Feedback Activity": "Retours utilisateurs", + "Feedback deleted successfully": "Avis supprimé avec succès", "Feedback Details": "Détails du retour d'information", "Feedback History": "Historique des avis", "Feel free to add specific details": "N'hésitez pas à ajouter des détails spécifiques", @@ -870,16 +870,16 @@ "File content": "", "File content updated successfully.": "Contenu du fichier mis à jour avec succès.", "File Context": "", - "File deleted successfully.": "", + "File deleted successfully.": "Fichier supprimé avec succès.", "File Mode": "Mode fichier", - "File name": "", + "File name": "Nom du fichier", "File not found.": "Fichier introuvable.", "File removed successfully.": "Fichier supprimé avec succès.", "File size should not exceed {{maxSize}} MB.": "La taille du fichier ne doit pas dépasser {{maxSize}} Mo.", "File Upload": "Téléversement du fichier", "File uploaded successfully": "Fichier téléversé avec succès", "File uploaded!": "Fichier téléversé !", - "Filename": "", + "Filename": "Nom du fichier", "Files": "Fichiers", "Filter": "Filtre", "Filter is now globally disabled": "Le filtre est maintenant désactivé globalement", @@ -890,7 +890,7 @@ "Firecrawl API Key": "Clé de l'API Firecrawl", "Firecrawl Timeout (s)": "", "Floating Quick Actions": "Actions rapides flottantes", - "Focus Chat Input": "", + "Focus Chat Input": "Activer la zone de saisie", "Folder": "Dossier", "Folder Background Image": "Image d'arrière-plan du dossier", "Folder deleted successfully": "Dossier supprimé avec succès", @@ -898,17 +898,17 @@ "Folder name": "", "Folder Name": "Nom du dossier", "Folder name cannot be empty.": "Le nom du dossier ne peut pas être vide.", - "Folder name updated successfully": "Le nom du dossier a été mis à jour avec succès", + "Folder name updated successfully": "Nom du dossier mis à jour avec succès", "Folder options": "", - "Folder updated successfully": "Le dossier a été mis à jour avec succès", + "Folder updated successfully": "Dossier mis à jour avec succès", "Folders": "Dossiers", "Follow up": "Suivi", "Follow Up Generation": "Suivi de la génération", - "Follow Up Generation Prompt": "Suivi de la génération du protompt", - "Follow up: {{question}}": "", + "Follow Up Generation Prompt": "Suivi de la génération du prompt", + "Follow up: {{question}}": "Relance : {{question}}", "Follow-Up Auto-Generation": "Suivi de l'auto-génération", "Followed instructions perfectly": "A parfaitement suivi les instructions", - "for placeholders": "", + "for placeholders": "pour les variables dynamiques", "Force OCR": "Forcer l'OCR", "Force OCR on all pages of the PDF. This can lead to worse results if you have good text in your PDFs. Defaults to False.": "Forcer l'OCR sur toutes les pages du PDF. Cela peut entraîner de moins bons résultats si vous avez du texte de bonne qualité dans vos PDF. La valeur par défaut est False.", "Forge new paths": "Créer de nouveaux chemins", @@ -921,31 +921,31 @@ "Full Context Mode": "Mode avec injection complète dans le Context", "Function": "Fonction", "Function Calling": "Appel de fonction", - "Function created successfully": "La fonction a été créée avec succès", + "Function created successfully": "Fonction créée avec succès", "Function deleted successfully": "Fonction supprimée avec succès", "Function Description": "Description de la fonction", "Function ID": "ID de la fonction", - "Function imported successfully": "Import de la fonction réalisé", + "Function imported successfully": "Fonction importée avec succès", "Function is now globally disabled": "La fonction est désormais globalement désactivée", "Function is now globally enabled": "La fonction est désormais globalement activée", "Function Name": "Nom de la fonction", "Function Name Filter List": "", - "Function updated successfully": "La fonction a été mise à jour avec succès", + "Function updated successfully": "Fonction mise à jour avec succès", "Functions": "Fonctions", "Functions allow arbitrary code execution.": "Les fonctions permettent l'exécution de code arbitraire.", "Functions imported successfully": "Fonctions importées avec succès", "Gemini": "Gemini", - "Gemini API Key": "", + "Gemini API Key": "Clé API Gemini", "Gemini API Key is required.": "La clé d'API de Gemini est requise", - "Gemini Base URL": "", - "Gemini Endpoint Method": "", + "Gemini Base URL": "URL de base Gemini", + "Gemini Endpoint Method": "Méthode de l'endpoint Gemini", "Gender": "Genre", "General": "Général", - "Generate": "Génére", + "Generate": "Génère", "Generate an image": "Génère une image", - "Generate and edit images": "", - "Generate Message Pair": "", - "Generated Image": "", + "Generate and edit images": "Créer et modifier des images", + "Generate Message Pair": "Générer une paire de messages", + "Generated Image": "Image générée", "Generated images will appear here": "", "Generating search query": "Génération d'une requête de recherche", "Generating...": "Génération en cours...", @@ -953,16 +953,16 @@ "Get information on {{name}} in the UI": "Obtenir des informations sur {{name}} dans l'interface utilisateur", "Get started": "Démarrer", "Get started with {{WEBUI_NAME}}": "Démarrez avec {{WEBUI_NAME}}", - "Global": "Globale", + "Global": "Global", "Good Response": "Bonne réponse", - "Google": "", + "Google": "Google", "Google Drive": "Google Drive", "Google PSE API Key": "Clé API Google PSE", "Google PSE Engine Id": "ID du moteur de recherche PSE de Google", "Gravatar": "", - "Grid": "", - "Grokipedia": "", - "Group Channel": "", + "Grid": "Grille", + "Grokipedia": "Grokipedia", + "Group Channel": "Canal de groupe", "Group created successfully": "Groupe créé avec succès", "Group deleted successfully": "Groupe supprimé avec succès", "Group Description": "Description du groupe", @@ -979,12 +979,12 @@ "Height": "Hauteur", "Hello, {{name}}": "Bonjour, {{name}}.", "Help": "Aide", - "Help the community discover great models": "", + "Help the community discover great models": "Aidez la communauté à découvrir les meilleurs modèles", "Hex Color": "Couleur Hex", "Hex Color - Leave empty for default color": "Couleur Hex - Laissez vide pour la couleur par défaut", "Hidden": "", "Hide": "Cacher", - "Hide All": "", + "Hide All": "Masquer tout", "Hide from Sidebar": "Cacher de la barre latérale", "Hide Model": "Cache le Model", "High": "Elevé", @@ -1010,10 +1010,10 @@ "Image Compression": "Compression d'image", "Image Compression Height": "Compression de la hauteur de l'image", "Image Compression Width": "Compression de la largeur de l'image", - "Image Edit": "", - "Image Edit Engine": "", - "Image Generation": "Génération d'images", - "Image Generation Engine": "Moteur de génération d'images", + "Image Edit": "Modification d'image", + "Image Edit Engine": "Moteur de modification d'image", + "Image Generation": "Génération d'image", + "Image Generation Engine": "Moteur de génération d'image", "Image Max Compression Size": "Taille maximale de compression d'image", "Image Max Compression Size height": "Taille maximale de compression d'image (hauteur)", "Image Max Compression Size width": "Taille maximale de compression d'image (largeur)", @@ -1032,8 +1032,8 @@ "Important Update": "Mise à jour importante", "Inactive": "", "Include": "Inclure", - "Include `--api-auth` flag when running stable-diffusion-webui": "Inclure le drapeau `--api-auth` lors de l'exécution de stable-diffusion-webui", - "Include `--api` flag when running stable-diffusion-webui": "Inclure le drapeau `--api` lorsque vous exécutez stable-diffusion-webui", + "Include `--api-auth` flag when running stable-diffusion-webui": "Inclure le flag `--api-auth` lors de l'exécution de stable-diffusion-webui", + "Include `--api` flag when running stable-diffusion-webui": "Inclure le flag `--api` lors de l'exécution de stable-diffusion-webui", "Includes SharePoint": "Inclut SharePoint", "Increase UI Scale": "", "Influences how quickly the algorithm responds to feedback from the generated text. A lower learning rate will result in slower adjustments, while a higher learning rate will make the algorithm more responsive.": "Influe sur la rapidité avec laquelle l'algorithme répond aux retours d'information du texte généré. Un taux d'apprentissage plus bas entraînera des ajustements plus lents, tandis qu'un taux d'apprentissage plus élevé rendra l'algorithme plus réactif.", @@ -1041,8 +1041,8 @@ "Initials": "Initiales", "Inject file content into conversation context": "", "Inject the entire content as context for comprehensive processing, this is recommended for complex queries.": "Injecter l'ensemble du contenu comme contexte pour un traitement complet, recommandé pour les requêtes complexes.", - "Input": "", - "Input Key (e.g. text, unet_name, steps)": "", + "Input": "Entrée", + "Input Key (e.g. text, unet_name, steps)": "Clé de la variable d'entrée (par ex. text, unet_name, steps)", "Input Variables": "Variables d'entrée", "Insert": "Insérer", "Insert Follow-Up Prompt to Input": "", @@ -1057,7 +1057,7 @@ "Invalid file content": "Contenu de fichier invalide", "Invalid file format.": "Format de fichier non valide.", "Invalid JSON file": "Fichier JSON non valide", - "Invalid JSON format for ComfyUI Edit Workflow.": "", + "Invalid JSON format for ComfyUI Edit Workflow.": "Format JSON non valide pour le workflow ComfyUI de modification d'image.", "Invalid JSON format for ComfyUI Workflow.": "Format JSON non valide pour le workflow ComfyUI.", "Invalid JSON format for Parameters": "", "Invalid JSON format in {{NAME}}": "", @@ -1071,7 +1071,7 @@ "join our Discord for help.": "Rejoignez notre Discord pour obtenir de l'aide.", "JSON": "JSON", "JSON Preview": "Aperçu JSON", - "JSON Spec": "", + "JSON Spec": "Spécification JSON", "July": "Juillet", "June": "Juin", "Jupyter Auth": "Auth Jupyter", @@ -1084,7 +1084,7 @@ "Key": "Clé", "Key is required": "La clé est requise", "Keyboard shortcuts": "Raccourcis clavier", - "Keyboard Shortcuts": "", + "Keyboard Shortcuts": "Raccourcis clavier", "Knowledge": "Connaissances", "Knowledge Access": "Accès aux connaissances", "Knowledge Base": "Base de connaissances", @@ -1103,13 +1103,13 @@ "Landing Page Mode": "Mode de la page d'accueil", "Language": "Langue", "Language Locales": "Réglages régionaux de langue", - "Last 24 hours": "", - "Last 30 days": "", - "Last 7 days": "", - "Last 90 days": "", + "Last 24 hours": "Dernières 24 heures", + "Last 30 days": "30 derniers jours", + "Last 7 days": "7 derniers jours", + "Last 90 days": "90 derniers jours", "Last Active": "Dernière activité", "Last Modified": "Dernière modification", - "Last reply": "Déernière réponse", + "Last reply": "Dernière réponse", "LDAP": "LDAP", "LDAP server updated": "Serveur LDAP mis à jour", "Leaderboard": "Classement", @@ -1118,7 +1118,7 @@ "Learn more about Open Terminal": "", "Learn more about OpenAPI tool servers.": "En savoir plus sur les serveurs d'outils OpenAPI.", "Learn more about Voxtral transcription.": "", - "Leave a public review for {{modelName}}": "", + "Leave a public review for {{modelName}}": "Laisser un avis public pour {{modelName}}", "Leave empty for no compression": "Laisser vide pour ne pas compresser", "Leave empty for unlimited": "Laissez vide pour illimité", "Leave empty to include all models from \"{{url}}\" endpoint": "Laissez vide pour inclure tous les modèles de l'endpoint \"{{url}}\"", @@ -1137,7 +1137,7 @@ "Light": "Clair", "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", "Limits the number of concurrent embedding requests. Set to 0 for unlimited.": "", - "List": "", + "List": "Liste", "Listening...": "Écoute en cours...", "Live": "", "Llama.cpp": "Llama.cpp", @@ -1159,7 +1159,7 @@ "Manage": "Gérer", "Manage Connections": "", "Manage Direct Connections": "Gérer les connexions directes", - "Manage Files": "", + "Manage Files": "Gérer les fichiers", "Manage Models": "Gérer les modèles", "Manage Ollama": "Gérer Ollama", "Manage Ollama API Connections": "Gérer les connexions API Ollama", @@ -1169,29 +1169,29 @@ "Manage your account information.": "Gérez les informations de votre compte.", "March": "Mars", "Markdown": "Markdown", - "Markdown Header Text Splitter": "", + "Markdown Header Text Splitter": "Découpage par en-têtes markdown", "Max Speakers": "Nombre maximal d'intervenants", "Max Upload Count": "Nombre maximal de téléversements", "Max Upload Size": "Limite de taille de téléversement", - "Maximum number of files allowed per folder.": "", - "Maximum number of files per folder is {{max}}.": "", + "Maximum number of files allowed per folder.": "Nombre maximum de fichiers autorisés par dossier.", + "Maximum number of files per folder is {{max}}.": "Le nombre maximum de fichiers par dossier est de {{max}}.", "Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Un maximum de 3 modèles peut être téléchargé en même temps. Veuillez réessayer ultérieurement.", "May": "Mai", "MBR": "", "MCP": "", "MCP support is experimental and its specification changes often, which can lead to incompatibilities. OpenAPI specification support is directly maintained by the Open WebUI team, making it the more reliable option for compatibility.": "", "Medium": "Moyen", - "Member removed successfully": "", - "members": "", - "Members": "", - "Members added successfully": "", + "Member removed successfully": "Membre supprimé avec succès", + "members": "membres", + "Members": "Membres", + "Members added successfully": "Membres ajoutés avec succès", "Memories": "", "Memories accessible by LLMs will be shown here.": "Les souvenirs accessibles par les LLMs seront affichées ici.", "Memory": "Mémoire", - "Memory added successfully": "Souvenir ajoutée avec succès", - "Memory cleared successfully": "La mémoire a été effacée avec succès", - "Memory deleted successfully": "Le souvenir a été supprimé avec succès", - "Memory updated successfully": "Le souvenir a été mis à jour avec succès", + "Memory added successfully": "Souvenir ajouté avec succès", + "Memory cleared successfully": "Souvenir effacé avec succès", + "Memory deleted successfully": "Souvenir supprimé avec succès", + "Memory updated successfully": "Souvenir mis à jour avec succès", "Merge Responses": "Fusionner les réponses", "Merged Response": "Réponse fusionnée", "Message": "", @@ -1213,7 +1213,7 @@ "Model '{{modelName}}' has been successfully downloaded.": "Le modèle '{{modelName}}' a été téléchargé avec succès.", "Model '{{modelTag}}' is already in queue for downloading.": "Le modèle '{{modelTag}}' est déjà dans la file d'attente pour le téléchargement.", "Model {{modelId}} not found": "Modèle {{modelId}} introuvable", - "Model {{modelName}} is not vision capable": "Le modèle {{modelName}} n'a pas de capacités visuelles", + "Model {{modelName}} is not vision capable": "Le modèle {{modelName}} n'a pas de fonctionnalité de vision", "Model {{name}} is now {{status}}": "Le modèle {{name}} est désormais {{status}}.", "Model {{name}} is now hidden": "Le modèle {{name}} est maintenant masqué", "Model {{name}} is now visible": "Le modèle {{name}} est maintenant visible", @@ -1222,8 +1222,8 @@ "Model can execute code and perform calculations": "Le modèle peut executer du code et faire des calculs", "Model can generate images based on text prompts": "Le modèle peut générer des images à partir des prompts textuels", "Model can search the web for information": "Le modèle peut faire des recherches sur internet pour trouver des informations", - "Model Capabilities": "", - "Model created successfully!": "Le modèle a été créé avec succès !", + "Model Capabilities": "Capacités du modèle", + "Model created successfully!": "Modèle créé avec succès !", "Model filesystem path detected. Model shortname is required for update, cannot continue.": "Chemin du système de fichiers de modèle détecté. Le nom court du modèle est requis pour la mise à jour, l'opération ne peut pas être poursuivie.", "Model Filtering": "Filtrage de modèle", "Model ID": "ID du modèle", @@ -1238,16 +1238,16 @@ "Model Parameters": "", "Model Params": "Réglages du modèle", "Model Permissions": "Autorisations du modèle", - "Model responses or outputs": "", - "Model unloaded successfully": "Le modèle a été déchargé avec succès", - "Model updated successfully": "Le modèle a été mis à jour avec succès", + "Model responses or outputs": "Les réponses des modèles", + "Model unloaded successfully": "Modèle déchargé avec succès", + "Model updated successfully": "Modèle mis à jour avec succès", "Model Usage": "", "Model(s) do not support file upload": "Le(s) modèle(s) ne supportent pas le téléversement de fichiers", "Modelfile Content": "Contenu du Fichier de Modèle", "Models": "Modèles", "Models Access": "Accès aux modèles", "Models configuration saved successfully": "Configuration des modèles enregistrée avec succès", - "Models imported successfully": "", + "Models imported successfully": "Modèle importé avec succès", "Models Public Sharing": "Partage public des modèles", "Models Sharing": "Partage des modèles", "Mojeek": "", @@ -1258,9 +1258,9 @@ "More Options": "Plus d'options", "Move": "Déplacer", "Moved {{name}}": "", - "My Terminal": "", + "My Terminal": "Mon terminal", "Name": "Nom d'utilisateur", - "Name and ID are required, please fill them out": "Le nom et l'identifiant sont obligatoires, veuillez les remplir", + "Name and ID are required, please fill them out": "Le nom et l'ID sont obligatoires, veuillez les remplir", "Name your knowledge base": "Nommez votre base de connaissances", "Native": "Natif", "New": "", @@ -1269,21 +1269,21 @@ "New File": "", "New Folder": "Nouveau dossier", "New Function": "Nouvelle fonction", - "New Group": "", - "New Knowledge": "", - "New Model": "", - "New Note": "", + "New Group": "Nouveau groupe", + "New Knowledge": "Nouvelle connaissance", + "New Model": "Nouveau modèle", + "New Note": "Nouvelle note", "New Password": "Nouveau mot de passe", - "New Prompt": "", - "New Skill": "", - "New Temporary Chat": "", - "New Terminal": "", + "New Prompt": "Nouveau prompt", + "New Skill": "Nouveau skill", + "New Temporary Chat": "Nouvelle conversation temporaire", + "New Terminal": "Nouveau terminal", "New Tool": "Nouvel outil", "New Webhook": "", "new-channel": "nouveau-canal", "Next message": "Message suivant", "No access grants. Private to you.": "", - "No activity data": "", + "No activity data": "Aucune activité", "No authentication": "Aucune authentification", "No chats found": "Aucune discussion trouvée", "No chats found for this user.": "Pas de conversation trouvée pour cet utilisateur.", @@ -1299,46 +1299,46 @@ "No feedback found": "", "No file selected": "Aucun fichier sélectionné", "No files found": "", - "No files in this knowledge base.": "", + "No files in this knowledge base.": "Aucun fichier dans cette base de connaissances.", "No functions found": "", "No groups found": "", - "No history available": "", + "No history available": "Aucun historique disponible", "No HTML, CSS, or JavaScript content found.": "Aucun contenu HTML, CSS ou JavaScript trouvé.", "No inference engine with management support found": "Aucun moteur d'inférence avec support trouvé", "No knowledge bases found.": "", "No knowledge found": "Aucune connaissance trouvée", "No memories to clear": "Aucun souvenir à effacer", "No model IDs": "Aucun ID de modèle", - "No models available": "", + "No models available": "Aucun modèle disponible", "No models found": "Aucun modèle trouvé", "No models selected": "Aucun modèle sélectionné", "No Notes": "Pas de note", "No notes found": "Aucune note trouvée", - "No one": "", + "No one": "Personne", "No pinned messages": "", - "No prompts found": "", + "No prompts found": "Aucun prompt trouvé", "No results": "Aucun résultat trouvé", "No results found": "Aucun résultat trouvé", "No search query generated": "Aucune requête de recherche générée", - "No skills found": "", + "No skills found": "Aucun skill trouvé", "No source available": "Aucune source n'est disponible", "No sources found": "Aucune source trouvée", "No suggestion prompts": "Aucun prompt suggéré", - "No Terminal connection configured.": "", - "No terminal connections configured.": "", - "No tool server connections configured.": "", - "No tools found": "", + "No Terminal connection configured.": "Aucune connexion à un terminal configurée.", + "No terminal connections configured.": "Aucune connexion à un terminal configurée.", + "No tool server connections configured.": "Aucune connexion à un serveur d'outils configurée.", + "No tools found": "Aucun outil trouvé", "No users were found.": "Aucun utilisateur trouvé.", - "No valves": "", + "No valves": "Aucune vanne trouvée", "No valves to update": "Aucune vanne à mettre à jour", - "No webhooks yet": "", - "Node Ids": "", + "No webhooks yet": "Aucun webhook trouvé", + "Node Ids": "ID des noeuds", "None": "Aucun", "Not factually correct": "Non factuellement correct", "Not helpful": "Pas utile", "Not Registered": "", "Note": "Note", - "Note deleted successfully": "Suppression de la note effective", + "Note deleted successfully": "Note supprimée avec succès", "Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "Note : Si vous définissez un score minimum, seuls les documents ayant un score supérieur ou égal à ce score minimum seront retournés par la recherche.", "Notes": "Notes", "Notes Public Sharing": "", @@ -1361,14 +1361,14 @@ "Ollama Version": "Version d'Ollama", "On": "Activé", "OneDrive": "OneDrive", - "Only active when \"Paste Large Text as File\" setting is toggled on.": "", - "Only active when the chat input is in focus and an LLM is generating a response.": "", - "Only active when the chat input is in focus.": "", + "Only active when \"Paste Large Text as File\" setting is toggled on.": "Uniquement lorsque le paramètre \"Coller un texte volumineux comme fichier\" est activé.", + "Only active when the chat input is in focus and an LLM is generating a response.": "Uniquement lorsque la zone de saisie de la conversation est active et qu'un LLM génère une réponse.", + "Only active when the chat input is in focus.": "Uniquement lorsque la zone de saisie de la conversation est active.", "Only alphanumeric characters and hyphens are allowed": "Seuls les caractères alphanumériques et les tirets sont autorisés", "Only alphanumeric characters and hyphens are allowed in the command string.": "Seuls les caractères alphanumériques et les tirets sont autorisés dans la chaîne de commande.", "Only can be triggered when the chat input is in focus.": "", - "Only collections can be edited, create a new knowledge base to edit/add documents.": "Seules les collections peuvent être modifiées, créez une nouvelle base de connaissance pour modifier/ajouter des documents.", - "Only invited users can access": "", + "Only collections can be edited, create a new knowledge base to edit/add documents.": "Seules les collections peuvent être modifiées, créez une nouvelle base de connaissances pour modifier/ajouter des documents.", + "Only invited users can access": "Limité aux utilisateurs sélectionnés", "Only markdown files are allowed": "Seul les fichiers markdown sont autorisés", "Only select users and groups with permission can access": "Seuls les utilisateurs et groupes autorisés peuvent accéder", "Only sync new/updated chats": "", @@ -1382,31 +1382,31 @@ "Open modal to configure connection": "Ouvrir la fenêtre modale pour configurer la connexion", "Open Modal To Manage Floating Quick Actions": "", "Open Modal To Manage Image Compression": "", - "Open Model Selector": "", - "Open Settings": "", + "Open Model Selector": "Ouvrir la liste des modèles", + "Open Settings": "Ouvrir les réglages", "Open Sidebar": "Ouvrir la barre latérale", - "Open Terminal": "", + "Open Terminal": "Open Terminal", "Open User Profile Menu": "Ouvrir le menu du profil utilisateur", "Open WebUI can use tools provided by any OpenAPI server.": "Open WebUI peut utiliser les outils fournis par n'importe quel serveur OpenAPI.", "Open WebUI uses faster-whisper internally.": "Open WebUI utilise faster-whisper en interne.", "Open WebUI uses SpeechT5 and CMU Arctic speaker embeddings.": "Open WebUI utilise SpeechT5 et les embeddings de locuteur CMU Arctic.", - "Open WebUI version": "", + "Open WebUI version": "Version d'Open WebUI", "Open WebUI version (v{{OPEN_WEBUI_VERSION}}) is lower than required version (v{{REQUIRED_VERSION}})": "La version Open WebUI (v{{OPEN_WEBUI_VERSION}}) est inférieure à la version requise (v{{REQUIRED_VERSION}})", "OpenAI": "OpenAI", "OpenAI API": "API compatibles OpenAI", - "OpenAI API Base URL": "", - "OpenAI API Key": "", - "OpenAI API Key is required.": "Une clé API OpenAI est requise.", + "OpenAI API Base URL": "URL de base de l'API OpenAI", + "OpenAI API Key": "Clé API OpenAI", + "OpenAI API Key is required.": "Une clé d'API OpenAI est requise.", "OpenAI API settings updated": "Réglages de l'API OpenAI mis à jour", - "OpenAI API Version": "", + "OpenAI API Version": "Version de l'API OpenAI", "OpenAI URL/Key required.": "URL/Clé OpenAI requise.", - "OpenAPI": "", - "OpenAPI Spec": "", + "OpenAPI": "OpenAPI", + "OpenAPI Spec": "Spécification OpenAPI", "openapi.json URL or Path": "URL ou chemin openapi.json", - "optional": "", + "optional": "optionnel", "Optional": "Facultatif", "or": "ou", - "Ordered List": "Liste ordonnéee", + "Ordered List": "Liste ordonnée", "Other": "Autre", "Output": "", "OUTPUT": "SORTIE", @@ -1414,12 +1414,12 @@ "Output Format": "Format de sortie", "Overview": "Aperçu", "page": "page", - "Page": "", - "Page mode creates one document per page. Single mode combines all pages into one document for better chunking across page boundaries.": "", + "Page": "Page", + "Page mode creates one document per page. Single mode combines all pages into one document for better chunking across page boundaries.": "Le mode Page crée un document par page. Le mode Unique combine toutes les pages en un seul document pour une meilleure segmentation à travers les limites de page.", "Paginate": "Paginer", "Parameters": "Réglages", "Parent message not found": "", - "Participate in community leaderboards and evaluations! Syncing aggregated usage stats helps drive research and improvements to Open WebUI. Your privacy is paramount: no message content is ever shared.": "", + "Participate in community leaderboards and evaluations! Syncing aggregated usage stats helps drive research and improvements to Open WebUI. Your privacy is paramount: no message content is ever shared.": "Participez aux classements et évaluations de la communauté ! La synchronisation des statistiques d'utilisation agrégées contribue à l'amélioration d'Open WebUI. Votre vie privée est primordiale : aucun contenu de message n'est jamais partagé.", "Password": "Mot de passe", "Passwords do not match.": "Les mots de passe ne correspondent pas.", "Paste Large Text as File": "Coller un texte volumineux comme fichier", @@ -1434,19 +1434,19 @@ "Permission denied when accessing microphone": "Accès au microphone refusé", "Permission denied when accessing microphone: {{error}}": "Accès au microphone refusé : {{error}}", "Permissions": "Permissions", - "Perplexity API Key": "Clé d'API de Perplexity", + "Perplexity API Key": "Clé API Perplexity", "Perplexity Model": "Modèle de Perplexity", - "Perplexity Search API URL": "", + "Perplexity Search API URL": "URL de l'API Perplexity Search", "Perplexity Search Context Usage": "Utilisation du contexte de recherche de Perplexity", "Personalization": "Personnalisation", "Pin": "Épingler", "Pinned": "Épinglé", - "Pinned Messages": "", - "Pinned Models": "", + "Pinned Messages": "Messages épinglés", + "Pinned Models": "Modèles épinglés", "Pioneer insights": "Explorer de nouvelles perspectives", "Pipe": "Pipeline", - "Pipeline deleted successfully": "Le pipeline a été supprimé avec succès", - "Pipeline downloaded successfully": "Le pipeline a été téléchargé avec succès", + "Pipeline deleted successfully": "Pipeline supprimée avec succès", + "Pipeline downloaded successfully": "Pipeline téléchargée avec succès", "Pipelines": "", "Pipelines are a plugin system with arbitrary code execution —": "Pipelines est un système de plug‑ins permettant l’exécution arbitraire de code —", "Pipelines Not Detected": "Aucun pipelines détecté", @@ -1472,20 +1472,20 @@ "Please select a model.": "Veuillez sélectionner un modèle.", "Please select a reason": "Veuillez sélectionner une raison", "Please select a valid JSON file": "", - "Please select at least one user for Direct Message channel.": "", + "Please select at least one user for Direct Message channel.": "Veuillez sélectionner au moins un utilisateur pour un canal de message direct.", "Please wait until all files are uploaded.": "Veuillez patienter jusqu'à ce que tous les fichiers soient téléchargés.", "Port": "Port", "Positive attitude": "Attitude positive", "Prefer not to say": "Je préfère ne pas répondre", "Prefix ID": "ID de préfixe", "Prefix ID is used to avoid conflicts with other connections by adding a prefix to the model IDs - leave empty to disable": "Le préfixe ID est utilisé pour éviter les conflits avec d'autres connexions en ajoutant un préfixe aux ID de modèle - laissez vide pour désactiver", - "Prevent File Creation": "", + "Prevent File Creation": "Empêcher la création de fichier", "Preview": "Aperçu", "Previous 30 days": "30 derniers jours", "Previous 7 days": "7 derniers jours", "Previous message": "Message précédent", "Private": "Privé", - "Private conversation between selected users": "", + "Private conversation between selected users": "Conversation privée entre les utilisateurs sélectionnés", "Production version updated": "", "Profile": "Profil", "Prompt": "Prompt", @@ -1508,7 +1508,7 @@ "Querying": "Requête en cours", "Quick Actions": "Actions rapide", "RAG Template": "Modèle RAG", - "Rate {{rating}} out of 10": "", + "Rate {{rating}} out of 10": "Noter {{rating}} sur 10", "Rating": "Note", "Re-rank models by topic similarity": "Reclasser les modèles par similarité de sujet", "Read": "Lire", @@ -1528,15 +1528,15 @@ "Refresh": "", "Refused when it shouldn't have": "Refusé alors qu'il n'aurait pas dû l'être", "Regenerate": "Regénérer", - "Regenerate Menu": "Menu Régénérer", - "Regenerate Response": "", + "Regenerate Menu": "Menu Regénérer", + "Regenerate Response": "Regénérer la réponse", "Register Again": "", "Register Client": "", "Registered": "", "Registration failed": "", "Registration successful": "", "Reindex": "Réindexer", - "Reindex Knowledge Base Vectors": "Réindexer les vecteurs de la base de connaissance", + "Reindex Knowledge Base Vectors": "Réindexer les vecteurs de la base de connaissances", "Release Notes": "Notes de mise à jour", "Releases": "Livraisons", "Relevance": "Pertinence", @@ -1547,13 +1547,13 @@ "Remove action": "", "Remove file": "Retirer le fichier", "Remove File": "Retirer le fichier", - "Remove from favorites": "", + "Remove from favorites": "Retirer des favoris", "Remove image": "Retirer l'image", "Remove Model": "Retirer le modèle", "Rename": "Renommer", "Render Markdown in Previews": "", "Reorder Models": "Réorganiser les modèles", - "Reply": "", + "Reply": "Répondre", "Reply in Thread": "Répondre dans le fil de discussion", "Reply to thread...": "", "Replying to {{NAME}}": "", @@ -1620,7 +1620,7 @@ "Search options": "Options de recherche", "Search Prompts": "Rechercher des prompts", "Search Result Count": "Nombre de résultats de recherche", - "Search Skills": "", + "Search Skills": "Rechercher des skills", "Search the internet": "Cherche sur Internet", "Search the web and fetch URLs": "", "Search Tools": "Rechercher des outils", @@ -1638,7 +1638,7 @@ "See what's new": "Découvrez les nouvelles fonctionnalités", "Seed": "Seed", "Select": "Choisir", - "Select {{modelName}} model": "", + "Select {{modelName}} model": "Sélectionner le modèle {{modelName}}", "Select a base model": "Sélectionnez un modèle de base", "Select a base model (e.g. llama3, gpt-4o)": "Chosir un modèle de base (ex : lamma3, gpt-4o)", "Select a conversation to preview": "Choisir une conversation pour la prévisualiser", @@ -1666,12 +1666,12 @@ "Select Engine": "Sélectionnez le moteur", "Select how to split message text for TTS requests": "Sélectionnez comment diviser le texte du message pour les requêtes TTS", "Select Knowledge": "Sélectionnez une connaissance", - "Select Method": "", + "Select Method": "Sélectionner une méthode", "Select only one model to call": "Sélectionnez seulement un modèle pour appeler", "Select view": "", "Selected model: {{modelName}}": "", "Selected model(s) do not support image inputs": "Les modèle(s) sélectionné(s) ne prennent pas en charge les entrées d'images", - "Selected Models": "", + "Selected Models": "Modèles sélectionnés par défaut", "semantic": "sémantique", "Send": "Envoyer", "Send a Message": "Envoyer un message", @@ -1679,7 +1679,7 @@ "Send now": "", "Sends `stream_options: { include_usage: true }` in the request.\nSupported providers will return token usage information in the response when set.": "Envoie `stream_options: { include_usage: true }` dans la requête.\nLes fournisseurs pris en charge renverront des informations sur l'utilisation des tokens dans la réponse lorsque cette option est activée.", "September": "Septembre", - "SerpApi API Key": "Clé d'API SerpAPI", + "SerpApi API Key": "Clé API SerpApi", "SerpApi Engine": "Moteur SerpAPI", "Serper API Key": "Clé API Serper", "Serply API Key": "Clé API Serply", @@ -1691,18 +1691,18 @@ "Set embedding model": "Définir le modèle d'embedding", "Set embedding model (e.g. {{model}})": "Définir le modèle d'embedding (par ex. {{model}})", "Set reranking model (e.g. {{model}})": "Définir le modèle de ré-ranking (par ex. {{model}})", - "Set the default models that are automatically selected for all users when a new chat is created.": "", - "Set the models that are automatically pinned to the sidebar for all users.": "", + "Set the default models that are automatically selected for all users when a new chat is created.": "Définit les modèles sélectionnés par défaut pour tous les utilisateurs lorsqu'une nouvelle conversation est créée.", + "Set the models that are automatically pinned to the sidebar for all users.": "Définit les modèles qui sont automatiquement épinglés à la barre latérale pour tous les utilisateurs.", "Set the number of layers, which will be off-loaded to GPU. Increasing this value can significantly improve performance for models that are optimized for GPU acceleration but may also consume more power and GPU resources.": "Définir le nombre de couches qui seront déchargées sur le GPU. Augmenter cette valeur peut améliorer considérablement les performances pour les modèles optimisés pour l'accélération GPU, mais peut également consommer plus d'énergie et de ressources GPU.", "Set the number of worker threads used for computation. This option controls how many threads are used to process incoming requests concurrently. Increasing this value can improve performance under high concurrency workloads but may also consume more CPU resources.": "Définir le nombre de threads de travail utilisés pour le calcul. Cette option contrôle combien de threads sont utilisés pour traiter les demandes entrantes simultanément. L'augmentation de cette valeur peut améliorer les performances sous de fortes charges de travail concurrentes mais peut également consommer plus de ressources CPU.", "Set Voice": "Choisir la voix", "Set whisper model": "Choisir le modèle Whisper", "Set your status": "", - "Sets a flat bias against tokens that have appeared at least once. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 0.9) will be more lenient. At 0, it is disabled.": "Applique un biais uniforme contre les jetons déjà apparus. Une valeur élevée (ex. : 1,5) pénalise fortement les répétitions, une valeur faible (ex. : 0,9) les tolère davantage. À 0, ce réglage est désactivé.", - "Sets a scaling bias against tokens to penalize repetitions, based on how many times they have appeared. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 0.9) will be more lenient. At 0, it is disabled.": "Applique un biais progressif contre les jetons en fonction de leur fréquence d'apparition. Une valeur plus élevée les pénalise davantage ; une valeur plus faible est plus indulgente. À 0, ce réglage est désactivé.", + "Sets a flat bias against tokens that have appeared at least once. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 0.9) will be more lenient. At 0, it is disabled.": "Applique un biais uniforme contre les tokens déjà apparus. Une valeur élevée (ex. : 1,5) pénalise fortement les répétitions, une valeur faible (ex. : 0,9) les tolère davantage. À 0, ce réglage est désactivé.", + "Sets a scaling bias against tokens to penalize repetitions, based on how many times they have appeared. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 0.9) will be more lenient. At 0, it is disabled.": "Applique un biais progressif contre les tokens en fonction de leur fréquence d'apparition. Une valeur plus élevée les pénalise davantage ; une valeur plus faible est plus indulgente. À 0, ce réglage est désactivé.", "Sets how far back for the model to look back to prevent repetition.": "Définit la profondeur de rétrospection du modèle pour éviter les répétitions.", "Sets the random number seed to use for generation. Setting this to a specific number will make the model generate the same text for the same prompt.": "Définit la graine du générateur aléatoire pour produire un résultat déterministe. Une même graine produira toujours la même sortie pour une invite donnée.", - "Sets the size of the context window used to generate the next token.": "Définit la taille de la fenêtre de contexte utilisée pour générer le prochain Token.", + "Sets the size of the context window used to generate the next token.": "Définit la taille de la fenêtre de contexte utilisée pour générer le prochain token.", "Sets the stop sequences to use. When this pattern is encountered, the LLM will stop generating text and return. Multiple stop patterns may be set by specifying multiple separate stop parameters in a modelfile.": "Définit les séquences d'arrêt à utiliser. Lorsque ce motif est rencontré, le LLM cessera de générer du texte et retournera. Plusieurs motifs d'arrêt peuvent être définis en spécifiant plusieurs réglages d'arrêt distincts dans un fichier modèle.", "Setting": "", "Settings": "Réglages", @@ -1713,19 +1713,19 @@ "Share link copied to clipboard.": "", "Share to Open WebUI Community": "Partager avec la communauté OpenWebUI", "Share your background and interests": "Partagez votre parcours et vos intérêts", - "Shared Chats": "", - "Shared with you": "", + "Shared Chats": "Conversations partagées", + "Shared with you": "Partagé avec vous", "Sharing Permissions": "Autorisation de partage", "Show": "Afficher", "Show \"What's New\" modal on login": "Afficher la fenêtre modale \"Quoi de neuf\" lors de la connexion", "Show Admin Details in Account Pending Overlay": "Afficher les coordonnées de l'administrateur aux comptes en attente", - "Show All": "", + "Show All": "Afficher tout", "Show all ({{COUNT}} characters)": "", "Show Files": "", "Show Formatting Toolbar": "Afficher la barre d'outils de formatage", "Show image preview": "Afficher l'aperçu de l'image", - "Show Model": "Afficher le model", - "Show Shortcuts": "", + "Show Model": "Afficher le modèle", + "Show Shortcuts": "Afficher les raccourcis clavier", "Show your support!": "Montrez votre soutien !", "Showcased creativity": "Créativité mise en avant", "Showing all messages (user + assistant) per user.": "", @@ -1737,21 +1737,21 @@ "Sign up to {{WEBUI_NAME}}": "Inscrivez-vous à {{WEBUI_NAME}}", "Significantly improves accuracy by using an LLM to enhance tables, forms, inline math, and layout detection. Will increase latency. Defaults to False.": "", "Signing in to {{WEBUI_NAME}}": "Connexion à {{WEBUI_NAME}}", - "Single": "", + "Single": "Unique", "Sink List": "", "sk-1234": "sk-1234", - "Skill created successfully": "", - "Skill deleted successfully": "", - "Skill Description": "", - "Skill ID": "", - "Skill imported successfully": "", - "Skill Instructions": "", - "Skill Name": "", - "Skill updated successfully": "", - "Skills": "", - "Skills Access": "", - "Skills Public Sharing": "", - "Skills Sharing": "", + "Skill created successfully": "Skill créé avec succès", + "Skill deleted successfully": "Skill supprimé avec succès", + "Skill Description": "Description du skill", + "Skill ID": "ID du skill", + "Skill imported successfully": "Skill importé avec succès", + "Skill Instructions": "Instructions du skill", + "Skill Name": "Nom du skill", + "Skill updated successfully": "Skill mis à jour avec succès", + "Skills": "Skills", + "Skills Access": "Accès aux skills", + "Skills Public Sharing": "Partage public des skills", + "Skills Sharing": "Partage des skills", "Skip Cache": "Ne pas utiliser le cache", "Skip the cache and re-run the inference. Defaults to False.": "Ne pas utiliser le cache et re executer l'inférence. Par defaut à False", "Something went wrong :/": "Quelque chose s'est mal passé :/", @@ -1770,24 +1770,24 @@ "Speech-to-Text": "Reconnaissance vocale", "Speech-to-Text Engine": "Moteur de reconnaissance vocale", "Speech-to-Text Language": "", - "Split documents by markdown headers before applying character/token splitting.": "", - "Start a new conversation": "", + "Split documents by markdown headers before applying character/token splitting.": "Découper les documents par en-têtes markdown avant d'appliquer le découpage par caractères/tokens.", + "Start a new conversation": "Démarrer une nouvelle conversation", "Start of the channel": "Début du canal", "Start Tag": "Balise de départ", "Status": "", - "Status cleared successfully": "", - "Status updated successfully": "", + "Status cleared successfully": "Statut effacé avec succès", + "Status updated successfully": "Statut mis à jour avec succès", "Status Updates": "Mises à jour de statut", "STDOUT/STDERR": "STDOUT/STDERR", - "Steps": "", + "Steps": "Étapes", "Stop": "Stop", "Stop Download": "", - "Stop Generating": "", + "Stop Generating": "Arrêter la génération", "Stop Sequence": "Séquence d'arrêt", "Stream Chat Response": "Streamer la réponse de la conversation", "Stream Delta Chunk Size": "", "Streamable HTTP": "", - "Strikethrough": "", + "Strikethrough": "Barré", "Strip Existing OCR": "Supprimer l'OCR existant", "Strip existing OCR text from the PDF and re-run OCR. Ignored if Force OCR is enabled. Defaults to False.": "Supprimer le texte OCR existant du PDF et réexécuter l'OCR. Ignoré si la fonction Force OCR est activée. Par défaut à False.", "STT Model": "Modèle de Speech-to-Text", @@ -1797,7 +1797,7 @@ "Submit suggestion": "", "Subtitle": "Sous-titre", "Success": "Réussite", - "Successfully imported {{userCount}} users.": "{{userCount}} utilisateurs ont été importés avec succès.", + "Successfully imported {{userCount}} users.": "{{userCount}} utilisateurs importés avec succès.", "Successfully updated.": "Mise à jour réussie.", "Suggest a change": "Proposer un changement", "Suggested": "Suggéré", @@ -1815,12 +1815,12 @@ "System": "Système", "System Instructions": "Instructions système", "System Prompt": "Prompt système", - "Tag": "", - "Tags": "Étiquettes", + "Tag": "Tag", + "Tags": "Tags", "Tags Generation": "Génération de tags", "Tags Generation Prompt": "Prompt de génération de tags", "Tail free sampling is used to reduce the impact of less probable tokens from the output. A higher value (e.g., 2.0) will reduce the impact more, while a value of 1.0 disables this setting.": "Le sampling sans queue est utilisé pour réduire l'impact des tokens moins probables dans la sortie. Une valeur plus élevée (par exemple, 2.0) réduira davantage l'impact, tandis qu'une valeur de 1.0 désactive ce réglage.", - "Talk to Model": "", + "Talk to Model": "Parler au modèle", "Tap to interrupt": "Appuyez pour interrompre", "Task List": "Liste pour les tâches", "Task Model": "Modèle pour les tâches", @@ -1831,9 +1831,9 @@ "Temperature": "Température", "Temporary Chat": "conversation temporaire", "Temporary Chat by Default": "Conversation temporaire par défaut", - "Terminal": "", - "Terminal servers saved": "", - "Text Splitter": "Text Splitter", + "Terminal": "Terminal", + "Terminal servers saved": "Serveurs de terminal sauvegardés", + "Text Splitter": "Découpage du texte", "Text-to-Speech": "Text-to-Speech", "Text-to-Speech Engine": "Moteur de Text-to-Speech", "Thanks for your feedback!": "Merci pour vos commentaires !", @@ -1841,7 +1841,7 @@ "The base to search for users": "La base pour rechercher des utilisateurs", "The batch size determines how many text requests are processed together at once. A higher batch size can increase the performance and speed of the model, but it also requires more memory.": "La taille du lot détermine combien de requêtes texte sont traitées simultanément. Une taille plus grande améliore les performances mais consomme plus de mémoire.", "The developers behind this plugin are passionate volunteers from the community. If you find this plugin helpful, please consider contributing to its development.": "Les développeurs de ce plugin sont des bénévoles passionnés issus de la communauté. Si vous trouvez ce plugin utile, merci de contribuer à son développement.", - "The evaluation leaderboard is based on the Elo rating system and is updated in real-time.": "Le classement d'évaluation est basé sur le système de notation Elo et est mis à jour en temps réel.", + "The evaluation leaderboard is based on the Elo rating system and is updated in real-time.": "Le classement est basé sur le système de notation Elo et est mis à jour en temps réel.", "The format to return a response in. Format can be json or a JSON schema.": "Le format dans lequel la réponse doit être renvoyée. Le format peut être json ou un schéma JSON.", "The height in pixels to compress images to. Leave empty for no compression.": "Hauteur en pixels à laquelle les images doivent être compressées. Laisser vide pour ne pas compresser.", "The language of the input audio. Supplying the input language in ISO-639-1 (e.g. en) format will improve accuracy and latency. Leave blank to automatically detect the language.": "La langue de l'audio d'entrée. Fournir la langue d'entrée au format ISO-639-1 (par ex. en) améliorera la précision et la latence. Laisser vide pour détecter automatiquement la langue.", @@ -1858,7 +1858,7 @@ "The Weight of BM25 Hybrid Search. 0 more semantic, 1 more lexical. Default 0.5": "", "The width in pixels to compress images to. Leave empty for no compression.": "Largeur en pixels à laquelle les images doivent être compressées. Laisser vide pour ne pas compresser.", "Theme": "Thème", - "There was an error syncing your stats. Please try again.": "", + "There was an error syncing your stats. Please try again.": "Une erreur est survenue lors de la synchronisation de vos statistiques. Veuillez réessayer.", "Thinking...": "En train de réfléchir...", "This action cannot be undone. Do you wish to continue?": "Cette action ne peut pas être annulée. Souhaitez-vous continuer ?", "This channel was created on {{createdAt}}. This is the very beginning of the {{channelName}} channel.": "Ce canal a été créé le {{createdAt}}. Voici le tout début du canal {{channelName}}.", @@ -1873,7 +1873,7 @@ "This option controls how long the model will stay loaded into memory following the request (default: 5m)": "Cette option détermine la durée pendant laquelle le modèle restera chargé en mémoire après la demande (par défaut : 5m).", "This option controls how many tokens are preserved when refreshing the context. For example, if set to 2, the last 2 tokens of the conversation context will be retained. Preserving context can help maintain the continuity of a conversation, but it may reduce the ability to respond to new topics.": "Cette option détermine combien de Token sont conservés lors du rafraîchissement du contexte. Par exemple, avec une valeur de 2, les 2 derniers Token seront conservés. Cela aide à maintenir la continuité de la conversation, mais peut limiter la capacité à traiter de nouveaux sujets.", "This option enables or disables the use of the reasoning feature in Ollama, which allows the model to think before generating a response. When enabled, the model can take a moment to process the conversation context and generate a more thoughtful response.": "Cette option active ou désactive l'utilisation de la fonctionnalité de raisonnement dans Ollama, qui permet au modèle de réfléchir avant de générer une réponse. Lorsqu'elle est activée, le modèle peut prendre un moment pour traiter le contexte de la conversation et générer une réponse plus réfléchie.", - "This option sets the maximum number of tokens the model can generate in its response. Increasing this limit allows the model to provide longer answers, but it may also increase the likelihood of unhelpful or irrelevant content being generated.": "Cette option définit le nombre maximal de Token que le modèle peut générer dans sa réponse. Une valeur plus élevée permet des réponses plus longues, mais peut aussi générer du contenu moins pertinent.", + "This option sets the maximum number of tokens the model can generate in its response. Increasing this limit allows the model to provide longer answers, but it may also increase the likelihood of unhelpful or irrelevant content being generated.": "Cette option définit le nombre maximal de tokens que le modèle peut générer dans sa réponse. Une valeur plus élevée permet des réponses plus longues, mais peut aussi générer du contenu moins pertinent.", "This option will delete all existing files in the collection and replace them with newly uploaded files.": "Cette option supprimera tous les fichiers existants dans la collection et les remplacera par les fichiers nouvellement téléchargés.", "This response was generated by \"{{model}}\"": "Cette réponse a été générée par \"{{model}}\"", "This will delete": "Cela supprimera", @@ -1886,7 +1886,7 @@ "Thought for {{DURATION}} seconds": "Réflexion pendant {{DURATION}} secondes", "Thought for less than a second": "Réflexion pendant moins d'une seconde", "Thread": "Fil de discussion", - "Thumbs up/down ratings from users on model responses": "", + "Thumbs up/down ratings from users on model responses": "Évaluations des utilisateurs (pouces vers le haut/bas) sur les réponses du modèle", "Tika": "Tika", "Tika Server URL required.": "URL du serveur Tika requise.", "Tiktoken": "Tiktoken", @@ -1903,30 +1903,30 @@ "To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Pour accéder à l'interface Web, veuillez contacter l'administrateur. Les administrateurs peuvent gérer les statuts des utilisateurs depuis le panneau d'administration.", "To attach knowledge base here, add them to the \"Knowledge\" workspace first.": "Pour attacher une base de connaissances ici, ajoutez-les d'abord à l'espace de travail « Connaissances ».", "To learn more about available endpoints, visit our documentation.": "Pour en savoir plus sur les points de terminaison disponibles, consultez notre documentation.", - "To select skills here, add them to the \"Skills\" workspace first.": "", + "To select skills here, add them to the \"Skills\" workspace first.": "Pour sélectionner des skills ici, ajoutez-les d'abord à l'espace de travail « Skills ».", "To select toolkits here, add them to the \"Tools\" workspace first.": "Pour sélectionner des outils ici, ajoutez-les d'abord à l'espace de travail « Outils ». ", "Toast notifications for new updates": "Notifications toast pour les nouvelles mises à jour", "Today": "Aujourd'hui", "Today at {{LOCALIZED_TIME}}": "Aujourd'hui à {{LOCALIZED_TIME}}", "Toggle {{COUNT}} sources": "", "Toggle 1 source": "", - "Toggle Dictation": "", - "Toggle Sidebar": "", + "Toggle Dictation": "Activer/Désactiver la dictée", + "Toggle Sidebar": "Afficher/Masquer la barre latérale", "Toggle status history": "", "Toggle whether current connection is active.": "Afficher/masquer si la connection courante est active", "Token": "Token", - "Token counts are estimates and may not reflect actual API usage": "", - "tokens": "", - "Tokens": "", + "Token counts are estimates and may not reflect actual API usage": "Le nombre de tokens est une estimation et peut ne pas refléter l'utilisation réelle de l'API", + "tokens": "tokens", + "Tokens": "Tokens", "Too verbose": "Trop détaillé", - "Tool created successfully": "L'outil a été créé avec succès", + "Tool created successfully": "Outil créé avec succès", "Tool deleted successfully": "Outil supprimé avec succès", "Tool Description": "Description de l'outil", "Tool ID": "ID de l'outil", "Tool imported successfully": "Outil importé avec succès", "Tool Name": "Nom de l'outil", "Tool Servers": "Serveurs d'outils", - "Tool updated successfully": "L'outil a été mis à jour avec succès", + "Tool updated successfully": "Outil mis à jour avec succès", "Tools": "Outils", "Tools Access": "Accès aux outils", "Tools are a function calling system with arbitrary code execution": "Les outils sont un système d'appel de fonction avec exécution de code arbitraire", @@ -1940,13 +1940,13 @@ "Transformers": "Transformers", "Trouble accessing Ollama?": "Problèmes d'accès à Ollama ?", "Trust Proxy Environment": "Faire confiance au proxy de l'environement", - "Try adjusting your search or filter to find what you are looking for.": "", + "Try adjusting your search or filter to find what you are looking for.": "Essayez d'ajuster votre recherche ou votre filtre.", "Try Again": "Essayer à nouveau", "TTS Model": "Modèle de Text-to-Speech", "TTS Settings": "Réglages de Text-to-Speech", "TTS Voice": "Voix de Text-to-Speech", "Type": "Type", - "Type here...": "", + "Type here...": "Entrez votre message ici...", "Type Hugging Face Resolve (Download) URL": "Entrez l'URL de Téléchargement Hugging Face Resolve", "Uh-oh! There was an issue with the response.": "Oh! Un problème est survenu avec la réponse.", "UI": "UI", @@ -1984,15 +1984,15 @@ "Upload Pipeline": "Pipeline de téléchargement", "Upload profile image": "", "Upload Progress": "Progression de l'envoi", - "Upload Progress: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)": "Progression du téléchargement\u00a0: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)", - "Uploaded files or images": "", + "Upload Progress: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)": "Progression du téléchargement : {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)", + "Uploaded files or images": "Les fichiers ou images téléversés", "Uploading file...": "Téléversement du fichier en cours...", - "Uploading...": "", + "Uploading...": "Téléversement en cours...", "URL": "URL", "URL is required": "L'URL est requise", "URL Mode": "Mode d'URL", "Usage": "Utilisation", - "Use": "", + "Use": "Utilisez", "Use '#' in the prompt input to load and include your knowledge.": "Utilisez '#' dans la zone de saisie du prompt pour charger et inclure vos connaissances.", "Use /v1/chat/completions endpoint instead of /v1/audio/transcriptions for potentially better accuracy.": "", "Use Chat Completions API": "", @@ -2004,9 +2004,9 @@ "User": "Utilisateur", "User Activity": "", "User Groups": "Groupes d'utilisateurs", - "User location successfully retrieved.": "L'emplacement de l'utilisateur a été récupéré avec succès.", + "User location successfully retrieved.": "Emplacement de l'utilisateur récupéré avec succès.", "User menu": "Menu utilisateur", - "User ratings (thumbs up/down)": "", + "User ratings (thumbs up/down)": "Évaluations des utilisateurs (pouces vers le haut/bas)", "User Status": "", "User Webhooks": "Webhooks utilisateur", "Username": "Nom d'utilisateur", @@ -2017,11 +2017,11 @@ "Using Entire Document": "Utilisation du document entier", "Using Focused Retrieval": "Utilisation de la récupération ciblée", "Using the default arena model with all models. Click the plus button to add custom models.": "Utilisation du modèle d'arène par défaut avec tous les modèles. Cliquez sur le bouton plus pour ajouter des modèles personnalisés.", - "Valid time units:": "Unités de temps valides\u00a0:", + "Valid time units:": "Unités de temps valides :", "Validate certificate": "Valider le certificat", "Valves": "Vannes", "Valves updated": "Vannes mises à jour", - "Valves updated successfully": "Les vannes ont été mises à jour avec succès", + "Valves updated successfully": "Vannes mises à jour avec succès", "variable": "variable", "Verify Connection": "Vérifier la connexion", "Verify SSL Certificate": "Vérifier le certificat SSL", @@ -2053,10 +2053,10 @@ "Web Search Engine": "Moteur de recherche Web", "Web Search in Chat": "Recherche web depuis la conversation", "Web Search Query Generation": "Génération de requête de recherche Web", - "Webhook Name": "", + "Webhook Name": "Nom du webhook", "Webhook URL": "URL du webhook", - "Webhooks": "", - "Webpage URLs": "", + "Webhooks": "Webhooks", + "Webpage URLs": "URL des pages web", "WebUI Settings": "Réglages de WebUI", "WebUI URL": "URL de WebUI", "WebUI will make requests to \"{{url}}\"": "WebUI effectuera des requêtes vers \"{{url}}\"", @@ -2067,12 +2067,12 @@ "What is NOT shared:": "", "What is shared:": "", "What's New in": "Quoi de neuf dans", - "What's on your mind?": "", + "What's on your mind?": "Quoi de neuf ?", "When enabled, the model will respond to each chat message in real-time, generating a response as soon as the user sends a message. This mode is useful for live chat applications, but may impact performance on slower hardware.": "Lorsqu'il est activé, le modèle répondra à chaque message de la conversation en temps réel, générant une réponse dès que l'utilisateur envoie un message. Ce mode est utile pour les applications de conversation en direct, mais peut affecter les performances sur un matériel plus lent.", "wherever you are": "où que vous soyez", "Whether to paginate the output. Each page will be separated by a horizontal rule and page number. Defaults to False.": "Indique si la sortie doit être paginée. Chaque page sera séparée par une règle horizontale et un numéro de page. La valeur par défaut est False.", "Whisper (Local)": "Whisper (local)", - "Who can share to this group": "", + "Who can share to this group": "Qui est autorisé à partager avec ce groupe", "Why?": "Pourquoi ?", "Widescreen Mode": "Mode grand écran", "Width": "Largeur", @@ -2100,26 +2100,26 @@ "You can only chat with a maximum of {{maxCount}} file(s) at a time.": "Vous ne pouvez discuter qu'avec un maximum de {{maxCount}} fichier(s) à la fois.", "You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Vous pouvez personnaliser vos interactions avec les LLM en ajoutant des mémoires à l'aide du bouton « Gérer » ci-dessous, ce qui les rendra plus utiles et mieux adaptées à vos besoins.", "You cannot upload an empty file.": "Vous ne pouvez pas envoyer un fichier vide.", - "You do not have permission to edit this model": "Vous n'avez pas la permission de modifier ce modèle", - "You do not have permission to edit this prompt.": "Vous n'avez pas la permission de modifier ce prompt.", - "You do not have permission to edit this skill.": "", - "You do not have permission to edit this tool": "", - "You do not have permission to make this public": "", - "You do not have permission to send messages in this channel.": "Vous n'avez pas la permission d'envoyer des messages dans ce canal.", - "You do not have permission to send messages in this thread.": "Vous n'avez pas la permission d'envoyer des messages dans ce fil de discussion.", - "You do not have permission to upload files to this knowledge base.": "Vous n'avez pas la permission de téléverser des fichiers dans cette base de connaissances.", - "You do not have permission to upload files.": "Vous n'avez pas l'autorisation de téléverser des fichiers", - "You do not have permission to upload web content.": "", + "You do not have permission to edit this model": "Vous n'êtes pas autorisé à modifier ce modèle", + "You do not have permission to edit this prompt.": "Vous n'êtes pas autorisé à modifier ce prompt.", + "You do not have permission to edit this skill.": "Vous n'êtes pas autorisé à modifier ce skill.", + "You do not have permission to edit this tool": "Vous n'êtes pas autorisé à modifier cet outil", + "You do not have permission to make this public": "Vous n'êtes pas autorisé à rendre ceci public", + "You do not have permission to send messages in this channel.": "Vous n'êtes pas autorisé à envoyer des messages dans ce canal.", + "You do not have permission to send messages in this thread.": "Vous n'êtes pas autorisé à envoyer des messages dans ce fil de discussion.", + "You do not have permission to upload files to this knowledge base.": "Vous n'êtes pas autorisé à téléverser des fichiers dans cette base de connaissances.", + "You do not have permission to upload files.": "Vous n'êtes pas autorisé à téléverser des fichiers.", + "You do not have permission to upload web content.": "Vous n'êtes pas autorisé à joindre une page web.", "You have no archived conversations.": "Vous n'avez aucune conversation archivée.", - "You have no shared conversations.": "", + "You have no shared conversations.": "Vous n'avez aucune conversation partagée.", "You have shared this chat": "Vous avez partagé cette conversation.", - "You.com API Key": "", + "You.com API Key": "Clé API You.com", "You're a helpful assistant.": "Vous êtes un assistant efficace.", "You're now logged in.": "Vous êtes désormais connecté.", "Your Account": "Votre compte", "Your account status is currently pending activation.": "Votre statut de compte est actuellement en attente d'activation.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "L'intégralité de votre contribution ira directement au développeur du plugin ; Open WebUI ne prend aucun pourcentage. Cependant, la plateforme de financement choisie peut avoir ses propres frais.", - "Your message text or inputs": "", + "Your message text or inputs": "Vos messages envoyés", "Your usage stats have been successfully synced.": "Vos statistiques d'utilisation ont été synchronisées avec succès.", "YouTube": "YouTube", "Youtube Language": "Langue de Youtube", From 6e43861c0c5f1df98adca9be7bc7d40df728d1cf Mon Sep 17 00:00:00 2001 From: Shirasawa <764798966@qq.com> Date: Thu, 5 Mar 2026 05:03:20 +0800 Subject: [PATCH 006/114] feat: prioritize in-group members in sorting (#22211) --- src/lib/components/admin/Users/Groups/Users.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/admin/Users/Groups/Users.svelte b/src/lib/components/admin/Users/Groups/Users.svelte index ac1daade87..ace5141a7f 100644 --- a/src/lib/components/admin/Users/Groups/Users.svelte +++ b/src/lib/components/admin/Users/Groups/Users.svelte @@ -31,7 +31,7 @@ let query = ''; let searchDebounceTimer: ReturnType; - let orderBy = 'created_at'; // default sort key + let orderBy = groupId ? `group_id:${groupId}` : 'last_active_at'; // default sort key let direction = 'desc'; // default sort order let page = 1; From 890949abe6b01d201355a86c50317e20da07dd34 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Wed, 4 Mar 2026 15:50:37 -0600 Subject: [PATCH 007/114] feat: add DOCX/XLSX/PPTX file preview - DOCX: mammoth converts to semantic HTML (prose preview) - XLSX: xlsx library extended to FileNav with sheet tabs at bottom - PPTX: custom canvas renderer produces PNG images per slide with panzoom zoom/pan and slide navigation Changes: - New: src/lib/utils/pptxToHtml.ts (canvas-based PPTX renderer) - FileNav.svelte: office format detection, blob download, conversion - FilePreview.svelte: office rendering branches, sheet tabs, slide viewer - FileItemModal.svelte: DOCX/PPTX preview tabs - package.json: added mammoth dependency --- package-lock.json | 209 +++++++------- package.json | 1 + src/lib/components/chat/FileNav.svelte | 81 +++++- .../chat/FileNav/FilePreview.svelte | 128 ++++++++- .../components/common/FileItemModal.svelte | 110 +++++++- src/lib/utils/pptxToHtml.ts | 259 ++++++++++++++++++ 6 files changed, 683 insertions(+), 105 deletions(-) create mode 100644 src/lib/utils/pptxToHtml.ts diff --git a/package-lock.json b/package-lock.json index b18ff000dc..75b3f3e20c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -66,6 +66,7 @@ "idb": "^7.1.1", "js-sha256": "^0.10.1", "jspdf": "^4.0.0", + "jszip": "^3.10.1", "katex": "^0.16.22", "kokoro-js": "^1.1.1", "leaflet": "^1.9.4", @@ -223,7 +224,7 @@ "version": "2.2.2", "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.2.2.tgz", "integrity": "sha512-UNtPCbrwrenpmrXuRwn9jYpPoweNXj8X5sMvYgsqYyaH8jQ6LfUJSk3dJLnBK+6sfYPrF4iAIo5sd5HQ+tg75A==", - "devOptional": true, + "dev": true, "license": "(Apache-2.0 AND BSD-3-Clause)" }, "node_modules/@chevrotain/cst-dts-gen": { @@ -1850,6 +1851,7 @@ "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -1860,6 +1862,7 @@ "version": "2.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -1870,6 +1873,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, "engines": { "node": ">=6.0.0" } @@ -1884,6 +1888,7 @@ "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -2304,6 +2309,7 @@ "version": "1.0.0-next.28", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", + "dev": true, "license": "MIT" }, "node_modules/@popperjs/core": { @@ -2702,6 +2708,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz", "integrity": "sha512-IwQk4yfwLdibDlrXVE04jTZYlLnwsTT2PIOQQGNLWfjavGifnk1JD1LcZjZaBTRcxZu2FfPfNLOE04DSu9lqtQ==", + "dev": true, "license": "MIT", "peerDependencies": { "acorn": "^8.9.0" @@ -2747,6 +2754,7 @@ "version": "2.22.4", "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.22.4.tgz", "integrity": "sha512-BXK9hTbP8AeQIfoz6+P3uoyVYStVHc5CIKqoTSF7hXm3Q5P9BwFMdEus4jsQuhaYmXGHzukcGlxe2QrsE8BJfQ==", + "dev": true, "license": "MIT", "dependencies": { "@sveltejs/acorn-typescript": "^1.0.5", @@ -2784,6 +2792,7 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-4.0.4.tgz", "integrity": "sha512-0ba1RQ/PHen5FGpdSrW7Y3fAMQjrXantECALeOiOdBdzR5+5vPP6HVZRLmZaQL+W8m++o+haIAKq5qT+MiZ7VA==", + "dev": true, "license": "MIT", "dependencies": { "@sveltejs/vite-plugin-svelte-inspector": "^3.0.0-next.0||^3.0.0", @@ -2805,6 +2814,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-3.0.1.tgz", "integrity": "sha512-2CKypmj1sM4GE7HjllT7UKmo4Q6L5xFRd7VMGEWhYnZ+wc6AUVU01IBd7yUi6WnFndEwWoMNOd6e8UjoN0nbvQ==", + "dev": true, "license": "MIT", "dependencies": { "debug": "^4.3.7" @@ -2822,6 +2832,7 @@ "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2839,12 +2850,14 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, "node_modules/@sveltejs/vite-plugin-svelte/node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, "license": "MIT", "dependencies": { "ms": "^2.1.3" @@ -2862,6 +2875,7 @@ "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, "license": "MIT" }, "node_modules/@swc/helpers": { @@ -3265,23 +3279,6 @@ "lowlight": "^2 || ^3" } }, - "node_modules/@tiptap/extension-collaboration": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-collaboration/-/extension-collaboration-3.20.0.tgz", - "integrity": "sha512-JItmI4U0i4kqorO114u24hM9k945IdaQ6Uc2DEtPBFFuS8cepJf2zw+ulAT1kAx6ZRiNvNpT9M7w+J0mWRn+Sg==", - "license": "MIT", - "peer": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.20.0", - "@tiptap/pm": "^3.20.0", - "@tiptap/y-tiptap": "^3.0.2", - "yjs": "^13" - } - }, "node_modules/@tiptap/extension-document": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.0.7.tgz", @@ -3524,21 +3521,6 @@ "@tiptap/suggestion": "^3.0.9" } }, - "node_modules/@tiptap/extension-node-range": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-node-range/-/extension-node-range-3.20.0.tgz", - "integrity": "sha512-XeKKTV88VuJ4Mh0Rxvc/PPzG76cb44sE+rB4u0J/ms63R/WFTm6yJQlCgUVGnGeHleSlrWuZY8gGSuoljmQzqg==", - "license": "MIT", - "peer": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.20.0", - "@tiptap/pm": "^3.20.0" - } - }, "node_modules/@tiptap/extension-ordered-list": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.0.7.tgz", @@ -3605,20 +3587,6 @@ "@tiptap/core": "^3.0.7" } }, - "node_modules/@tiptap/extension-text-style": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-3.20.0.tgz", - "integrity": "sha512-zyWW1a6W+kaXAn3wv2svJ1XuVMapujftvH7Xn2Q3QmKKiDkO+NiFkrGe8BhMopu8Im51nO3NylIgVA0X1mS1rQ==", - "license": "MIT", - "peer": true, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/ueberdosis" - }, - "peerDependencies": { - "@tiptap/core": "^3.20.0" - } - }, "node_modules/@tiptap/extension-typography": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@tiptap/extension-typography/-/extension-typography-3.0.7.tgz", @@ -3752,31 +3720,11 @@ "@tiptap/pm": "^3.4.2" } }, - "node_modules/@tiptap/y-tiptap": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@tiptap/y-tiptap/-/y-tiptap-3.0.2.tgz", - "integrity": "sha512-flMn/YW6zTbc6cvDaUPh/NfLRTXDIqgpBUkYzM74KA1snqQwhOMjnRcnpu4hDFrTnPO6QGzr99vRyXEA7M44WA==", - "license": "MIT", - "peer": true, - "dependencies": { - "lib0": "^0.2.100" - }, - "engines": { - "node": ">=16.0.0", - "npm": ">=8.0.0" - }, - "peerDependencies": { - "prosemirror-model": "^1.7.1", - "prosemirror-state": "^1.2.3", - "prosemirror-view": "^1.9.10", - "y-protocols": "^1.0.1", - "yjs": "^13.5.38" - } - }, "node_modules/@types/cookie": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==" + "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", + "dev": true }, "node_modules/@types/d3": { "version": "7.4.3", @@ -4713,6 +4661,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">= 0.4" @@ -4794,6 +4743,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">= 0.4" @@ -5074,7 +5024,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/buffer-builder/-/buffer-builder-0.2.0.tgz", "integrity": "sha512-7VPMEPuYznPSoR21NE1zvd2Xna6c/CloiZCfcMXR1Jny6PjX0N4Nsa38zcBFo/FMK+BlA+FLKbJCQ0i2yxp+Xg==", - "devOptional": true, + "dev": true, "license": "MIT/X11" }, "node_modules/buffer-crc32": { @@ -5620,6 +5570,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -5737,7 +5688,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/colorjs.io/-/colorjs.io-0.5.2.tgz", "integrity": "sha512-twmVoizEW7ylZSN32OgKdXRmo1qg+wT5/6C3xu5b9QsWzSFAhHLn2xd8ro0diCsKfCj1RdaTP/nrcW+vAoQPIw==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/colors": { @@ -5806,6 +5757,7 @@ "version": "0.6.0", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -6675,7 +6627,8 @@ "node_modules/devalue": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz", - "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==" + "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==", + "dev": true }, "node_modules/devlop": { "version": "1.1.0", @@ -7229,6 +7182,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==", + "dev": true, "license": "MIT" }, "node_modules/espree": { @@ -7264,6 +7218,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.1.1.tgz", "integrity": "sha512-ebTT9B6lOtZGMgJ3o5r12wBacHctG7oEWazIda8UlPfA3HD/Wrv8FdXoVo73vzdpwCxNyXjPauyN2bbJzMkB9A==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" @@ -8011,7 +7966,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "devOptional": true, + "dev": true, "engines": { "node": ">=8" } @@ -8341,7 +8296,7 @@ "version": "5.0.3", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz", "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/import-fresh": { @@ -8800,6 +8755,7 @@ "version": "4.1.5", "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "dev": true, "engines": { "node": ">=6" } @@ -8928,7 +8884,7 @@ "version": "1.29.1", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.1.tgz", "integrity": "sha512-FmGoeD4S05ewj+AkhTY+D+myDvXI6eL27FjHIjoyUkO/uw7WZD1fBVs0QxeYWa7E17CUHJaYX/RUGISCtcrG4Q==", - "devOptional": true, + "dev": true, "license": "MPL-2.0", "dependencies": { "detect-libc": "^1.0.3" @@ -8960,6 +8916,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -8980,6 +8937,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -9000,6 +8958,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -9020,6 +8979,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -9040,6 +9000,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -9060,6 +9021,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -9080,6 +9042,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -9100,6 +9063,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -9120,6 +9084,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -9140,6 +9105,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -9157,7 +9123,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "bin": { "detect-libc": "bin/detect-libc.js" @@ -9276,7 +9242,8 @@ "node_modules/locate-character": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", - "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==" + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", + "dev": true }, "node_modules/locate-path": { "version": "6.0.0", @@ -9840,6 +9807,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "dev": true, "engines": { "node": ">=4" } @@ -9848,6 +9816,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -10379,6 +10348,7 @@ "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -10510,6 +10480,7 @@ "version": "3.3.8", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "dev": true, "funding": [ { "type": "github", @@ -11340,7 +11311,7 @@ "version": "7.8.1", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "devOptional": true, + "dev": true, "dependencies": { "tslib": "^2.1.0" } @@ -11349,6 +11320,7 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dev": true, "dependencies": { "mri": "^1.1.0" }, @@ -11370,7 +11342,7 @@ "version": "1.81.0", "resolved": "https://registry.npmjs.org/sass-embedded/-/sass-embedded-1.81.0.tgz", "integrity": "sha512-uZQ2Faxb1oWBHpeSSzjxnhClbMb3QadN0ql0ZFNuqWOLUxwaVhrMlMhPq6TDPbbfDUjihuwrMCuy695Bgna5RA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "@bufbuild/protobuf": "^2.0.0", @@ -11418,6 +11390,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11434,6 +11407,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11450,6 +11424,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11466,6 +11441,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11482,6 +11458,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11498,6 +11475,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11514,6 +11492,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11530,6 +11509,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11546,6 +11526,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11562,6 +11543,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11578,6 +11560,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11594,6 +11577,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11610,6 +11594,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11626,6 +11611,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11642,6 +11628,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11658,6 +11645,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11674,6 +11662,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11690,6 +11679,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11706,6 +11696,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11722,6 +11713,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -11735,7 +11727,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -11761,7 +11753,8 @@ "node_modules/set-cookie-parser": { "version": "2.6.0", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", - "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==", + "dev": true }, "node_modules/set-function-length": { "version": "1.2.2", @@ -11890,6 +11883,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.0.tgz", "integrity": "sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==", + "dev": true, "license": "MIT", "dependencies": { "@polka/url": "^1.0.0-next.24", @@ -11965,6 +11959,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -12223,6 +12218,7 @@ "version": "5.42.2", "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.42.2.tgz", "integrity": "sha512-iSry5jsBHispVczyt9UrBX/1qu3HQ/UyKPAIjqlvlu3o/eUvc+kpyMyRS2O4HLLx4MvLurLGIUOyyP11pyD59g==", + "dev": true, "license": "MIT", "dependencies": { "@jridgewell/remapping": "^2.3.4", @@ -12302,21 +12298,6 @@ } } }, - "node_modules/svelte-check/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "optional": true, - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, "node_modules/svelte-check/node_modules/readdirp": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", @@ -12380,12 +12361,14 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, "license": "MIT" }, "node_modules/svelte/node_modules/is-reference": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", + "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.6" @@ -12411,7 +12394,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz", "integrity": "sha512-8lD+t2KrrScJ/7KXCSyfhT3/hRq78rC0wBFqNJXv3mZyn6hW2ypM05JmlSvtqRbeq6jqA94oHbxAr2vYsJ8vDA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "sync-message-port": "^1.0.0" @@ -12424,7 +12407,7 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/sync-message-port/-/sync-message-port-1.1.3.tgz", "integrity": "sha512-GTt8rSKje5FilG+wEdfCkOcLL7LWqpMlr2c3LRuKt/YXxcJ52aGSbGBAdI4L3aaqfrBt6y711El53ItyH1NWzg==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=16.0.0" @@ -12633,6 +12616,7 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -12893,7 +12877,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/varint/-/varint-6.0.0.tgz", "integrity": "sha512-cXEIW6cfr15lFv563k4GuVuW/fiwjknytD37jIOLSdSWuOI6WnO/oKwmP2FQTU2l01LP8/M5TSAJpzUaGe3uWg==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/vega": { @@ -13402,6 +13386,7 @@ "version": "5.4.21", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "dev": true, "license": "MIT", "dependencies": { "esbuild": "^0.21.3", @@ -13505,6 +13490,7 @@ "cpu": [ "ppc64" ], + "dev": true, "optional": true, "os": [ "aix" @@ -13520,6 +13506,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "android" @@ -13535,6 +13522,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "android" @@ -13550,6 +13538,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "android" @@ -13565,6 +13554,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -13580,6 +13570,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -13595,6 +13586,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -13610,6 +13602,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -13625,6 +13618,7 @@ "cpu": [ "arm" ], + "dev": true, "optional": true, "os": [ "linux" @@ -13640,6 +13634,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -13655,6 +13650,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "linux" @@ -13670,6 +13666,7 @@ "cpu": [ "loong64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -13685,6 +13682,7 @@ "cpu": [ "mips64el" ], + "dev": true, "optional": true, "os": [ "linux" @@ -13700,6 +13698,7 @@ "cpu": [ "ppc64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -13715,6 +13714,7 @@ "cpu": [ "riscv64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -13730,6 +13730,7 @@ "cpu": [ "s390x" ], + "dev": true, "optional": true, "os": [ "linux" @@ -13745,6 +13746,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -13760,6 +13762,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "netbsd" @@ -13775,6 +13778,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "openbsd" @@ -13790,6 +13794,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "sunos" @@ -13805,6 +13810,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -13820,6 +13826,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" @@ -13835,6 +13842,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -13847,6 +13855,7 @@ "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -13884,6 +13893,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz", "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", + "dev": true, "license": "MIT", "workspaces": [ "tests/deps/*", @@ -14607,6 +14617,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz", "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==", + "dev": true, "license": "MIT" } } diff --git a/package.json b/package.json index 703f1bc553..0774ca5d2a 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,7 @@ "idb": "^7.1.1", "js-sha256": "^0.10.1", "jspdf": "^4.0.0", + "jszip": "^3.10.1", "katex": "^0.16.22", "kokoro-js": "^1.1.1", "leaflet": "^1.9.4", diff --git a/src/lib/components/chat/FileNav.svelte b/src/lib/components/chat/FileNav.svelte index b6ba861e6a..9daf03592a 100644 --- a/src/lib/components/chat/FileNav.svelte +++ b/src/lib/components/chat/FileNav.svelte @@ -37,6 +37,7 @@ import FileNavToolbar from './FileNav/FileNavToolbar.svelte'; import FilePreview from './FileNav/FilePreview.svelte'; import FileEntryRow from './FileNav/FileEntryRow.svelte'; + import PortList from './FileNav/PortList.svelte'; import XTerminal from './XTerminal.svelte'; const i18n = getContext('i18n'); @@ -93,6 +94,14 @@ let fileLoading = false; let filePreviewRef: FilePreview; + // ── Office preview state ──────────────────────────────────────────── + let fileOfficeHtml: string | null = null; + let fileOfficeSlides: string[] | null = null; + let currentSlide = 0; + let excelSheetNames: string[] = []; + let selectedExcelSheet = ''; + let excelWorkbook: import('xlsx').WorkBook | null = null; + // ── File preview toolbar state (bound from FilePreview) ───────────── let editing = false; let showRaw = false; @@ -101,12 +110,15 @@ const MD_EXTS = new Set(['md', 'markdown', 'mdx']); const CSV_EXTS = new Set(['csv', 'tsv']); const HTML_EXTS = new Set(['html', 'htm']); + const OFFICE_EXTS = new Set(['docx', 'xlsx', 'pptx']); const getFileExt = (path: string | null) => path?.split('.').pop()?.toLowerCase() ?? ''; $: isMarkdown = MD_EXTS.has(getFileExt(selectedFile)); $: isCsv = CSV_EXTS.has(getFileExt(selectedFile)); $: isHtml = HTML_EXTS.has(getFileExt(selectedFile)); - $: isTextFile = fileContent !== null && fileImageUrl === null && filePdfData === null; + $: isOfficeFile = OFFICE_EXTS.has(getFileExt(selectedFile)); + $: isTextFile = + fileContent !== null && fileImageUrl === null && filePdfData === null && !isOfficeFile; // ── Upload / folder creation ───────────────────────────────────────── let isDragOver = false; @@ -169,6 +181,7 @@ const IMAGE_EXTS = new Set(['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg', 'bmp', 'ico', 'avif']); const isImage = (path: string) => IMAGE_EXTS.has(path.split('.').pop()?.toLowerCase() ?? ''); const isPdf = (path: string) => path.split('.').pop()?.toLowerCase() === 'pdf'; + const isOffice = (path: string) => OFFICE_EXTS.has(path.split('.').pop()?.toLowerCase() ?? ''); const buildBreadcrumbs = (path: string) => path @@ -192,6 +205,12 @@ fileImageUrl = null; } filePdfData = null; + fileOfficeHtml = null; + fileOfficeSlides = null; + currentSlide = 0; + excelSheetNames = []; + selectedExcelSheet = ''; + excelWorkbook = null; }; // ── Directory operations ───────────────────────────────────────────── @@ -244,6 +263,41 @@ } else if (isPdf(filePath)) { const result = await downloadFileBlob(terminal.url, terminal.key, filePath); if (result) filePdfData = await result.blob.arrayBuffer(); + } else if (isOffice(filePath)) { + const result = await downloadFileBlob(terminal.url, terminal.key, filePath); + if (result) { + const ext = getFileExt(filePath); + const arrayBuffer = await result.blob.arrayBuffer(); + try { + if (ext === 'docx') { + const mammoth = await import('mammoth'); + const res = await mammoth.convertToHtml({ arrayBuffer }); + const DOMPurify = (await import('dompurify')).default; + fileOfficeHtml = DOMPurify.sanitize(res.value); + } else if (ext === 'xlsx') { + const XLSX = await import('xlsx'); + const wb = XLSX.read(new Uint8Array(arrayBuffer), { type: 'array' }); + excelWorkbook = wb; + excelSheetNames = wb.SheetNames; + if (excelSheetNames.length > 0) { + selectedExcelSheet = excelSheetNames[0]; + const ws = wb.Sheets[selectedExcelSheet]; + const DOMPurify = (await import('dompurify')).default; + fileOfficeHtml = DOMPurify.sanitize( + XLSX.utils.sheet_to_html(ws, { id: 'excel-table', editable: false, header: '' }) + ); + } + } else if (ext === 'pptx') { + const { pptxToImages } = await import('$lib/utils/pptxToHtml'); + const result = await pptxToImages(arrayBuffer); + fileOfficeSlides = result.images; + currentSlide = 0; + } + } catch (e) { + console.error('Failed to render Office file:', e); + fileContent = `Error previewing file: ${e instanceof Error ? e.message : 'Unknown error'}`; + } + } } else { fileContent = await readFile(terminal.url, terminal.key, filePath); } @@ -536,7 +590,7 @@ onUploadFiles={handleUploadFiles} onMove={handleMove} > - {#if fileImageUrl !== null} + {#if fileImageUrl !== null || (fileOfficeSlides !== null && fileOfficeSlides.length > 0)} + {/each} + + {/if} + + {:else if fileOfficeSlides !== null && fileOfficeSlides.length > 0} +
+
+ Slide {currentSlide + 1} +
+ {#if fileOfficeSlides.length > 1} +
+ + {currentSlide + 1} / {fileOfficeSlides.length} + +
+ {/if} +
{:else if fileContent !== null} {#if isHtml && !showRaw} {#if overlay} @@ -226,7 +290,7 @@ class="text-xs font-mono text-gray-800 dark:text-gray-200 whitespace-pre-wrap break-all leading-relaxed p-3">{fileContent} {/if} {:else} -
+
{$i18n.t('Could not read file.')}
{/if} @@ -284,4 +348,62 @@ :global(.dark) .csv-row-num { color: #6b7280; } + /* ── Office preview styles ──────────────────────────────────────── */ + :global(.office-preview) { + font-size: 0.875rem; + line-height: 1.6; + color: #1f2937; + background: #fff; + border-radius: 4px; + } + :global(.dark .office-preview) { + color: #e5e7eb; + background: #1a1a2e; + } + :global(.office-preview table) { + border-collapse: collapse; + font-size: 0.8rem; + line-height: 1.25rem; + } + :global(.office-preview table td), + :global(.office-preview table th) { + border: 1px solid rgba(128, 128, 128, 0.25); + padding: 0.5rem 0.75rem; + text-align: left; + white-space: nowrap; + } + :global(.dark .office-preview table td), + :global(.dark .office-preview table th) { + border-color: rgba(128, 128, 128, 0.35); + } + :global(.office-preview table th) { + background: rgba(243, 244, 246, 0.95); + font-weight: 600; + position: sticky; + top: 0; + z-index: 1; + } + :global(.dark .office-preview table th) { + background: rgba(31, 41, 55, 0.95); + } + :global(.office-preview table tr:nth-child(even)) { + background: rgba(128, 128, 128, 0.04); + } + :global(.office-preview table tr:hover) { + background: rgba(59, 130, 246, 0.06); + } + :global(.dark .office-preview table tr:hover) { + background: rgba(59, 130, 246, 0.1); + } + :global(.office-preview img) { + max-width: 100%; + height: auto; + } + :global(.office-preview h1) { font-size: 1.5rem; font-weight: 700; margin: 0.75em 0 0.5em; } + :global(.office-preview h2) { font-size: 1.25rem; font-weight: 600; margin: 0.75em 0 0.5em; } + :global(.office-preview h3) { font-size: 1.1rem; font-weight: 600; margin: 0.5em 0 0.25em; } + :global(.office-preview p) { margin: 0.25em 0; } + :global(.office-preview ul), + :global(.office-preview ol) { padding-left: 1.5em; margin: 0.5em 0; } + diff --git a/src/lib/components/common/FileItemModal.svelte b/src/lib/components/common/FileItemModal.svelte index 9d617f3604..0058cf637a 100644 --- a/src/lib/components/common/FileItemModal.svelte +++ b/src/lib/components/common/FileItemModal.svelte @@ -40,6 +40,8 @@ let isAudio = false; let isImage = false; let isExcel = false; + let isDocx = false; + let isPptx = false; let selectedTab = ''; let excelWorkbook: WorkBook | null = null; @@ -49,6 +51,15 @@ let excelError = ''; let rowCount = 0; + // DOCX state + let docxHtml = ''; + let docxError = ''; + + // PPTX state + let pptxSlides: string[] = []; + let pptxCurrentSlide = 0; + let pptxError = ''; + let pzInstance: PanZoom | null = null; const initImagePanzoom = (node: HTMLElement) => { @@ -128,6 +139,16 @@ item.name.toLowerCase().endsWith('.xlsx') || item.name.toLowerCase().endsWith('.csv'))); + $: isDocx = + item?.meta?.content_type === + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' || + (item?.name && item.name.toLowerCase().endsWith('.docx')); + + $: isPptx = + item?.meta?.content_type === + 'application/vnd.openxmlformats-officedocument.presentationml.presentation' || + (item?.name && item.name.toLowerCase().endsWith('.pptx')); + const loadExcelContent = async () => { try { excelError = ''; @@ -170,6 +191,37 @@ renderExcelSheet(); } + const loadDocxContent = async () => { + try { + docxError = ''; + const [arrayBuffer, mammoth] = await Promise.all([ + getFileContentById(item.id), + import('mammoth') + ]); + const result = await mammoth.convertToHtml({ arrayBuffer }); + docxHtml = DOMPurify.sanitize(result.value); + } catch (error) { + console.error('Error loading DOCX file:', error); + docxError = $i18n.t('Failed to load DOCX file. Please try downloading it instead.'); + } + }; + + const loadPptxContent = async () => { + try { + pptxError = ''; + const [arrayBuffer, { pptxToImages }] = await Promise.all([ + getFileContentById(item.id), + import('$lib/utils/pptxToHtml') + ]); + const result = await pptxToImages(arrayBuffer); + pptxSlides = result.images; + pptxCurrentSlide = 0; + } catch (error) { + console.error('Error loading PPTX file:', error); + pptxError = $i18n.t('Failed to load PPTX file. Please try downloading it instead.'); + } + }; + const loadContent = async () => { selectedTab = ''; expandedContent = false; @@ -201,6 +253,12 @@ if (isExcel) { await loadExcelContent(); } + if (isDocx) { + await loadDocxContent(); + } + if (isPptx) { + await loadPptxContent(); + } loading = false; } @@ -358,7 +416,7 @@
{/if} - {#if isAudio || isPDF || isExcel || isCode || isMarkdown} + {#if isAudio || isPDF || isExcel || isCode || isMarkdown || isDocx || isPptx}
@@ -534,6 +592,56 @@ >
+ {:else if isDocx} + {#if docxError} +
{docxError}
+ {:else if docxHtml} +
+ {@html docxHtml} +
+ {:else} +
No content available
+ {/if} + {:else if isPptx} + {#if pptxError} +
{pptxError}
+ {:else if pptxSlides.length > 0} +
+
+ Slide {pptxCurrentSlide + 1} +
+ {#if pptxSlides.length > 1} +
+ + {pptxCurrentSlide + 1} / {pptxSlides.length} + +
+ {/if} +
+ {:else} +
No content available
+ {/if} {:else}
{(item?.file?.data?.content ?? '').trim() || 'No content'} diff --git a/src/lib/utils/pptxToHtml.ts b/src/lib/utils/pptxToHtml.ts new file mode 100644 index 0000000000..193469ddc5 --- /dev/null +++ b/src/lib/utils/pptxToHtml.ts @@ -0,0 +1,259 @@ +/** + * Lightweight PPTX → Image renderer. + * + * Extracts text and images from each slide and renders them + * directly to canvas, returning PNG data URLs. + * + * Uses jszip (dynamically imported) and the browser Canvas 2D API. + * No theme resolution, charts, SmartArt, or animations — preview only. + */ + +const EMU_PER_PX = 9525; +const emuToPx = (emu: number) => Math.round(emu / EMU_PER_PX); + +const parseEmu = (val: string | null | undefined): number => + val ? parseInt(val, 10) || 0 : 0; + +/** Load a data URI into an Image element and wait for it. */ +const loadImage = (src: string): Promise => + new Promise((resolve, reject) => { + const img = new Image(); + img.onload = () => resolve(img); + img.onerror = () => reject(new Error('Failed to load image')); + img.src = src; + }); + +/** + * Convert PPTX ArrayBuffer → array of PNG data URL strings, one per slide. + */ +export async function pptxToImages( + buffer: ArrayBuffer +): Promise<{ images: string[]; width: number; height: number }> { + const JSZip = (await import('jszip')).default; + const zip = await JSZip.loadAsync(buffer); + + // ── Read slide dimensions from presentation.xml ────────────────── + let slideW = 960; + let slideH = 540; + const presXml = zip.file('ppt/presentation.xml'); + if (presXml) { + const presText = await presXml.async('text'); + const presDoc = new DOMParser().parseFromString(presText, 'application/xml'); + const sldSz = presDoc.getElementsByTagName('p:sldSz')[0]; + if (sldSz) { + slideW = emuToPx(parseEmu(sldSz.getAttribute('cx'))); + slideH = emuToPx(parseEmu(sldSz.getAttribute('cy'))); + } + } + + // ── Collect media files (images) as base64 data URIs ───────────── + const media: Record = {}; + const mediaFiles = Object.keys(zip.files).filter((f) => f.startsWith('ppt/media/')); + await Promise.all( + mediaFiles.map(async (path) => { + const file = zip.file(path); + if (!file) return; + const base64 = await file.async('base64'); + const ext = path.split('.').pop()?.toLowerCase() ?? ''; + const mime = + ext === 'png' + ? 'image/png' + : ext === 'gif' + ? 'image/gif' + : ext === 'svg' + ? 'image/svg+xml' + : ext === 'emf' || ext === 'wmf' + ? 'image/x-emf' + : 'image/jpeg'; + media[path] = `data:${mime};base64,${base64}`; + }) + ); + + // ── Discover slide files ───────────────────────────────────────── + const slideFiles = Object.keys(zip.files) + .filter((f) => /^ppt\/slides\/slide\d+\.xml$/.test(f)) + .sort((a, b) => { + const na = parseInt(a.match(/slide(\d+)/)?.[1] ?? '0'); + const nb = parseInt(b.match(/slide(\d+)/)?.[1] ?? '0'); + return na - nb; + }); + + const images: string[] = []; + + for (const slidePath of slideFiles) { + const slideText = await zip.file(slidePath)!.async('text'); + const slideDoc = new DOMParser().parseFromString(slideText, 'application/xml'); + + // Load relationship file for this slide to resolve image references + const slideNum = slidePath.match(/slide(\d+)/)?.[1]; + const relsPath = `ppt/slides/_rels/slide${slideNum}.xml.rels`; + const rels: Record = {}; + const relsFile = zip.file(relsPath); + if (relsFile) { + const relsText = await relsFile.async('text'); + const relsDoc = new DOMParser().parseFromString(relsText, 'application/xml'); + const relEls = relsDoc.getElementsByTagName('Relationship'); + for (let i = 0; i < relEls.length; i++) { + const rel = relEls[i]; + const id = rel.getAttribute('Id') ?? ''; + const target = rel.getAttribute('Target') ?? ''; + if (target.startsWith('../')) { + rels[id] = 'ppt/' + target.replace('../', ''); + } else { + rels[id] = target; + } + } + } + + // ── Create canvas and render slide ─────────────────────────── + const canvas = document.createElement('canvas'); + canvas.width = slideW; + canvas.height = slideH; + const ctx = canvas.getContext('2d')!; + + // White background + ctx.fillStyle = '#ffffff'; + ctx.fillRect(0, 0, slideW, slideH); + + const spTree = slideDoc.getElementsByTagName('p:spTree')[0]; + if (!spTree) { + images.push(canvas.toDataURL('image/png')); + continue; + } + + const shapes = [ + ...Array.from(spTree.getElementsByTagName('p:sp')), + ...Array.from(spTree.getElementsByTagName('p:pic')) + ]; + + for (const shape of shapes) { + const xfrm = + shape.getElementsByTagName('a:xfrm')[0] ?? + shape.getElementsByTagName('p:xfrm')[0]; + if (!xfrm) continue; + + const off = xfrm.getElementsByTagName('a:off')[0]; + const ext = xfrm.getElementsByTagName('a:ext')[0]; + if (!off || !ext) continue; + + const x = emuToPx(parseEmu(off.getAttribute('x'))); + const y = emuToPx(parseEmu(off.getAttribute('y'))); + const w = emuToPx(parseEmu(ext.getAttribute('cx'))); + const h = emuToPx(parseEmu(ext.getAttribute('cy'))); + + if (w === 0 && h === 0) continue; + + // ── Picture ────────────────────────────────────────────── + const blipFill = shape.getElementsByTagName('p:blipFill')[0]; + if (blipFill) { + const blip = blipFill.getElementsByTagName('a:blip')[0]; + if (blip) { + const rEmbed = blip.getAttribute('r:embed') ?? ''; + const mediaPath = rels[rEmbed]; + const dataUri = mediaPath ? media[mediaPath] : ''; + if (dataUri && !dataUri.includes('image/x-emf')) { + try { + const img = await loadImage(dataUri); + ctx.drawImage(img, x, y, w, h); + } catch { + // Skip images that fail to load + } + } + } + continue; + } + + // ── Text shape ─────────────────────────────────────────── + const txBody = shape.getElementsByTagName('p:txBody')[0]; + if (!txBody) continue; + + ctx.save(); + ctx.rect(x, y, w, h); + ctx.clip(); + + const paragraphs = txBody.getElementsByTagName('a:p'); + let cursorY = y; + const defaultFontSize = 12; + + for (let pi = 0; pi < paragraphs.length; pi++) { + const para = paragraphs[pi]; + const runs = para.getElementsByTagName('a:r'); + + if (runs.length === 0) { + cursorY += defaultFontSize * 1.5; + continue; + } + + // Calculate max font size in this paragraph for line height + let maxFontPt = defaultFontSize; + for (let ri = 0; ri < runs.length; ri++) { + const rPr = runs[ri].getElementsByTagName('a:rPr')[0]; + if (rPr) { + const sz = rPr.getAttribute('sz'); + if (sz) { + const pt = parseInt(sz, 10) / 100; + if (pt > maxFontPt) maxFontPt = pt; + } + } + } + + const lineHeight = maxFontPt * 1.4; + cursorY += maxFontPt; // baseline offset + + let cursorX = x + 4; // small left padding + + for (let ri = 0; ri < runs.length; ri++) { + const run = runs[ri]; + const rPr = run.getElementsByTagName('a:rPr')[0]; + const text = run.getElementsByTagName('a:t')[0]?.textContent ?? ''; + if (!text) continue; + + let fontPt = defaultFontSize; + let bold = false; + let italic = false; + let color = '#000000'; + + if (rPr) { + if (rPr.getAttribute('b') === '1') bold = true; + if (rPr.getAttribute('i') === '1') italic = true; + const sz = rPr.getAttribute('sz'); + if (sz) fontPt = parseInt(sz, 10) / 100; + const solidFill = rPr.getElementsByTagName('a:solidFill')[0]; + if (solidFill) { + const srgb = solidFill.getElementsByTagName('a:srgbClr')[0]; + if (srgb) { + const val = srgb.getAttribute('val'); + if (val) color = `#${val}`; + } + } + } + + ctx.font = `${italic ? 'italic ' : ''}${bold ? 'bold ' : ''}${fontPt}pt Calibri, Arial, sans-serif`; + ctx.fillStyle = color; + ctx.textBaseline = 'alphabetic'; + + // Simple word-wrap within the shape bounds + const words = text.split(/(\s+)/); + for (const word of words) { + const metrics = ctx.measureText(word); + if (cursorX + metrics.width > x + w && cursorX > x + 4) { + cursorX = x + 4; + cursorY += lineHeight; + } + if (cursorY > y + h) break; + ctx.fillText(word, cursorX, cursorY); + cursorX += metrics.width; + } + } + + cursorY += lineHeight * 0.4; // paragraph spacing + } + + ctx.restore(); + } + + images.push(canvas.toDataURL('image/png')); + } + + return { images, width: slideW, height: slideH }; +} From e08341dab3bb10e26a64eb44cbebd2d507087b03 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Wed, 4 Mar 2026 15:51:03 -0600 Subject: [PATCH 008/114] enh: ot ports --- src/lib/apis/terminal/index.ts | 23 +++ .../components/chat/FileNav/PortList.svelte | 141 ++++++++++++++++++ 2 files changed, 164 insertions(+) create mode 100644 src/lib/components/chat/FileNav/PortList.svelte diff --git a/src/lib/apis/terminal/index.ts b/src/lib/apis/terminal/index.ts index aa99810753..b1a0e7acf9 100644 --- a/src/lib/apis/terminal/index.ts +++ b/src/lib/apis/terminal/index.ts @@ -5,6 +5,12 @@ export type FileEntry = { modified?: number; }; +export type ListeningPort = { + port: number; + pid: number | null; + process: string | null; +}; + export type TerminalFeatures = { terminal?: boolean; }; @@ -235,3 +241,20 @@ export const moveEntry = async ( }); return res; }; + +export const getListeningPorts = async ( + baseUrl: string, + apiKey: string +): Promise => { + const url = `${baseUrl.replace(/\/$/, '')}/ports`; + const res = await fetch(url, { + headers: { Authorization: `Bearer ${apiKey}` } + }).catch(() => null); + if (!res || !res.ok) return []; + const json = await res.json().catch(() => null); + return json?.ports ?? []; +}; + +export const getPortProxyUrl = (baseUrl: string, port: number, path: string = ''): string => { + return `${baseUrl.replace(/\/$/, '')}/proxy/${port}/${path}`; +}; diff --git a/src/lib/components/chat/FileNav/PortList.svelte b/src/lib/components/chat/FileNav/PortList.svelte new file mode 100644 index 0000000000..609ce9f0b4 --- /dev/null +++ b/src/lib/components/chat/FileNav/PortList.svelte @@ -0,0 +1,141 @@ + + +
+ + + + + + {#if expanded} +
+ {#if ports.length === 0} +
+ {$i18n.t('No servers detected')} +
+ {:else} + {#each ports as port} + + {/each} + {/if} +
+ {/if} +
From f962bae98306ea9264967b78b803397f4821f9b0 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Wed, 4 Mar 2026 15:59:55 -0600 Subject: [PATCH 009/114] feat: improve XLSX preview + add code syntax highlighting XLSX QoL: - Custom table renderer (excelToTable.ts) with column letters, row numbers, right-aligned numbers, empty cell handling - Monospace font, sticky headers + row nums, cell cursor - Sheet tabs moved to bottom bar (like PPTX navigation) - Unified styles between FileNav and FileItemModal Code highlighting: - Shiki-based syntax highlighting for code files in FileNav - Line numbers, dark/light theme support - Source/Preview toggle for code files --- src/lib/components/chat/FileNav.svelte | 21 ++- .../chat/FileNav/FilePreview.svelte | 146 ++++++++++++++++-- .../components/common/FileItemModal.svelte | 19 +-- src/lib/utils/codeHighlight.ts | 95 ++++++++++++ src/lib/utils/excelToTable.ts | 86 +++++++++++ 5 files changed, 326 insertions(+), 41 deletions(-) create mode 100644 src/lib/utils/codeHighlight.ts create mode 100644 src/lib/utils/excelToTable.ts diff --git a/src/lib/components/chat/FileNav.svelte b/src/lib/components/chat/FileNav.svelte index 9daf03592a..dfeb9064c5 100644 --- a/src/lib/components/chat/FileNav.svelte +++ b/src/lib/components/chat/FileNav.svelte @@ -26,6 +26,7 @@ setCwd, type FileEntry } from '$lib/apis/terminal'; + import { isCodeFile } from '$lib/utils/codeHighlight'; import Folder from '../icons/Folder.svelte'; import Document from '../icons/Document.svelte'; import PenAlt from '../icons/PenAlt.svelte'; @@ -116,6 +117,7 @@ $: isMarkdown = MD_EXTS.has(getFileExt(selectedFile)); $: isCsv = CSV_EXTS.has(getFileExt(selectedFile)); $: isHtml = HTML_EXTS.has(getFileExt(selectedFile)); + $: isCode = isCodeFile(selectedFile); $: isOfficeFile = OFFICE_EXTS.has(getFileExt(selectedFile)); $: isTextFile = fileContent !== null && fileImageUrl === null && filePdfData === null && !isOfficeFile; @@ -281,11 +283,9 @@ excelSheetNames = wb.SheetNames; if (excelSheetNames.length > 0) { selectedExcelSheet = excelSheetNames[0]; - const ws = wb.Sheets[selectedExcelSheet]; - const DOMPurify = (await import('dompurify')).default; - fileOfficeHtml = DOMPurify.sanitize( - XLSX.utils.sheet_to_html(ws, { id: 'excel-table', editable: false, header: '' }) - ); + const { excelToTable } = await import('$lib/utils/excelToTable'); + const result = await excelToTable(wb.Sheets[selectedExcelSheet]); + fileOfficeHtml = result.html; } } else if (ext === 'pptx') { const { pptxToImages } = await import('$lib/utils/pptxToHtml'); @@ -612,7 +612,7 @@ {/if} - {#if (isMarkdown || isCsv || isHtml) && fileContent !== null && !editing} + {#if (isMarkdown || isCsv || isHtml || isCode) && fileContent !== null && !editing} +
+ {#if queryError} +
{queryError}
+ {/if} + + + {#if queryColumns.length > 0} +
+ + + + + {#each queryColumns as col} + + {/each} + + + + {#each queryRows as row, i} + + + {#each row as cell} + + {/each} + + {/each} + +
#{col}
{i + 1}{cell}
+
+ {/if} + {:else} + +
+ {#if columns.length > 0} + + + + + {#each columns as col} + + {/each} + + + + {#each rows as row, i} + + + {#each row as cell} + + {/each} + + {/each} + +
#{col}
{page * pageSize + i + 1}{cell}
+ {:else} +
{$i18n.t('No data')}
+ {/if} +
+ + + {#if totalPages > 1} +
+ + {page + 1} / {totalPages} ({totalRows.toLocaleString()} rows) + +
+ {/if} + {/if} + {/if} + + + diff --git a/static/sql.js/sql-wasm.wasm b/static/sql.js/sql-wasm.wasm new file mode 100755 index 0000000000000000000000000000000000000000..b32b66473d5a3947a89eaa0cd54caef9e0cda9ef GIT binary patch literal 659730 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%0AUur`umG`g>}HDGtk^` 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
tD`saR49Z|p;*n+SI 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

)(o>u<`n8?u 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 mW_H2e4cY_R3)%t(9| literal 0 HcmV?d00001 From f5ea1ce250cb02fbc583c6cb3f52a923912d0178 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 5 Mar 2026 13:53:19 -0600 Subject: [PATCH 020/114] feat: add copy-to-clipboard button next to download in file toolbar --- src/lib/components/chat/FileNav.svelte | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/lib/components/chat/FileNav.svelte b/src/lib/components/chat/FileNav.svelte index 3897a3c40c..141f4c68bc 100644 --- a/src/lib/components/chat/FileNav.svelte +++ b/src/lib/components/chat/FileNav.svelte @@ -762,6 +762,33 @@ {/if} {/if} + {#if fileContent !== null} + + + + {/if} - {#if queryError} -

{queryError}
- {/if} {#if queryColumns.length > 0} @@ -327,4 +330,10 @@ :global(.dark) .sqlite-null { color: #6b7280 !important; } + .query-editor::placeholder { + color: #9ca3af; + } + :global(.dark) .query-editor::placeholder { + color: #6b7280; + } From aaa49bdd6d6e5c10e8be554039d3cac673008fc2 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 5 Mar 2026 14:52:50 -0600 Subject: [PATCH 024/114] refac --- .../chat/FileNav/FilePreview.svelte | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/lib/components/chat/FileNav/FilePreview.svelte b/src/lib/components/chat/FileNav/FilePreview.svelte index cd68692495..c4b73e5108 100644 --- a/src/lib/components/chat/FileNav/FilePreview.svelte +++ b/src/lib/components/chat/FileNav/FilePreview.svelte @@ -5,6 +5,7 @@ import DOMPurify from 'dompurify'; import { settings } from '$lib/stores'; import { isCodeFile, highlightCode } from '$lib/utils/codeHighlight'; + import { initMermaid, renderMermaidDiagram } from '$lib/utils'; import Spinner from '../../common/Spinner.svelte'; import PDFViewer from '../../common/PDFViewer.svelte'; import JsonTreeView from './JsonTreeView.svelte'; @@ -92,6 +93,41 @@ ? DOMPurify.sanitize(marked.parse(fileContent, { async: false }) as string) : ''; + let markdownEl: HTMLDivElement; + let mermaidInstance: any = null; + + const renderMermaidBlocks = async (el: HTMLDivElement) => { + if (!el) return; + const codeEls = el.querySelectorAll('code.language-mermaid'); + if (codeEls.length === 0) return; + + if (!mermaidInstance) { + mermaidInstance = await initMermaid(); + } + + for (const codeEl of codeEls) { + const pre = codeEl.parentElement; + if (!pre || pre.tagName !== 'PRE' || pre.dataset.mermaidRendered) continue; + pre.dataset.mermaidRendered = 'true'; + + try { + const svg = await renderMermaidDiagram(mermaidInstance, codeEl.textContent ?? ''); + if (svg) { + const wrapper = document.createElement('div'); + wrapper.className = 'mermaid-diagram flex justify-center py-2'; + wrapper.innerHTML = svg; + pre.replaceWith(wrapper); + } + } catch (e) { + console.error('Mermaid render error:', e); + } + } + }; + + $: if (renderedHtml && markdownEl) { + tick().then(() => renderMermaidBlocks(markdownEl)); + } + // Simple CSV parser that handles quoted fields const parseCsv = (text: string, delimiter: string): string[][] => { const rows: string[][] = []; @@ -341,7 +377,7 @@ title="HTML Preview" /> {:else if isMarkdown && !showRaw} -
+
{@html renderedHtml}
{:else if isCsv && !showRaw && csvRows.length > 0} From 8cd2157564c6e8a531e6d2f32c4a34ac13a3cd83 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Thu, 5 Mar 2026 23:02:00 +0100 Subject: [PATCH 025/114] Perf: precompile katex unicode regex (#22196) * perf: pre-compile KaTeX Unicode regex at module load time The katexStart() function was creating a new RegExp with Unicode property escapes (\p{Script=Han}, \p{Script=Hiragana}, etc.) on every invocation. Unicode property escapes are extremely expensive to compile as the regex engine must build character class tables covering tens of thousands of code points. Since marked calls the start() function at every character position while scanning source text, this meant hundreds of regex compilations per marked.lexer() call, and lexer runs ~60 times/sec during streaming. Profiling showed KaTeX regex consuming 87% (320ms/365ms) of total markdown rendering time. Changes: - Pre-compile SURROUNDING_CHARS_REGEX once at module load time - Use .test() instead of .match() to avoid array allocations - Fix delimiter search to find earliest match, not last match * perf: replace katexStart with single-pass character scan The katexStart() function was the dominant cost in marked's lexer, consuming 55-58% of total markdown rendering time per profiling. It was called at every character position by marked and each call: - Looped through 3-5 delimiters, each doing indexOf() on the full remaining source (3-5 x O(n) string scans per call) - Ran the complex ruleReg regex with Unicode lookaheads for validation - On failed validation, created substrings and looped again Replace with a single linear character scan using charCodeAt that: - Checks only for $ (charCode 36) or backslash (charCode 92) - Filters backslash hits by next character to avoid false positives - Preserves the surrounding-character validation - Returns immediately on first valid candidate - Lets the tokenizer handle full validation (it already does this) This reduces start() from O(n * delimiters * retries) to O(n) with a very small constant factor per call. * Update katex-extension.ts --- src/lib/utils/marked/katex-extension.ts | 61 ++++++++++--------------- 1 file changed, 25 insertions(+), 36 deletions(-) diff --git a/src/lib/utils/marked/katex-extension.ts b/src/lib/utils/marked/katex-extension.ts index dd755066ce..13860fab30 100644 --- a/src/lib/utils/marked/katex-extension.ts +++ b/src/lib/utils/marked/katex-extension.ts @@ -13,6 +13,12 @@ const ALLOWED_SURROUNDING_CHARS = '\\s。,、、;;„“‘’“”()「」『』[]《》【】‹›«»…⋯::?!~⇒?!-\\/:-@\\[-`{-~\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}'; // Modified to fit more formats in different languages. Originally: '\\s?。,、;!-\\/:-@\\[-`{-~\\p{Script=Han}\\p{Script=Hiragana}\\p{Script=Katakana}\\p{Script=Hangul}'; +// Pre-compile the surrounding character regex once at module load time. +// This regex uses Unicode property escapes (\p{Script=Han}, etc.) which are +// extremely expensive to compile - doing so on every call caused ~87% of +// markdown rendering time to be spent in KaTeX regex compilation. +const ALLOWED_SURROUNDING_CHARS_REGEX = new RegExp(`[${ALLOWED_SURROUNDING_CHARS}]`, 'u'); + // const DELIMITER_LIST = [ // { left: '$$', right: '$$', display: false }, // { left: '$', right: '$', display: false }, @@ -67,48 +73,31 @@ export default function (options = {}) { } function katexStart(src, displayMode: boolean) { - const ruleReg = displayMode ? blockRule : inlineRule; + for (let i = 0; i < src.length; i++) { + const ch = src.charCodeAt(i); - let indexSrc = src; - - while (indexSrc) { - let index = -1; - let startIndex = -1; - let startDelimiter = ''; - let endDelimiter = ''; - for (const delimiter of DELIMITER_LIST) { - if (delimiter.display !== displayMode) { + if (ch === 36 /* $ */) { + // Display mode requires $$, skip single $ for display + if (displayMode && src.charAt(i + 1) !== '$') { continue; } - - startIndex = indexSrc.indexOf(delimiter.left); - if (startIndex === -1) { - continue; + if (i === 0 || ALLOWED_SURROUNDING_CHARS_REGEX.test(src.charAt(i - 1))) { + return i; } - - index = startIndex; - startDelimiter = delimiter.left; - endDelimiter = delimiter.right; - } - - if (index === -1) { - return; - } - - // Check if the delimiter is preceded by a special character. - // If it does, then it's potentially a math formula. - const f = - index === 0 || - indexSrc.charAt(index - 1).match(new RegExp(`[${ALLOWED_SURROUNDING_CHARS}]`, 'u')); - if (f) { - const possibleKatex = indexSrc.substring(index); - - if (possibleKatex.match(ruleReg)) { - return index; + } else if (ch === 92 /* \ */) { + const next = src.charAt(i + 1); + // Only consider \ if followed by a valid math delimiter start + if (displayMode) { + // Display: \[ or \begin{equation} + if (next !== '[' && next !== 'b') continue; + } else { + // Inline: \( or \ce{ or \pu{ + if (next !== '(' && next !== 'c' && next !== 'p') continue; + } + if (i === 0 || ALLOWED_SURROUNDING_CHARS_REGEX.test(src.charAt(i - 1))) { + return i; } } - - indexSrc = indexSrc.substring(index + startDelimiter.length).replace(endDelimiter, ''); } } From 4b3ed3e802d6f2ec8ee7caf358af810b7d09f789 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Thu, 5 Mar 2026 16:08:11 -0600 Subject: [PATCH 026/114] feat: notebook per-cell execution via open-terminal REST endpoints - Add notebook API functions (createNotebookSession, executeNotebookCell, stopNotebookSession) - Create CellEditor component with CodeMirror for cell editing - Rewrite NotebookView with session-based execution, Run All, Restart, Stop - Kernel status indicator with tooltips - Wire baseUrl/apiKey through FilePreview and FileNav --- src/lib/apis/terminal/index.ts | 78 ++++ src/lib/components/chat/FileNav.svelte | 2 + .../components/chat/FileNav/CellEditor.svelte | 109 ++++++ .../chat/FileNav/FilePreview.svelte | 6 +- .../chat/FileNav/NotebookView.svelte | 361 ++++++++++++++++-- 5 files changed, 523 insertions(+), 33 deletions(-) create mode 100644 src/lib/components/chat/FileNav/CellEditor.svelte diff --git a/src/lib/apis/terminal/index.ts b/src/lib/apis/terminal/index.ts index b1a0e7acf9..748ada33a0 100644 --- a/src/lib/apis/terminal/index.ts +++ b/src/lib/apis/terminal/index.ts @@ -258,3 +258,81 @@ export const getListeningPorts = async ( export const getPortProxyUrl = (baseUrl: string, port: number, path: string = ''): string => { return `${baseUrl.replace(/\/$/, '')}/proxy/${port}/${path}`; }; + +// --------------------------------------------------------------------------- +// Notebook execution +// --------------------------------------------------------------------------- + +export const createNotebookSession = async ( + baseUrl: string, + apiKey: string, + path: string +): Promise<{ id: string; kernel: string; status: string } | { error: string }> => { + const url = `${baseUrl.replace(/\/$/, '')}/notebooks`; + const res = await fetch(url, { + method: 'POST', + headers: { + Authorization: `Bearer ${apiKey}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ path }) + }) + .then(async (res) => { + if (!res.ok) { + const body = await res.json().catch(() => ({})); + return { error: body?.detail ?? `HTTP ${res.status}` }; + } + return res.json(); + }) + .catch((err) => { + console.error('open-terminal createNotebookSession error:', err); + return { error: 'Connection failed' }; + }); + return res; +}; + +export const executeNotebookCell = async ( + baseUrl: string, + apiKey: string, + sessionId: string, + cellIndex: number, + source?: string +): Promise<{ status: string; execution_count?: number; outputs: any[] } | { error: string }> => { + const url = `${baseUrl.replace(/\/$/, '')}/notebooks/${sessionId}/execute`; + const body: Record = { cell_index: cellIndex }; + if (source !== undefined) body.source = source; + + const res = await fetch(url, { + method: 'POST', + headers: { + Authorization: `Bearer ${apiKey}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(body) + }) + .then(async (res) => { + if (!res.ok) { + const body = await res.json().catch(() => ({})); + return { error: body?.detail ?? `HTTP ${res.status}` }; + } + return res.json(); + }) + .catch((err) => { + console.error('open-terminal executeNotebookCell error:', err); + return { error: 'Connection failed' }; + }); + return res; +}; + +export const stopNotebookSession = async ( + baseUrl: string, + apiKey: string, + sessionId: string +): Promise => { + const url = `${baseUrl.replace(/\/$/, '')}/notebooks/${sessionId}`; + const res = await fetch(url, { + method: 'DELETE', + headers: { Authorization: `Bearer ${apiKey}` } + }).catch(() => null); + return res?.ok ?? false; +}; diff --git a/src/lib/components/chat/FileNav.svelte b/src/lib/components/chat/FileNav.svelte index 7e9e977e67..12d0c9daf3 100644 --- a/src/lib/components/chat/FileNav.svelte +++ b/src/lib/components/chat/FileNav.svelte @@ -845,6 +845,8 @@ const result = await excelToTable(excelWorkbook.Sheets[sheet]); fileOfficeHtml = result.html; }} + baseUrl={selectedTerminal?.url ?? ''} + apiKey={selectedTerminal?.key ?? ''} {overlay} onSave={async (content) => { const terminal = selectedTerminal; diff --git a/src/lib/components/chat/FileNav/CellEditor.svelte b/src/lib/components/chat/FileNav/CellEditor.svelte new file mode 100644 index 0000000000..f39b3bba33 --- /dev/null +++ b/src/lib/components/chat/FileNav/CellEditor.svelte @@ -0,0 +1,109 @@ + + +
+ + diff --git a/src/lib/components/chat/FileNav/FilePreview.svelte b/src/lib/components/chat/FileNav/FilePreview.svelte index c4b73e5108..5b23dc4df2 100644 --- a/src/lib/components/chat/FileNav/FilePreview.svelte +++ b/src/lib/components/chat/FileNav/FilePreview.svelte @@ -25,6 +25,10 @@ export let fileSqliteData: ArrayBuffer | null = null; export let fileContent: string | null = null; + // Terminal connection for notebook execution + export let baseUrl: string = ''; + export let apiKey: string = ''; + // Office preview props export let fileOfficeHtml: string | null = null; export let fileOfficeSlides: string[] | null = null; @@ -409,7 +413,7 @@
{:else if isNotebook && !showRaw && parsedNotebook}
- +
{:else if isJson && !showRaw && parsedJson !== undefined}
diff --git a/src/lib/components/chat/FileNav/NotebookView.svelte b/src/lib/components/chat/FileNav/NotebookView.svelte index 5c88abd0c4..a3ea8279ce 100644 --- a/src/lib/components/chat/FileNav/NotebookView.svelte +++ b/src/lib/components/chat/FileNav/NotebookView.svelte @@ -1,12 +1,23 @@
+ + {#if baseUrl && apiKey && filePath} +
+ + {#if kernelReady} + + + {/if} + +
+ +
+ {#if kernelStarting} + + {:else if runningCell !== null} + + {:else if kernelReady} + + {:else} + + {/if} +
+
+ + {#if kernelError} +
+ {kernelError} +
+ {/if} + {/if} + + {#each cells as cell, i}
{#if cell.cell_type === 'markdown'} -
- {@html renderMarkdown(toStr(cell.source))} -
+ {#if editingCell[i]} + + {:else} + +
startEditing(i)} + > + {@html renderMarkdown(toStr(cell.source))} +
+ {/if} {:else if cell.cell_type === 'code'}
-
- {#if cell.execution_count !== undefined && cell.execution_count !== null} - [{cell.execution_count}] - {:else} - [ ] +
+ {#if runningCell === i} +
+ {:else if baseUrl && apiKey && filePath} + {/if} +
+ {#if cell.execution_count !== undefined && cell.execution_count !== null} + [{cell.execution_count}] + {:else} + [ ] + {/if} +
- {#if highlightedCells[i]} -
- {@html highlightedCells[i]} -
+ {#if editingCell[i]} + { editedSources[i] = e.detail; }} + on:run={() => runCell(i)} + on:cancel={() => cancelEditing(i)} + /> {:else} -
{toStr(cell.source)}
+ +
startEditing(i)} + > + {#if highlightedCells[i]} +
+ {@html highlightedCells[i]} +
+ {:else} +
{toStr(cell.source)}
+ {/if} +
{/if} {#if cell.outputs && cell.outputs.length > 0} @@ -153,9 +363,37 @@ diff --git a/src/lib/components/chat/FileNav/FilePreview.svelte b/src/lib/components/chat/FileNav/FilePreview.svelte index 5b23dc4df2..0230017814 100644 --- a/src/lib/components/chat/FileNav/FilePreview.svelte +++ b/src/lib/components/chat/FileNav/FilePreview.svelte @@ -4,15 +4,17 @@ import { marked } from 'marked'; import DOMPurify from 'dompurify'; import { settings } from '$lib/stores'; - import { isCodeFile, highlightCode } from '$lib/utils/codeHighlight'; + import { isCodeFile } from '$lib/utils/codeHighlight'; import { initMermaid, renderMermaidDiagram } from '$lib/utils'; import Spinner from '../../common/Spinner.svelte'; import PDFViewer from '../../common/PDFViewer.svelte'; import JsonTreeView from './JsonTreeView.svelte'; import NotebookView from './NotebookView.svelte'; import SqliteView from './SqliteView.svelte'; + import FileCodeEditor from './FileCodeEditor.svelte'; let pdfViewerRef: PDFViewer; + let fileCodeEditorRef: FileCodeEditor; const i18n = getContext('i18n'); @@ -76,6 +78,15 @@ editContent = ''; }; + /** Save code file directly from CodeMirror */ + export const saveCodeFile = async () => { + if (!onSave) return; + saving = true; + const content = fileCodeEditorRef?.getValue() ?? ''; + await onSave(content); + saving = false; + }; + $: isTextFile = fileContent !== null && fileImageUrl === null && filePdfData === null; const MD_EXTS = new Set(['md', 'markdown', 'mdx']); @@ -175,24 +186,21 @@ $: csvHeader = csvRows.length > 0 ? csvRows[0] : []; $: csvBody = csvRows.length > 1 ? csvRows.slice(1) : []; - // ── Shiki code highlighting ───────────────────────────────────────── + // ── Shiki code highlighting (SVG only) ────────────────────────────── let highlightedHtml: string | null = null; - let highlightingFile: string | null = null; // track which file we're highlighting + let highlightingFile: string | null = null; - $: if ((isCode || isSvg) && fileContent !== null && selectedFile) { + $: if (isSvg && fileContent !== null && selectedFile) { const currentFile = selectedFile; highlightingFile = currentFile; - const lang = isSvg ? 'xml' : undefined; - (lang - ? import('shiki').then(({ codeToHtml }) => - codeToHtml(fileContent!, { - lang: 'xml', - themes: { light: 'github-light', dark: 'github-dark' }, - defaultColor: 'light' - }) - ) - : highlightCode(fileContent!, selectedFile!) - ) + import('shiki') + .then(({ codeToHtml }) => + codeToHtml(fileContent!, { + lang: 'xml', + themes: { light: 'github-light', dark: 'github-dark' }, + defaultColor: 'light' + }) + ) .then((html) => { if (highlightingFile === currentFile) highlightedHtml = html; }) @@ -428,7 +436,16 @@
{@html DOMPurify.sanitize(fileContent, { USE_PROFILES: { svg: true, svgFilters: true }, ADD_TAGS: ['use'] })}
- {:else if (isCode || isSvg) && highlightedHtml && !showRaw} + {:else if isCode && !showRaw} +
+ +
+ {:else if isSvg && highlightedHtml && !showRaw}
{@html highlightedHtml}
From 80376a3fdc06b15541264f1229cde7542ec2619f Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Fri, 6 Mar 2026 15:05:36 -0600 Subject: [PATCH 050/114] revert --- backend/open_webui/routers/retrieval.py | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/backend/open_webui/routers/retrieval.py b/backend/open_webui/routers/retrieval.py index a6f7cb32dd..46725ea901 100644 --- a/backend/open_webui/routers/retrieval.py +++ b/backend/open_webui/routers/retrieval.py @@ -1055,10 +1055,27 @@ async def update_rag_config( ) # File upload settings - request.app.state.config.FILE_MAX_SIZE = form_data.FILE_MAX_SIZE - request.app.state.config.FILE_MAX_COUNT = form_data.FILE_MAX_COUNT - request.app.state.config.FILE_IMAGE_COMPRESSION_WIDTH = form_data.FILE_IMAGE_COMPRESSION_WIDTH - request.app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT = form_data.FILE_IMAGE_COMPRESSION_HEIGHT + request.app.state.config.FILE_MAX_SIZE = ( + form_data.FILE_MAX_SIZE + if form_data.FILE_MAX_SIZE is not None + else request.app.state.config.FILE_MAX_SIZE + ) + request.app.state.config.FILE_MAX_COUNT = ( + form_data.FILE_MAX_COUNT + if form_data.FILE_MAX_COUNT is not None + else request.app.state.config.FILE_MAX_COUNT + ) + request.app.state.config.FILE_IMAGE_COMPRESSION_WIDTH = ( + form_data.FILE_IMAGE_COMPRESSION_WIDTH + if form_data.FILE_IMAGE_COMPRESSION_WIDTH is not None + else request.app.state.config.FILE_IMAGE_COMPRESSION_WIDTH + ) + request.app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT = ( + form_data.FILE_IMAGE_COMPRESSION_HEIGHT + if form_data.FILE_IMAGE_COMPRESSION_HEIGHT is not None + else request.app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT + ) + request.app.state.config.ALLOWED_FILE_EXTENSIONS = ( form_data.ALLOWED_FILE_EXTENSIONS if form_data.ALLOWED_FILE_EXTENSIONS is not None From 73b69ae408431c925c765178ebd647d2ae20fc98 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Fri, 6 Mar 2026 15:13:21 -0600 Subject: [PATCH 051/114] refac --- backend/open_webui/routers/retrieval.py | 46 +++++++++---------- .../admin/Settings/Documents.svelte | 6 +++ 2 files changed, 28 insertions(+), 24 deletions(-) diff --git a/backend/open_webui/routers/retrieval.py b/backend/open_webui/routers/retrieval.py index 46725ea901..3aec9c274e 100644 --- a/backend/open_webui/routers/retrieval.py +++ b/backend/open_webui/routers/retrieval.py @@ -729,10 +729,10 @@ class ConfigForm(BaseModel): CHUNK_OVERLAP: Optional[int] = None # File upload settings - FILE_MAX_SIZE: Optional[int] = None - FILE_MAX_COUNT: Optional[int] = None - FILE_IMAGE_COMPRESSION_WIDTH: Optional[int] = None - FILE_IMAGE_COMPRESSION_HEIGHT: Optional[int] = None + FILE_MAX_SIZE: Optional[Union[int, str]] = None + FILE_MAX_COUNT: Optional[Union[int, str]] = None + FILE_IMAGE_COMPRESSION_WIDTH: Optional[Union[int, str]] = None + FILE_IMAGE_COMPRESSION_HEIGHT: Optional[Union[int, str]] = None ALLOWED_FILE_EXTENSIONS: Optional[List[str]] = None # Integration settings @@ -1055,26 +1055,24 @@ async def update_rag_config( ) # File upload settings - request.app.state.config.FILE_MAX_SIZE = ( - form_data.FILE_MAX_SIZE - if form_data.FILE_MAX_SIZE is not None - else request.app.state.config.FILE_MAX_SIZE - ) - request.app.state.config.FILE_MAX_COUNT = ( - form_data.FILE_MAX_COUNT - if form_data.FILE_MAX_COUNT is not None - else request.app.state.config.FILE_MAX_COUNT - ) - request.app.state.config.FILE_IMAGE_COMPRESSION_WIDTH = ( - form_data.FILE_IMAGE_COMPRESSION_WIDTH - if form_data.FILE_IMAGE_COMPRESSION_WIDTH is not None - else request.app.state.config.FILE_IMAGE_COMPRESSION_WIDTH - ) - request.app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT = ( - form_data.FILE_IMAGE_COMPRESSION_HEIGHT - if form_data.FILE_IMAGE_COMPRESSION_HEIGHT is not None - else request.app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT - ) + # Empty string means "clear to None" (unlimited/no compression), + # None means "don't change", int means "set to this value" + if form_data.FILE_MAX_SIZE is not None: + request.app.state.config.FILE_MAX_SIZE = ( + None if form_data.FILE_MAX_SIZE == '' else form_data.FILE_MAX_SIZE + ) + if form_data.FILE_MAX_COUNT is not None: + request.app.state.config.FILE_MAX_COUNT = ( + None if form_data.FILE_MAX_COUNT == '' else form_data.FILE_MAX_COUNT + ) + if form_data.FILE_IMAGE_COMPRESSION_WIDTH is not None: + request.app.state.config.FILE_IMAGE_COMPRESSION_WIDTH = ( + None if form_data.FILE_IMAGE_COMPRESSION_WIDTH == '' else form_data.FILE_IMAGE_COMPRESSION_WIDTH + ) + if form_data.FILE_IMAGE_COMPRESSION_HEIGHT is not None: + request.app.state.config.FILE_IMAGE_COMPRESSION_HEIGHT = ( + None if form_data.FILE_IMAGE_COMPRESSION_HEIGHT == '' else form_data.FILE_IMAGE_COMPRESSION_HEIGHT + ) request.app.state.config.ALLOWED_FILE_EXTENSIONS = ( form_data.ALLOWED_FILE_EXTENSIONS diff --git a/src/lib/components/admin/Settings/Documents.svelte b/src/lib/components/admin/Settings/Documents.svelte index 78e300ae04..ece64afd54 100644 --- a/src/lib/components/admin/Settings/Documents.svelte +++ b/src/lib/components/admin/Settings/Documents.svelte @@ -221,6 +221,12 @@ const res = await updateRAGConfig(localStorage.token, { ...RAGConfig, + // Convert null (from cleared number inputs) to empty string so the backend + // can distinguish "clear this field" from "don't change this field" + FILE_MAX_SIZE: RAGConfig.FILE_MAX_SIZE ?? '', + FILE_MAX_COUNT: RAGConfig.FILE_MAX_COUNT ?? '', + FILE_IMAGE_COMPRESSION_WIDTH: RAGConfig.FILE_IMAGE_COMPRESSION_WIDTH ?? '', + FILE_IMAGE_COMPRESSION_HEIGHT: RAGConfig.FILE_IMAGE_COMPRESSION_HEIGHT ?? '', ALLOWED_FILE_EXTENSIONS: RAGConfig.ALLOWED_FILE_EXTENSIONS.split(',') .map((ext) => ext.trim()) .filter((ext) => ext !== ''), From 016928722c7a601ea8de003d91b28f5942515292 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Fri, 6 Mar 2026 15:23:29 -0600 Subject: [PATCH 052/114] refac --- src/lib/components/chat/ChatControls.svelte | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/components/chat/ChatControls.svelte b/src/lib/components/chat/ChatControls.svelte index 2f5aec4b09..0abefe2aae 100644 --- a/src/lib/components/chat/ChatControls.svelte +++ b/src/lib/components/chat/ChatControls.svelte @@ -342,7 +342,7 @@ ? 'h-full' : activeTab === 'controls' ? 'overflow-y-auto px-3 pt-1' - : 'overflow-y-auto'}" + : ''}" > {#if activeTab === 'overview'} {#if $showCallOverlay} @@ -483,7 +483,7 @@ ? 'h-full' : activeTab === 'controls' ? 'overflow-y-auto px-3 pt-1' - : 'overflow-y-auto'}" + : ''}" > {#if activeTab === 'overview'} Date: Fri, 6 Mar 2026 15:29:38 -0600 Subject: [PATCH 053/114] refac --- .../layout/Sidebar/PinnedModelList.svelte | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/lib/components/layout/Sidebar/PinnedModelList.svelte b/src/lib/components/layout/Sidebar/PinnedModelList.svelte index da35a3df3d..235dda9034 100644 --- a/src/lib/components/layout/Sidebar/PinnedModelList.svelte +++ b/src/lib/components/layout/Sidebar/PinnedModelList.svelte @@ -37,6 +37,20 @@ let unsubscribeSettings; + const cleanupStalePinnedModels = async (modelIds) => { + const validModels = modelIds.filter((id) => { + const model = $models.find((m) => m.id === id); + // Remove if model not found (deleted) or if hidden + return model && !(model?.info?.meta?.hidden ?? false); + }); + + if (validModels.length !== modelIds.length) { + pinnedModels = validModels; + settings.set({ ...$settings, pinnedModels: validModels }); + await updateUserSettings(localStorage.token, { ui: $settings }); + } + }; + onMount(async () => { pinnedModels = $settings?.pinnedModels ?? []; @@ -48,6 +62,11 @@ await updateUserSettings(localStorage.token, { ui: $settings }); } + // Auto-unpin hidden or deleted models + if (pinnedModels.length > 0) { + await cleanupStalePinnedModels(pinnedModels); + } + unsubscribeSettings = settings.subscribe((value) => { pinnedModels = value?.pinnedModels ?? []; }); From 576ee9243890e612652886d46c464e86b4f1a6f4 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Fri, 6 Mar 2026 22:36:13 +0100 Subject: [PATCH 054/114] perf: rewrite createMessagesList from recursive to iterative (#22194) Replace the recursive spread-based implementation with an iterative push+reverse approach. The recursive version created a new array at each level of recursion via spread, resulting in O(d^2) array copies where d is the conversation depth. The iterative version walks from the target message to the root, pushes each message, and reverses once at the end for O(d) total work. No behavioral change - same input produces the same output array. --- src/lib/utils/index.ts | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 4a1cf2e919..18c5c6b674 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -1181,19 +1181,19 @@ export const getWeekday = () => { }; export const createMessagesList = (history, messageId) => { - if (messageId === null) { - return []; - } + const list = []; + let currentId = messageId; - const message = history.messages[messageId]; - if (message === undefined) { - return []; - } - if (message?.parentId) { - return [...createMessagesList(history, message.parentId), message]; - } else { - return [message]; + while (currentId !== null && currentId !== undefined) { + const message = history.messages[currentId]; + if (message === undefined) { + break; + } + list.push(message); + currentId = message.parentId; } + + return list.reverse(); }; export const formatFileSize = (size) => { From 4ab831b2596f92fc247c8d788f584ae82d63a88d Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Fri, 6 Mar 2026 15:42:13 -0600 Subject: [PATCH 055/114] refac --- backend/open_webui/utils/middleware.py | 35 +++++++++++++------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 53d1a54859..27323742a4 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -4163,25 +4163,26 @@ async def flush_pending_delta_data(threshold: int = 0): tool_args = tool_call.get("function", {}).get("arguments", "{}") tool_function_params = {} - try: - # json.loads cannot be used because some models do not produce valid JSON - tool_function_params = ast.literal_eval(tool_args) - except Exception as e: - log.debug(e) - # Fallback to JSON parsing + if tool_args and tool_args.strip(): try: - tool_function_params = json.loads(tool_args) + # json.loads cannot be used because some models do not produce valid JSON + tool_function_params = ast.literal_eval(tool_args) except Exception as e: - log.error( - f"Error parsing tool call arguments: {tool_args}" - ) - results.append( - { - "tool_call_id": tool_call_id, - "content": f"Error: Tool call arguments could not be parsed. The model generated malformed or incomplete JSON for `{tool_function_name}`. Please try again.", - } - ) - continue + log.debug(e) + # Fallback to JSON parsing + try: + tool_function_params = json.loads(tool_args) + except Exception as e: + log.error( + f"Error parsing tool call arguments: {tool_args}" + ) + results.append( + { + "tool_call_id": tool_call_id, + "content": f"Error: Tool call arguments could not be parsed. The model generated malformed or incomplete JSON for `{tool_function_name}`. Please try again.", + } + ) + continue # Ensure arguments are valid JSON for downstream LLM integrations log.debug( From 200fb093b10af0dc02c185b29b686d9c780608ee Mon Sep 17 00:00:00 2001 From: Shirasawa <764798966@qq.com> Date: Sat, 7 Mar 2026 05:48:44 +0800 Subject: [PATCH 056/114] fix: Use toBlob on first mobile export to avoid black canvas image on Android (#22317) --- src/lib/utils/index.ts | 53 +++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 18c5c6b674..3b8a6a3d72 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -275,11 +275,50 @@ export const canvasPixelTest = () => { return true; }; + +let resizeImageWarmupDone = false; +/** + * Draws an image to a canvas at the given dimensions and returns a data URL. + * On mobile, the first export uses toBlob (avoids black image on Android); later exports use toDataURL. + */ +async function resizeImageToDataURL( + img: HTMLImageElement, + width: number, + height: number, + mimeType = 'image/jpeg', +): Promise { + const canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + canvas.getContext('2d')?.drawImage(img, 0, 0, width, height); + + const toDataURL = () => canvas.toDataURL(mimeType); + + if (!resizeImageWarmupDone && canvas.toBlob && /android|iphone|ipad|ipod/i.test(navigator?.userAgent)) { + resizeImageWarmupDone = true; + return new Promise((resolve) => { + canvas.toBlob( + (blob) => { + if (!blob) { + resolve(toDataURL()); + return; + } + const reader = new FileReader(); + reader.onload = () => resolve(String(reader.result)); + reader.onerror = () => resolve(toDataURL()); + reader.readAsDataURL(blob); + }, + mimeType, + ); + }); + } + return Promise.resolve(toDataURL()); +} + export const compressImage = async (imageUrl, maxWidth, maxHeight) => { return new Promise((resolve, reject) => { const img = new Image(); img.onload = () => { - const canvas = document.createElement('canvas'); let width = img.width; let height = img.height; @@ -322,16 +361,8 @@ export const compressImage = async (imageUrl, maxWidth, maxHeight) => { height = maxHeight; } - canvas.width = width; - canvas.height = height; - - const context = canvas.getContext('2d'); - context.drawImage(img, 0, 0, width, height); - - // Get compressed image URL - const mimeType = imageUrl.match(/^data:([^;]+);/)?.[1]; - const compressedUrl = canvas.toDataURL(mimeType); - resolve(compressedUrl); + const mimeType = imageUrl.match(/^data:([^;]+);/)?.[1] ?? 'image/jpeg'; + resolve(await resizeImageToDataURL(img, width, height, mimeType)); }; img.onerror = (error) => reject(error); img.src = imageUrl; From d93cb3658dae98499af10946444de54b572e8e71 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Fri, 6 Mar 2026 22:56:01 +0100 Subject: [PATCH 057/114] perf(models): batch-fetch function valves to eliminate N+1 queries (#22301) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * perf(models): batch-fetch function valves to eliminate N+1 queries get_action_priority() called Functions.get_function_valves_by_id() individually for every action on every model — an N+1 query pattern that issued one DB round-trip per (action x model) pair. Add Functions.get_function_valves_by_ids() that fetches all valves in a single WHERE IN query, then look up each action's valves from the pre-fetched dict inside get_action_priority(). No functional change — same priority resolution, same sort order. * Update models.py * Update models.py --- backend/open_webui/models/functions.py | 25 +++++++++++++++++++++++++ backend/open_webui/utils/models.py | 8 +++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/models/functions.py b/backend/open_webui/models/functions.py index fdbfac5e7c..bca1223b72 100644 --- a/backend/open_webui/models/functions.py +++ b/backend/open_webui/models/functions.py @@ -308,6 +308,31 @@ def get_function_valves_by_id( log.exception(f"Error getting function valves by id {id}: {e}") return None + def get_function_valves_by_ids( + self, ids: list[str], db: Optional[Session] = None + ) -> dict[str, dict]: + """ + Batch fetch valves for multiple functions in a single query. + Returns a dict mapping function_id -> valves dict. + Functions without valves are mapped to {}. + """ + if not ids: + return {} + try: + with get_db_context(db) as db: + functions = ( + db.query(Function.id, Function.valves) + .filter(Function.id.in_(ids)) + .all() + ) + return { + f.id: (f.valves if f.valves else {}) for f in functions + } + except Exception as e: + log.exception(f"Error batch-fetching function valves: {e}") + return {} + + def update_function_valves_by_id( self, id: str, valves: dict, db: Optional[Session] = None ) -> Optional[FunctionValves]: diff --git a/backend/open_webui/utils/models.py b/backend/open_webui/utils/models.py index 6c82b4aa98..ebf855d2cc 100644 --- a/backend/open_webui/utils/models.py +++ b/backend/open_webui/utils/models.py @@ -331,11 +331,17 @@ def get_filter_items_from_module(function, module): elif meta.get(key) is None: meta[key] = copy.deepcopy(value) + # Batch-fetch all function valves in one query to avoid N+1 DB hits + # inside get_action_priority (previously called per action × per model). + all_function_valves = Functions.get_function_valves_by_ids( + list(all_function_ids) + ) + def get_action_priority(action_id): try: function_module = request.app.state.FUNCTIONS.get(action_id) if function_module and hasattr(function_module, "Valves"): - valves_db = Functions.get_function_valves_by_id(action_id) + valves_db = all_function_valves.get(action_id) valves = function_module.Valves(**(valves_db if valves_db else {})) return getattr(valves, "priority", 0) except Exception: From d8bb8c58d04ba57d34bc0543ca9de194b5f44711 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Fri, 6 Mar 2026 16:21:42 -0600 Subject: [PATCH 058/114] refac --- .github/pull_request_template.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 9a19bfa6b4..8726cb9990 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -88,9 +88,12 @@ This is to ensure large feature PRs are discussed with the community first, befo 🚨 DO NOT DELETE THE TEXT BELOW 🚨 Keep the "Contributor License Agreement" confirmation text intact. Deleting it will trigger the CLA-Bot to INVALIDATE your PR. + +Your PR will NOT be reviewed or merged until you check the box below confirming that you have read and agree to the terms of the CLA. --> -By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms. +- [ ] By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](./CLA.md), and I am providing my contributions under its terms. + > [!NOTE] > Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in. From b3622474d7b8de618ad0f24ed6946a96e5e333a2 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Fri, 6 Mar 2026 16:25:00 -0600 Subject: [PATCH 059/114] refac --- src/lib/utils/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 3b8a6a3d72..455594b65c 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -318,7 +318,7 @@ async function resizeImageToDataURL( export const compressImage = async (imageUrl, maxWidth, maxHeight) => { return new Promise((resolve, reject) => { const img = new Image(); - img.onload = () => { + img.onload = async () => { let width = img.width; let height = img.height; From 7806cd5aef9fb0505b2c642ef70599a403cf14ba Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Fri, 6 Mar 2026 20:00:12 -0600 Subject: [PATCH 060/114] feat: use CodeMirror editor for HTML source view, hide save in preview mode - HTML preview (iframe) no longer shows Edit/Save toolbar buttons - Clicking Source toggle opens CodeMirror editor with syntax highlighting - Save button appears only in source mode, using saveCodeFile() - Ctrl+S saving supported via CodeMirror keybinding --- src/lib/components/chat/FileNav.svelte | 55 +++++++++++++------ .../chat/FileNav/FilePreview.svelte | 9 +++ 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/lib/components/chat/FileNav.svelte b/src/lib/components/chat/FileNav.svelte index fbc7568f80..80285c976b 100644 --- a/src/lib/components/chat/FileNav.svelte +++ b/src/lib/components/chat/FileNav.svelte @@ -709,24 +709,43 @@ {/if} {#if isTextFile} - {#if isCode} - - - - {:else if editing} + {#if isHtml && showRaw} + + + + {:else if isHtml} + + {:else if isCode} + + + + {:else if editing} - - {:else if isHtml} - - {:else if isCode} - - - - {:else if editing} + {#if isHtml && showRaw} + + + + {:else if isHtml} + + {:else if isCode} + + + + {:else if editing}
{:else if fileOfficeSlides !== null && fileOfficeSlides.length > 0}
-
+
Slide {currentSlide + 1}
{#if fileOfficeSlides.length > 1} -
+
{currentSlide + 1} / {fileOfficeSlides.length}
@@ -402,8 +425,8 @@ {@html renderedHtml}
{:else if isCsv && !showRaw && csvRows.length > 0} -
- +
+
@@ -439,11 +462,15 @@ {:else if isJson && !showRaw && jsonError}
JSON parse error: {jsonError}
-
{fileContent}
+
{fileContent}
{:else if isSvg && !showRaw && fileContent}
- {@html DOMPurify.sanitize(fileContent, { USE_PROFILES: { svg: true, svgFilters: true }, ADD_TAGS: ['use'] })} + {@html DOMPurify.sanitize(fileContent, { + USE_PROFILES: { svg: true, svgFilters: true }, + ADD_TAGS: ['use'] + })}
{:else if isCode && !showRaw}
@@ -631,12 +658,29 @@ max-width: 100%; height: auto; } - :global(.office-preview h1) { font-size: 1.5rem; font-weight: 700; margin: 0.75em 0 0.5em; } - :global(.office-preview h2) { font-size: 1.25rem; font-weight: 600; margin: 0.75em 0 0.5em; } - :global(.office-preview h3) { font-size: 1.1rem; font-weight: 600; margin: 0.5em 0 0.25em; } - :global(.office-preview p) { margin: 0.25em 0; } + :global(.office-preview h1) { + font-size: 1.5rem; + font-weight: 700; + margin: 0.75em 0 0.5em; + } + :global(.office-preview h2) { + font-size: 1.25rem; + font-weight: 600; + margin: 0.75em 0 0.5em; + } + :global(.office-preview h3) { + font-size: 1.1rem; + font-weight: 600; + margin: 0.5em 0 0.25em; + } + :global(.office-preview p) { + margin: 0.25em 0; + } :global(.office-preview ul), - :global(.office-preview ol) { padding-left: 1.5em; margin: 0.5em 0; } + :global(.office-preview ol) { + padding-left: 1.5em; + margin: 0.5em 0; + } /* ── Shiki code highlighting ─────────────────────────────────── */ .shiki-preview :global(pre.shiki) { margin: 0; @@ -679,4 +723,3 @@ text-decoration: var(--shiki-dark-text-decoration) !important; } - diff --git a/src/lib/components/chat/FileNav/JsonTreeView.svelte b/src/lib/components/chat/FileNav/JsonTreeView.svelte index a76f4f06e2..47e94564d6 100644 --- a/src/lib/components/chat/FileNav/JsonTreeView.svelte +++ b/src/lib/components/chat/FileNav/JsonTreeView.svelte @@ -39,7 +39,13 @@
{#each entries as [k, v], i}
- + {#if i < entries.length - 1},{/if}
{/each} diff --git a/src/lib/components/chat/FileNav/NotebookView.svelte b/src/lib/components/chat/FileNav/NotebookView.svelte index a3ea8279ce..7fcff1b8c1 100644 --- a/src/lib/components/chat/FileNav/NotebookView.svelte +++ b/src/lib/components/chat/FileNav/NotebookView.svelte @@ -38,11 +38,12 @@ $: cells = (notebook?.cells as NotebookCell[]) ?? []; $: lang = (notebook?.metadata as Record)?.kernelspec - ? ((notebook.metadata as Record>).kernelspec?.language ?? 'python') + ? ((notebook.metadata as Record>).kernelspec?.language ?? + 'python') : 'python'; const toStr = (s: string[] | string | undefined): string => - Array.isArray(s) ? s.join('') : s ?? ''; + Array.isArray(s) ? s.join('') : (s ?? ''); // ── Syntax highlighting ────────────────────────────────────────────── let highlightedCells: Record = {}; @@ -75,8 +76,7 @@ const renderMarkdown = (src: string): string => DOMPurify.sanitize(marked.parse(src, { async: false }) as string); - const stripAnsi = (s: string): string => - s.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, ''); + const stripAnsi = (s: string): string => s.replace(/\x1b\[[0-9;]*[a-zA-Z]/g, ''); const getOutputImages = (output: NotebookOutput): string[] => { if (!output.data) return []; @@ -173,12 +173,14 @@ const result = await executeNotebookCell(baseUrl, apiKey, sessionId!, index, source); if ('error' in result) { - cells[index].outputs = [{ - output_type: 'error', - ename: 'ExecutionError', - evalue: result.error, - traceback: [result.error] - }]; + cells[index].outputs = [ + { + output_type: 'error', + ename: 'ExecutionError', + evalue: result.error, + traceback: [result.error] + } + ]; } else { cells[index].outputs = result.outputs; if (result.execution_count !== undefined) { @@ -225,7 +227,13 @@ {$i18n.t('Run All')} {#if kernelReady} -
{#if kernelError} -
+
{kernelError}
{/if} @@ -265,7 +284,9 @@ bind:value={editedSources[i]} on:input={autoResize} on:blur={() => cancelEditing(i)} - on:keydown={(e) => { if (e.key === 'Escape') cancelEditing(i); }} + on:keydown={(e) => { + if (e.key === 'Escape') cancelEditing(i); + }} > {:else} @@ -290,8 +311,19 @@ disabled={runningCell !== null} title="Run cell (⌘+Enter)" > - - + + {/if} @@ -308,7 +340,9 @@ { editedSources[i] = e.detail; }} + on:change={(e) => { + editedSources[i] = e.detail; + }} on:run={() => runCell(i)} on:cancel={() => cancelEditing(i)} /> @@ -334,7 +368,9 @@
{#each cell.outputs as output} {#if output.output_type === 'error'} -
{stripAnsi((output.traceback ?? []).join('\n') || `${output.ename}: ${output.evalue}`)}
+
{stripAnsi(
+												(output.traceback ?? []).join('\n') || `${output.ename}: ${output.evalue}`
+											)}
{:else} {@const html = getOutputHtml(output)} {@const images = getOutputImages(output)} @@ -401,10 +437,18 @@ padding-top: 0.5rem; padding-bottom: 0.5rem; } - .nb-markdown :global(h1) { font-size: 1.4rem; } - .nb-markdown :global(h2) { font-size: 1.2rem; } - .nb-markdown :global(h3) { font-size: 1.05rem; } - .nb-markdown :global(p) { margin: 0.4em 0; } + .nb-markdown :global(h1) { + font-size: 1.4rem; + } + .nb-markdown :global(h2) { + font-size: 1.2rem; + } + .nb-markdown :global(h3) { + font-size: 1.05rem; + } + .nb-markdown :global(p) { + margin: 0.4em 0; + } .nb-markdown :global(pre) { background: rgba(128, 128, 128, 0.06); padding: 0.5rem 0.75rem; @@ -495,7 +539,8 @@ background: #161b22; color: #e6edf3; } - .nb-code-textarea, .nb-edit-textarea { + .nb-code-textarea, + .nb-edit-textarea { width: 100%; padding: 0.5rem 0.75rem; font-size: 0.75rem; diff --git a/src/lib/components/chat/FileNav/PortList.svelte b/src/lib/components/chat/FileNav/PortList.svelte index 557b8150f1..8a5dfb3cd2 100644 --- a/src/lib/components/chat/FileNav/PortList.svelte +++ b/src/lib/components/chat/FileNav/PortList.svelte @@ -67,33 +67,33 @@ {$i18n.t('Ports')} - {#if ports.length > 0} - - {ports.length} - - {/if} - - - + {ports.length} + + {/if} + + + @@ -112,9 +112,7 @@ :{port.port} - + {port.process ?? ''} 0) { rows = result[0].values.map((r: any[]) => r.map((v: any) => formatValue(v))); } else { @@ -119,7 +117,9 @@ onDestroy(() => { if (db) { - try { db.close(); } catch {} + try { + db.close(); + } catch {} db = null; } }); @@ -132,7 +132,9 @@
{error}
{:else} -
+
{#each tables as table} @@ -172,9 +176,13 @@ } }} > -
+
{#if queryError} - {queryError} + {queryError} {:else} ⌘+Enter {/if} @@ -242,24 +250,50 @@ {#if totalPages > 1} -
+
{page + 1} / {totalPages} ({totalRows.toLocaleString()} rows)
diff --git a/src/lib/components/chat/Messages/ContentRenderer.svelte b/src/lib/components/chat/Messages/ContentRenderer.svelte index 8b157c8886..663fafd71c 100644 --- a/src/lib/components/chat/Messages/ContentRenderer.svelte +++ b/src/lib/components/chat/Messages/ContentRenderer.svelte @@ -205,7 +205,7 @@ ? model?.id : (selectedModels ?? []).length > 0 ? selectedModels.at(0) - : model?.id ?? null} + : (model?.id ?? null)} messages={createMessagesList(history, messageId)} onAdd={({ modelId, parentId, messages }) => { console.log(modelId, parentId, messages); diff --git a/src/lib/components/common/FileItemModal.svelte b/src/lib/components/common/FileItemModal.svelte index f61f3e1aa3..ea161a5c28 100644 --- a/src/lib/components/common/FileItemModal.svelte +++ b/src/lib/components/common/FileItemModal.svelte @@ -587,7 +587,9 @@ {#if docxError}
{docxError}
{:else if docxHtml} -
+
{@html docxHtml}
{:else} @@ -611,20 +613,39 @@ {pptxCurrentSlide + 1} / {pptxSlides.length}
diff --git a/src/lib/i18n/locales/ar-BH/translation.json b/src/lib/i18n/locales/ar-BH/translation.json index 24df9be05f..3adfdfc6d5 100644 --- a/src/lib/i18n/locales/ar-BH/translation.json +++ b/src/lib/i18n/locales/ar-BH/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "المحادثة", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "UI الدردشة", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "فشل في قراءة محتويات الحافظة", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "لا توجد نتائج", "No results found": "لا توجد نتايج", "No search query generated": "لم يتم إنشاء استعلام بحث", + "No servers detected": "", "No skills found": "", "No source available": "لا يوجد مصدر متاح", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "موقف ايجابي", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "النتيجة", "Retrieval": "", @@ -1587,6 +1595,7 @@ "Role": "منصب", "RTL": "من اليمين إلى اليسار", "Run": "", + "Run All": "", "Running": "", "Running...": "جارٍ التنفيذ...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1777,6 +1786,7 @@ "Start a new conversation": "", "Start of the channel": "بداية القناة", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2121,6 +2131,8 @@ "You're now logged in.": "لقد قمت الآن بتسجيل الدخول.", "Your Account": "", "Your account status is currently pending activation.": "", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/ar/translation.json b/src/lib/i18n/locales/ar/translation.json index d3a392666a..4d6927b51c 100644 --- a/src/lib/i18n/locales/ar/translation.json +++ b/src/lib/i18n/locales/ar/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "حد الأحرف لمدخل توليد الإكمال التلقائي", "Chart new frontiers": "رسم آفاق جديدة", "Chat": "محادثة", + "Chat archived.": "", "Chat Background Image": "صورة خلفية المحادثة", "Chat Bubble UI": "واجهة فقاعات المحادثة", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "فشل في إضافة الملف.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "فشل في قراءة محتويات الحافظة", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "لم يتم العثور على محتوى HTML أو CSS أو JavaScript.", "No inference engine with management support found": "لم يتم العثور على محرك استدلال يدعم الإدارة", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "لم يتم العثور على معرفة", "No memories to clear": "لا توجد ذاكرة لمسحها", @@ -1320,6 +1325,7 @@ "No results": "لا توجد نتائج", "No results found": "لا توجد نتايج", "No search query generated": "لم يتم إنشاء استعلام بحث", + "No servers detected": "", "No skills found": "", "No source available": "لا يوجد مصدر متاح", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "المنفذ", + "Ports": "", "Positive attitude": "موقف ايجابي", "Prefer not to say": "", "Prefix ID": "معرف البادئة", @@ -1571,6 +1578,7 @@ "Response splitting": "تقسيم الرد", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "النتيجة", "RESULT": "النتيجة", "Retrieval": "الاسترجاع", @@ -1587,6 +1595,7 @@ "Role": "منصب", "RTL": "من اليمين إلى اليسار", "Run": "تنفيذ", + "Run All": "", "Running": "جارٍ التنفيذ", "Running...": "جارٍ التنفيذ...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1777,6 +1786,7 @@ "Start a new conversation": "", "Start of the channel": "بداية القناة", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2121,6 +2131,8 @@ "You're now logged in.": "لقد قمت الآن بتسجيل الدخول.", "Your Account": "", "Your account status is currently pending activation.": "حالة حسابك حالياً بانتظار التفعيل.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "سيتم توجيه كامل مساهمتك مباشرة إلى مطور المكون الإضافي؛ لا تأخذ Open WebUI أي نسبة. ومع ذلك، قد تفرض منصة التمويل المختارة رسومًا خاصة بها.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/bg-BG/translation.json b/src/lib/i18n/locales/bg-BG/translation.json index 31a13b8893..f6792cb8fd 100644 --- a/src/lib/i18n/locales/bg-BG/translation.json +++ b/src/lib/i18n/locales/bg-BG/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Ограничение на символите за входа на генериране на автоматично довършване", "Chart new frontiers": "Начертайте нови граници", "Chat": "Чат", + "Chat archived.": "", "Chat Background Image": "Фоново изображение на чата", "Chat Bubble UI": "Потребителски интерфейс за чат балон", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Неуспешно добавяне на файл.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Грешка при четене на съдържанието от клипборда", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Не е намерено HTML, CSS или JavaScript съдържание.", "No inference engine with management support found": "Не е намерен механизъм за извод с поддръжка на управлението", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Не са намерени знания", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Няма намерени резултати", "No results found": "Няма намерени резултати", "No search query generated": "Не е генерирана заявка за търсене", + "No servers detected": "", "No skills found": "", "No source available": "Няма наличен източник", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Порт", + "Ports": "", "Positive attitude": "Позитивно отношение", "Prefer not to say": "", "Prefix ID": "Префикс ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Разделяне на отговора", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "Резултат", "RESULT": "Резултат", "Retrieval": "Извличане", @@ -1583,6 +1591,7 @@ "Role": "Роля", "RTL": "RTL", "Run": "Изпълни", + "Run All": "", "Running": "Изпълнява се", "Running...": "Изпълнява се...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Начало на канала", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Сега вие влязохте в системата.", "Your Account": "", "Your account status is currently pending activation.": "Статусът на вашия акаунт в момента очаква активиране.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Цялата ви вноска ще отиде директно при разработчика на плъгина; Open WebUI не взима никакъв процент. Въпреки това, избраната платформа за финансиране може да има свои собствени такси.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/bn-BD/translation.json b/src/lib/i18n/locales/bn-BD/translation.json index 1c4808b5de..a348795018 100644 --- a/src/lib/i18n/locales/bn-BD/translation.json +++ b/src/lib/i18n/locales/bn-BD/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "চ্যাট", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "চ্যাট বাবল UI", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "ক্লিপবোর্ডের বিষয়বস্তু পড়া সম্ভব হয়নি", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "কোন ফলাফল পাওয়া যায়নি", "No results found": "কোন ফলাফল পাওয়া যায়নি", "No search query generated": "কোনও অনুসন্ধান ক্যোয়ারী উত্পন্ন হয়নি", + "No servers detected": "", "No skills found": "", "No source available": "কোন উৎস পাওয়া যায়নি", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "পজিটিভ আক্রমণ", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "ফলাফল", "Retrieval": "", @@ -1583,6 +1591,7 @@ "Role": "পদবি", "RTL": "RTL", "Run": "", + "Run All": "", "Running": "", "Running...": "চলমান...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "চ্যানেলের শুরু", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "আপনি এখন লগইন করা অবস্থায় আছেন", "Your Account": "", "Your account status is currently pending activation.": "", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/bo-TB/translation.json b/src/lib/i18n/locales/bo-TB/translation.json index 22991d9e4e..8288ca9fcc 100644 --- a/src/lib/i18n/locales/bo-TB/translation.json +++ b/src/lib/i18n/locales/bo-TB/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "རང་འཚང་བཟོ་སྐྲུན་ནང་འཇུག་གི་ཡིག་འབྲུ་ཚད་བཀག", "Chart new frontiers": "ས་མཚམས་གསར་པ་འགོད་པ།", "Chat": "ཁ་བརྡ།", + "Chat archived.": "", "Chat Background Image": "ཁ་བརྡའི་རྒྱབ་ལྗོངས་པར།", "Chat Bubble UI": "ཁ་བརྡའི་ལྦུ་བའི་ UI", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "ཡིག་ཆ་སྣོན་པར་མ་ཐུབ།", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "{{URL}} OpenAPI ལག་ཆའི་སར་བར་ལ་སྦྲེལ་མཐུད་བྱེད་མ་ཐུབ།", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "སྦྱར་སྡེར་གྱི་ནང་དོན་ཀློག་མ་ཐུབ།", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "HTML, CSS, ཡང་ན་ JavaScript གི་ནང་དོན་མ་རྙེད།", "No inference engine with management support found": "དོ་དམ་རྒྱབ་སྐྱོར་ཡོད་པའི་དཔོག་རྩིས་འཕྲུལ་འཁོར་མ་རྙེད།", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "ཤེས་བྱ་མ་རྙེད།", "No memories to clear": "གཙང་སེལ་བྱེད་རྒྱུའི་དྲན་ཤེས་མེད།", @@ -1320,6 +1325,7 @@ "No results": "འབྲས་བུ་མ་རྙེད།", "No results found": "འབྲས་བུ་མ་རྙེད།", "No search query generated": "འཚོལ་བཤེར་འདྲི་བ་བཟོས་མེད།", + "No servers detected": "", "No skills found": "", "No source available": "འབྱུང་ཁུངས་མེད།", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Port", + "Ports": "", "Positive attitude": "ལྟ་སྟངས་དགེ་མཚན།", "Prefer not to say": "", "Prefix ID": "སྔོན་སྦྱོར་ ID", @@ -1571,6 +1578,7 @@ "Response splitting": "ལན་བགོ་བ།", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "འབྲས་བུ།", "RESULT": "འབྲས་བུ།", "Retrieval": "ལེན་ཚུར་སྒྲུབ།", @@ -1582,6 +1590,7 @@ "Role": "གནས་ཚད།", "RTL": "RTL", "Run": "ལག་བསྟར།", + "Run All": "", "Running": "ལག་བསྟར་བྱེད་བཞིན་པ།", "Running...": "ལག་བསྟར་བྱེད་བཞིན་པ།...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1772,6 +1781,7 @@ "Start a new conversation": "", "Start of the channel": "རྒྱས་ལམ་འགོ་རིམ་", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2116,6 +2126,8 @@ "You're now logged in.": "ཁྱེད་ད་ལྟ་ནང་འཛུལ་བྱས་ཟིན།", "Your Account": "", "Your account status is currently pending activation.": "ཁྱེད་ཀྱི་རྩིས་ཁྲའི་གནས་སྟངས་ད་ལྟ་སྒུལ་བསྐྱོད་སྒུག་བཞིན་པ།", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "ཁྱེད་ཀྱི་ཞལ་འདེབས་ཆ་ཚང་ཐད་ཀར་ plugin གསར་སྤེལ་བ་ལ་འགྲོ་ངེས། Open WebUI ཡིས་བརྒྱ་ཆ་གང་ཡང་མི་ལེན། འོན་ཀྱང་། གདམ་ཟིན་པའི་མ་དངུལ་གཏོང་བའི་སྟེགས་བུ་ལ་དེའི་རང་གི་འགྲོ་གྲོན་ཡོད་སྲིད།", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/bs-BA/translation.json b/src/lib/i18n/locales/bs-BA/translation.json index 7ad5248c05..bc8773f0d1 100644 --- a/src/lib/i18n/locales/bs-BA/translation.json +++ b/src/lib/i18n/locales/bs-BA/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "Razgovor", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "Razgovor - Bubble UI", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Neuspješno čitanje sadržaja međuspremnika", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Nema rezultata", "No results found": "Nema rezultata", "No search query generated": "Nije generiran upit za pretraživanje", + "No servers detected": "", "No skills found": "", "No source available": "Nema dostupnog izvora", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "Pozitivan stav", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "REZULTAT", "Retrieval": "", @@ -1584,6 +1592,7 @@ "Role": "Uloga", "RTL": "RTL", "Run": "", + "Run All": "", "Running": "Pokrenuto", "Running...": "Pokrenuto...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1774,6 +1783,7 @@ "Start a new conversation": "", "Start of the channel": "Početak kanala", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2118,6 +2128,8 @@ "You're now logged in.": "Sada ste prijavljeni.", "Your Account": "", "Your account status is currently pending activation.": "Status vašeg računa trenutno čeka aktivaciju.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/ca-ES/translation.json b/src/lib/i18n/locales/ca-ES/translation.json index 2c2609e1d2..b1b621ebfe 100644 --- a/src/lib/i18n/locales/ca-ES/translation.json +++ b/src/lib/i18n/locales/ca-ES/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Límit de caràcters per a l'entrada de generació automàtica", "Chart new frontiers": "Traça noves fronteres", "Chat": "Xat", + "Chat archived.": "", "Chat Background Image": "Imatge de fons del xat", "Chat Bubble UI": "Chat Bubble UI", "Chat Completions": "Completacions de xat", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Efecte de fos a negre per al text en streaming", "Failed to add file.": "No s'ha pogut afegir l'arxiu.", "Failed to add members": "No s'han pogut afegir el membres", + "Failed to archive chat.": "", "Failed to attach file": "No s'ha pogut adjuntar l'arxiu", "Failed to clear status": "No s'ha pogut esborar l'estat", "Failed to connect to {{URL}} OpenAPI tool server": "No s'ha pogut connecta al servidor d'eines OpenAPI {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "No s'ha pogut generar el títol", "Failed to import models": "No s'han pogut importar el models", "Failed to load chat preview": "No s'ha pogut carregar la previsualització del xat", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "No s'ha pogut carregar el fitxer Excel/CSV. Si us plau, prova de descarregar-lo.", "Failed to load file content.": "No s'ha pogut carregar el contingut del fitxer", "Failed to load Interface settings": "No s'ha pogut carregar la configuració de la interficie", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "No s'ha pogut moure el xat", "Failed to process URL: {{url}}": "No s'ha pogut processar la URL: {{url}}", "Failed to read clipboard contents": "No s'ha pogut llegir el contingut del porta-retalls", @@ -1305,6 +1309,7 @@ "No history available": "No hi ha historial disponible", "No HTML, CSS, or JavaScript content found.": "No s'ha trobat contingut HTML, CSS o JavaScript.", "No inference engine with management support found": "No s'ha trobat un motor d'inferència amb suport de gestió", + "No kernel": "", "No knowledge bases found.": "No s'han trobat bases de coneixement.", "No knowledge found": "No s'ha trobat Coneixement", "No memories to clear": "No hi ha memòries per netejar", @@ -1320,6 +1325,7 @@ "No results": "No s'han trobat resultats", "No results found": "No s'han trobat resultats", "No search query generated": "No s'ha generat cap consulta", + "No servers detected": "", "No skills found": "No s'han trobat habilitats", "No source available": "Sense font disponible", "No sources found": "No s'han trobat fonts", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "Selecciona com a mínim un usuari per al canal de missatge directe.", "Please wait until all files are uploaded.": "Si us plau, espera fins que s'hagin carregat tots els fitxers.", "Port": "Port", + "Ports": "", "Positive attitude": "Actitud positiva", "Prefer not to say": "Prefereixo no dir-ho", "Prefix ID": "Identificador del prefix", @@ -1571,6 +1578,7 @@ "Response splitting": "Divisió de la resposta", "Response Watermark": "Marca d'aigua de la resposta", "Responses": "Respostes", + "Restart": "", "Result": "Resultat", "RESULT": "Resultat", "Retrieval": "Retrieval", @@ -1584,6 +1592,7 @@ "Role": "Rol", "RTL": "RTL", "Run": "Executar", + "Run All": "", "Running": "S'està executant", "Running...": "S'està executant...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "Executa tasques d'incrustació simultàniament per accelerar el processament. Desactiva-ho si els límits de velocitat es converteixen en un problema.", @@ -1774,6 +1783,7 @@ "Start a new conversation": "Iniciar una nova conversa", "Start of the channel": "Inici del canal", "Start Tag": "Etiqueta d'inici", + "Starting kernel...": "", "Status": "Estat", "Status cleared successfully": "S'ha eliminat correctament el teu estat", "Status updated successfully": "S'ha actualitzat correctament el teu estat", @@ -2118,6 +2128,8 @@ "You're now logged in.": "Ara estàs connectat.", "Your Account": "El teu compte", "Your account status is currently pending activation.": "El compte està actualment pendent d'activació", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Tota la teva contribució anirà directament al desenvolupador del complement; Open WebUI no se'n queda cap percentatge. Tanmateix, la plataforma de finançament escollida pot tenir les seves pròpies comissions.", "Your message text or inputs": "El text o les entrades del teu missatge", "Your usage stats have been successfully synced.": "Les teves estadístiques d'ús s'han sincronitzat correctament.", diff --git a/src/lib/i18n/locales/ceb-PH/translation.json b/src/lib/i18n/locales/ceb-PH/translation.json index e094ff8360..098776cc6d 100644 --- a/src/lib/i18n/locales/ceb-PH/translation.json +++ b/src/lib/i18n/locales/ceb-PH/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "Panaghisgot", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Napakyas sa pagbasa sa sulod sa clipboard", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Walay resulta", "No results found": "", "No search query generated": "", + "No servers detected": "", "No skills found": "", "No source available": "Walay tinubdan nga anaa", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "RESULTA", "Retrieval": "", @@ -1583,6 +1591,7 @@ "Role": "Papel", "RTL": "", "Run": "", + "Run All": "", "Running": "", "Running...": "Nagdagan...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Sinugdan sa channel", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Konektado ka na karon.", "Your Account": "", "Your account status is currently pending activation.": "", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/cs-CZ/translation.json b/src/lib/i18n/locales/cs-CZ/translation.json index eae230e54a..e3d2f4ba85 100644 --- a/src/lib/i18n/locales/cs-CZ/translation.json +++ b/src/lib/i18n/locales/cs-CZ/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Limit znaků pro vstup generování automatického dokončování", "Chart new frontiers": "Objevujte nové hranice", "Chat": "Konverzace", + "Chat archived.": "", "Chat Background Image": "Obrázek pozadí konverzace", "Chat Bubble UI": "Uživatelské rozhraní s bublinami konverzace", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Efekt prolínání pro streamovaný text", "Failed to add file.": "Nepodařilo se přidat soubor.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Nepodařilo se připojit k serveru nástrojů OpenAPI {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "Nepodařilo se vygenerovat název", "Failed to import models": "", "Failed to load chat preview": "Nepodařilo se načíst náhled konverzace", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "Nepodařilo se načíst obsah souboru.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Nepodařilo se přečíst obsah schránky", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Nebyl nalezen žádný obsah HTML, CSS ani JavaScriptu.", "No inference engine with management support found": "Nebyl nalezeno žádné inferenční jádro s podporou správy", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Nebyly nalezeny žádné znalosti", "No memories to clear": "Žádné vzpomínky k vymazání", @@ -1320,6 +1325,7 @@ "No results": "Nebyly nalezeny žádné výsledky", "No results found": "Nebyly nalezeny žádné výsledky", "No search query generated": "Nebyl vygenerován žádný vyhledávací dotaz.", + "No servers detected": "", "No skills found": "", "No source available": "Není k dispozici žádný zdroj.", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "Prosím počkejte dokud nebudou všechny soubory nahrány.", "Port": "Port", + "Ports": "", "Positive attitude": "Pozitivní přístup", "Prefer not to say": "Raději nevyberu", "Prefix ID": "Prefix ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Dělení odpovědi", "Response Watermark": "Vodoznak odpovědi", "Responses": "", + "Restart": "", "Result": "Výsledek", "RESULT": "Výsledek", "Retrieval": "Vyhledávání", @@ -1585,6 +1593,7 @@ "Role": "Role", "RTL": "RTL", "Run": "Spustit", + "Run All": "", "Running": "Běží", "Running...": "Běží...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1775,6 +1784,7 @@ "Start a new conversation": "", "Start of the channel": "Začátek kanálu", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2119,6 +2129,8 @@ "You're now logged in.": "Nyní jste přihlášeni.", "Your Account": "Váš účet", "Your account status is currently pending activation.": "Stav vašeho účtu aktuálně čeká na aktivaci.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Celý váš příspěvek půjde přímo vývojáři pluginu; Open WebUI si nebere žádné procento. Zvolená platforma pro financování však může mít vlastní poplatky.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/da-DK/translation.json b/src/lib/i18n/locales/da-DK/translation.json index 3ec07a868a..ecb07cafa5 100644 --- a/src/lib/i18n/locales/da-DK/translation.json +++ b/src/lib/i18n/locales/da-DK/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Karaktergrænse for genereret autofuldførsel", "Chart new frontiers": "Udforsk nye grænser", "Chat": "Chat", + "Chat archived.": "", "Chat Background Image": "Chat baggrundsbillede", "Chat Bubble UI": "Chat Bubble UI", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Fade-effekt for streaming tekst", "Failed to add file.": "Kunne ikke tilføje fil.", "Failed to add members": "Kunne ikke tilføje medlemmer", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "Kunne ikke fjerne status", "Failed to connect to {{URL}} OpenAPI tool server": "Kunne ikke forbinde til {{URL}} OpenAPI tool server", @@ -836,9 +838,11 @@ "Failed to generate title": "Kunne ikke generere titel", "Failed to import models": "Kunne ikke importere modeller", "Failed to load chat preview": "Kunne ikke indlæse chat forhåndsvisning", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "Kunne ikke indlæse filindhold.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Kunne ikke flytte chat", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Kunne ikke læse indholdet af udklipsholderen", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Intet HTML-, CSS- eller JavaScript-indhold fundet.", "No inference engine with management support found": "Ingen inference-engine med støtte til administration fundet", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Ingen viden fundet", "No memories to clear": "Ingen hukommelser at ryde", @@ -1320,6 +1325,7 @@ "No results": "Ingen resultater fundet", "No results found": "Ingen resultater fundet", "No search query generated": "Ingen søgeforespørgsel genereret", + "No servers detected": "", "No skills found": "", "No source available": "Ingen kilde tilgængelig", "No sources found": "Ingen kilder fundet", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "Vælg mindst én bruger til direkte besked-kanal.", "Please wait until all files are uploaded.": "Vent venligst indtil alle filerne er uploadet.", "Port": "Port", + "Ports": "", "Positive attitude": "Positiv holdning", "Prefer not to say": "Foretrækker ikke at oplyse", "Prefix ID": "Prefix ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Svaropdeling", "Response Watermark": "Vandmærke på svar", "Responses": "", + "Restart": "", "Result": "Resultat", "RESULT": "Resultat", "Retrieval": "Hentning", @@ -1583,6 +1591,7 @@ "Role": "Rolle", "RTL": "RTL", "Run": "Kør", + "Run All": "", "Running": "Kører", "Running...": "Kører...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "Kører embedding-opgaver sideløbende for at fremskynde behandlingen. Slå fra hvis hastighedsbegrænsninger bliver et problem.", @@ -1773,6 +1782,7 @@ "Start a new conversation": "Start en ny samtale", "Start of the channel": "Kanalens start", "Start Tag": "Start tag", + "Starting kernel...": "", "Status": "Status", "Status cleared successfully": "Status slettet", "Status updated successfully": "Status opdateret", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Du er nu logget ind.", "Your Account": "Din bruger", "Your account status is currently pending activation.": "Din kontostatus afventer i øjeblikket aktivering.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Hele dit bidrag går direkte til plugin-udvikleren; Open WebUI tager ikke nogen procentdel. Den valgte finansieringsplatform kan dog have sine egne gebyrer.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/de-DE/translation.json b/src/lib/i18n/locales/de-DE/translation.json index e137bd9401..21e871c778 100644 --- a/src/lib/i18n/locales/de-DE/translation.json +++ b/src/lib/i18n/locales/de-DE/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Zeichenlimit für Eingabe der Autovervollständigung", "Chart new frontiers": "Neue Grenzen erkunden", "Chat": "Chat", + "Chat archived.": "", "Chat Background Image": "Hintergrundbild des Chats", "Chat Bubble UI": "Sprechblasen-Ansicht", "Chat Completions": "Chat Completions", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Fade-Effekt für Text-Streaming", "Failed to add file.": "Hinzufügen der Datei fehlgeschlagen.", "Failed to add members": "Mitglieder konnten nicht hinzugefügt werden", + "Failed to archive chat.": "", "Failed to attach file": "Datei konnte nicht hinzugefügt werden", "Failed to clear status": "Status konnte nicht geleert werden", "Failed to connect to {{URL}} OpenAPI tool server": "Verbindung zum OpenAPI-Toolserver {{URL}} fehlgeschlagen", @@ -836,9 +838,11 @@ "Failed to generate title": "Titel konnte nicht generiert werden", "Failed to import models": "Modelle konnten nicht importiert werden", "Failed to load chat preview": "Chat-Vorschau konnte nicht geladen werden", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV-Datei konnte nicht geladen werden. Bitte versuchen Sie stattdessen, sie herunterzuladen.", "Failed to load file content.": "Dateiinhalt konnte nicht geladen werden.", "Failed to load Interface settings": "Interface Einstellungen konnten nicht geladen werden", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Chat konnte nicht verschoben werden", "Failed to process URL: {{url}}": "{{url}} konnte nicht verarbeitet werden", "Failed to read clipboard contents": "Zwischenablage konnte nicht gelesen werden", @@ -1305,6 +1309,7 @@ "No history available": "Keine History verfügbar", "No HTML, CSS, or JavaScript content found.": "Keine HTML-, CSS- oder JavaScript-Inhalte gefunden.", "No inference engine with management support found": "Keine Inferenz-Engine mit Verwaltungsunterstützung gefunden", + "No kernel": "", "No knowledge bases found.": "Keine Wissensspeicher gefunden.", "No knowledge found": "Kein Wissen gefunden", "No memories to clear": "Keine Erinnerungen zum Löschen", @@ -1320,6 +1325,7 @@ "No results": "Keine Ergebnisse", "No results found": "Keine Ergebnisse gefunden", "No search query generated": "Keine Suchanfrage generiert", + "No servers detected": "", "No skills found": "Keine Skills gefunden", "No source available": "Keine Quelle verfügbar", "No sources found": "Keine Quellen gefunden", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "Bitte wählen Sie mindestens einen Benutzer für den Direktnachrichten-Kanal aus.", "Please wait until all files are uploaded.": "Bitte warten Sie, bis alle Dateien hochgeladen sind.", "Port": "Port", + "Ports": "", "Positive attitude": "Positive Einstellung", "Prefer not to say": "Keine Angabe", "Prefix ID": "Präfix-ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Antwortaufteilung", "Response Watermark": "Antwort-Wasserzeichen", "Responses": "Responses", + "Restart": "", "Result": "Ergebnis", "RESULT": "ERGEBNIS", "Retrieval": "Abruf", @@ -1583,6 +1591,7 @@ "Role": "Rolle", "RTL": "RTL", "Run": "Ausführen", + "Run All": "", "Running": "Läuft", "Running...": "Läuft...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "Führt Embedding-Aufgaben parallel aus, um die Verarbeitung zu beschleunigen. Deaktivieren Sie dies, falls Rate-Limits oder Ressourcenprobleme auftreten.", @@ -1773,6 +1782,7 @@ "Start a new conversation": "Neue Unterhaltung beginnen", "Start of the channel": "Beginn des Kanals", "Start Tag": "Start-Tag", + "Starting kernel...": "", "Status": "Status", "Status cleared successfully": "Status erfolgreich gelöscht", "Status updated successfully": "Status erfolgreich aktualisiert", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Sie sind jetzt angemeldet.", "Your Account": "Ihr Konto", "Your account status is currently pending activation.": "Ihr Kontostatus wartet derzeit auf Aktivierung.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Ihr gesamter Beitrag geht direkt an den Plugin-Entwickler; Open WebUI behält keinen Anteil ein. Die gewählte Plattform kann jedoch eigene Gebühren erheben.", "Your message text or inputs": "Ihre Nachrichtentexte oder Eingaben", "Your usage stats have been successfully synced.": "Ihre Nutzungsstatistiken wurden erfolgreich synchronisiert.", diff --git a/src/lib/i18n/locales/dg-DG/translation.json b/src/lib/i18n/locales/dg-DG/translation.json index ff64e67a59..f530299954 100644 --- a/src/lib/i18n/locales/dg-DG/translation.json +++ b/src/lib/i18n/locales/dg-DG/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "Chat", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Failed to read clipboard borks", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "No results, very empty", "No results found": "", "No search query generated": "", + "No servers detected": "", "No skills found": "", "No source available": "No source available", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "RESULT much", "Retrieval": "", @@ -1583,6 +1591,7 @@ "Role": "Role", "RTL": "", "Run": "", + "Run All": "", "Running": "", "Running...": "Running... wow", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Start of channel", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "You're now logged in. Much logged.", "Your Account": "", "Your account status is currently pending activation.": "", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/el-GR/translation.json b/src/lib/i18n/locales/el-GR/translation.json index bcb3d60100..66db5bd86c 100644 --- a/src/lib/i18n/locales/el-GR/translation.json +++ b/src/lib/i18n/locales/el-GR/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Όριο χαρακτήρων για αυτόματη συμπλήρωση εισαγωγής", "Chart new frontiers": "Σχεδιάστε νέους ορίζοντες", "Chat": "Συνομιλία", + "Chat archived.": "", "Chat Background Image": "Εικόνα Φόντου Συνομιλίας", "Chat Bubble UI": "Διεπαφή Φούσκας Συνομιλίας", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Αποτυχία προσθήκης αρχείου.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Αποτυχία σύνδεσης στο διακομιστή εργαλείων OpenAPI {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "Αποτυχία δημιουργίας τίτλου", "Failed to import models": "Αποτυχία εισαγωγής μοντέλων", "Failed to load chat preview": "Αποτυχία φόρτωσης προεπισκόπησης συνομιλίας", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "Αποτυχία φόρτωσης περιεχομένου αρχείου", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Αποτυχία μετακίνησης συνομιλίας", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Αποτυχία ανάγνωσης περιεχομένων πρόχειρου", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Δεν βρέθηκε περιεχόμενο HTML, CSS ή JavaScript.", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Δεν βρέθηκε Knowledge", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Δεν βρέθηκαν αποτελέσματα", "No results found": "Δεν βρέθηκαν αποτελέσματα", "No search query generated": "Δεν δημιουργήθηκε ερώτηση αναζήτησης", + "No servers detected": "", "No skills found": "", "No source available": "Δεν υπάρχει διαθέσιμη πηγή", "No sources found": "Δεν βρέθηκαν πηγές", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Θύρα", + "Ports": "", "Positive attitude": "Θετική στάση", "Prefer not to say": "", "Prefix ID": "ID Προθέματος", @@ -1571,6 +1578,7 @@ "Response splitting": "Διαχωρισμός απάντησης", "Response Watermark": "Υδρογράφημα Απάντησης", "Responses": "", + "Restart": "", "Result": "Αποτέλεσμα", "RESULT": "Αποτέλεσμα", "Retrieval": "Ανάκτηση", @@ -1583,6 +1591,7 @@ "Role": "Ρόλος", "RTL": "RTL", "Run": "Εκτέλεση", + "Run All": "", "Running": "Εκτέλεση", "Running...": "Εκτέλεση...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Αρχή του καναλιού", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Τώρα είστε συνδεδεμένοι.", "Your Account": "Ο λογαριασμός σας", "Your account status is currently pending activation.": "Η κατάσταση του λογαριασμού σας είναι αυτή τη στιγμή σε εκκρεμότητα ενεργοποίησης.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Η ολόκληρη η συνεισφορά σας θα πάει απευθείας στον προγραμματιστή του plugin· το Open WebUI δεν παίρνει κανένα ποσοστό. Ωστόσο, η επιλεγμένη πλατφόρμα χρηματοδότησης μπορεί να έχει τα δικά της τέλη.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/en-GB/translation.json b/src/lib/i18n/locales/en-GB/translation.json index 392c88046d..4cc97d93cd 100644 --- a/src/lib/i18n/locales/en-GB/translation.json +++ b/src/lib/i18n/locales/en-GB/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "", "No results found": "", "No search query generated": "", + "No servers detected": "", "No skills found": "", "No source available": "", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "", "Retrieval": "", @@ -1583,6 +1591,7 @@ "Role": "", "RTL": "", "Run": "", + "Run All": "", "Running": "", "Running...": "", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "", "Your Account": "", "Your account status is currently pending activation.": "", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index 83431383ef..dced0f6c92 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "", "No results found": "", "No search query generated": "", + "No servers detected": "", "No skills found": "", "No source available": "", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "", "Retrieval": "", @@ -1583,6 +1591,7 @@ "Role": "", "RTL": "", "Run": "", + "Run All": "", "Running": "", "Running...": "", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "", "Your Account": "", "Your account status is currently pending activation.": "", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/es-ES/translation.json b/src/lib/i18n/locales/es-ES/translation.json index 18a9624e6d..d9877b5d3b 100644 --- a/src/lib/i18n/locales/es-ES/translation.json +++ b/src/lib/i18n/locales/es-ES/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Límite de caracteres de entrada de la generación de autocompletado", "Chart new frontiers": "Trazar nuevas fronteras", "Chat": "Chat", + "Chat archived.": "", "Chat Background Image": "Imágen de Fondo del Chat", "Chat Bubble UI": "Interfaz del Chat en Burbuja", "Chat Completions": "Completación del Chat", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Efecto de desvanecimiento para texto transmitido (streaming)", "Failed to add file.": "Fallo al añadir el archivo.", "Failed to add members": "Fallo al añadir miembros", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "Fallo al limpiar el estado", "Failed to connect to {{URL}} OpenAPI tool server": "Fallo al conectar al servidor de herramientas {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "Fallo al generar el título", "Failed to import models": "Fallo al importar modelos", "Failed to load chat preview": "Fallo al cargar la previsualización del chat", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "Fallo al cargar el archivo Excel/CSV. Por favor, en su lugar intente descargarlo.", "Failed to load file content.": "Fallo al cargar el contenido del archivo", "Failed to load Interface settings": "Fallo al cargar la configuración del Interface", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Fallo al mover el chat", "Failed to process URL: {{url}}": "Fallo al procesar la URL", "Failed to read clipboard contents": "Fallo al leer el contenido del portapapeles", @@ -1305,6 +1309,7 @@ "No history available": "No hay historial disponible", "No HTML, CSS, or JavaScript content found.": "No se encontró contenido HTML, CSS, o JavaScript.", "No inference engine with management support found": "No se encontró un motor de inferencia que soporte gestión", + "No kernel": "", "No knowledge bases found.": "No se encontraron bases de conocimiento", "No knowledge found": "No se encontró ningún conocimiento", "No memories to clear": "No hay memorias para borrar", @@ -1320,6 +1325,7 @@ "No results": "No se encontraron resultados", "No results found": "No se encontraron resultados", "No search query generated": "No se generó ninguna consulta de búsqueda", + "No servers detected": "", "No skills found": "No se encontraron habilidades", "No source available": "No hay fuente disponible", "No sources found": "No se han encontrado fuentes", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "Por favor selecciona al menos un usuario para el canal de Mensajes Directos", "Please wait until all files are uploaded.": "Por favor, espera a que todos los archivos se acaben de subir", "Port": "Puerto", + "Ports": "", "Positive attitude": "Actitud Positiva", "Prefer not to say": "Prefiero no decirlo", "Prefix ID": "prefijo ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Particionado de Respuesta", "Response Watermark": "Marca de Agua en Respuesta", "Responses": "Respuestas", + "Restart": "", "Result": "Resultado", "RESULT": "Resultado", "Retrieval": "Recuperación", @@ -1584,6 +1592,7 @@ "Role": "Rol", "RTL": "RTL", "Run": "Ejecutar", + "Run All": "", "Running": "Ejecutando", "Running...": "Ejecutando...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "Ejecuta tareas de incrustración concurrentes para acelerar el procesado. Desactivar si se generan problemas (por limitaciones de los motores de incrustracción en uso)", @@ -1774,6 +1783,7 @@ "Start a new conversation": "Comenzar una conversación nueva", "Start of the channel": "Inicio del canal", "Start Tag": "Etiqueta de Inicio", + "Starting kernel...": "", "Status": "Estado", "Status cleared successfully": "Estado limpiado correctamente", "Status updated successfully": "Estado actualizado correctamente", @@ -2118,6 +2128,8 @@ "You're now logged in.": "Has iniciado sesión.", "Your Account": "Tu Cuenta", "Your account status is currently pending activation.": "Tu cuenta está pendiente de activación.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Tu entera contribución irá directamente al desarrollador del complemento; Open-WebUI no recibe ningún porcentaje. Sin embargo, la plataforma de financiación elegida podría tener sus propias tarifas.", "Your message text or inputs": "Tu mensaje de texto o entrada", "Your usage stats have been successfully synced.": "Tu estadistica de uso ha sido sincronizada", diff --git a/src/lib/i18n/locales/et-EE/translation.json b/src/lib/i18n/locales/et-EE/translation.json index e5611c0be0..b133d638e7 100644 --- a/src/lib/i18n/locales/et-EE/translation.json +++ b/src/lib/i18n/locales/et-EE/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Märkide piirang automaattäitmise genereerimise sisendile", "Chart new frontiers": "Kaardista uusi piire", "Chat": "Vestlus", + "Chat archived.": "", "Chat Background Image": "Vestluse taustapilt", "Chat Bubble UI": "Vestlusmullide kasutajaliides", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Hajuefekt voogteksti jaoks", "Failed to add file.": "Faili lisamine ebaõnnestus.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Ebaõnnestus kuni connect kuni {{URL}} OpenAPI tööriist server", @@ -836,9 +838,11 @@ "Failed to generate title": "Ebaõnnestus kuni generate title", "Failed to import models": "Ebaõnnestus kuni impordi mudelid", "Failed to load chat preview": "Ebaõnnestus kuni load vestlus preview", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "Ebaõnnestus kuni load fail content.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Ebaõnnestus kuni teisalda vestlus", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Lõikelaua sisu lugemine ebaõnnestus", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "HTML, CSS ega JavaScript sisu ei leitud.", "No inference engine with management support found": "Järeldusmootorit haldamise toega ei leitud", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Teadmisi ei leitud", "No memories to clear": "Pole mälestusi, mida kustutada", @@ -1320,6 +1325,7 @@ "No results": "Tulemusi ei leitud", "No results found": "Tulemusi ei leitud", "No search query generated": "Otsingupäringut ei genereeritud", + "No servers detected": "", "No skills found": "", "No source available": "Allikas pole saadaval", "No sources found": "No allikad found", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "Please wait until all failid are uploaded.", "Port": "Port", + "Ports": "", "Positive attitude": "Positiivne suhtumine", "Prefer not to say": "Prefer not kuni say", "Prefix ID": "Prefiksi ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Vastuse tükeldamine", "Response Watermark": "Vastus Watermark", "Responses": "", + "Restart": "", "Result": "Tulemus", "RESULT": "Tulemus", "Retrieval": "Taastamine", @@ -1583,6 +1591,7 @@ "Role": "Roll", "RTL": "RTL", "Run": "Käivita", + "Run All": "", "Running": "Töötab", "Running...": "Töötab...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "Käivita a new conversation", "Start of the channel": "Kanali algus", "Start Tag": "Käivita Silt", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Olete nüüd sisse logitud.", "Your Account": "Your Konto", "Your account status is currently pending activation.": "Teie konto staatus on praegu ootel aktiveerimist.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Kogu teie toetus läheb otse pistikprogrammi arendajale; Open WebUI ei võta mingit protsenti. Kuid valitud rahastamisplatvormil võivad olla oma tasud.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/eu-ES/translation.json b/src/lib/i18n/locales/eu-ES/translation.json index f897c87d83..117a260c60 100644 --- a/src/lib/i18n/locales/eu-ES/translation.json +++ b/src/lib/i18n/locales/eu-ES/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "Esploratu muga berriak", "Chat": "Txata", + "Chat archived.": "", "Chat Background Image": "Txataren Atzeko Irudia", "Chat Bubble UI": "Txat Burbuilen Interfazea", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Huts egin du fitxategia gehitzean.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Huts egin du arbelaren edukia irakurtzean", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Ez da HTML, CSS, edo JavaScript edukirik aurkitu.", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Ez da ezagutzarik aurkitu", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Ez da emaitzarik aurkitu", "No results found": "Ez da emaitzarik aurkitu", "No search query generated": "Ez da bilaketa kontsultarik sortu", + "No servers detected": "", "No skills found": "", "No source available": "Ez dago iturririk eskuragarri", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Ataka", + "Ports": "", "Positive attitude": "Jarrera positiboa", "Prefer not to say": "", "Prefix ID": "Aurrizki ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Erantzun banaketa", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "Emaitza", "RESULT": "Emaitza", "Retrieval": "", @@ -1583,6 +1591,7 @@ "Role": "Rola", "RTL": "RTL", "Run": "Exekutatu", + "Run All": "", "Running": "Exekutatzen", "Running...": "Exekutatzen...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Kanalaren hasiera", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Orain saioa hasita duzu.", "Your Account": "", "Your account status is currently pending activation.": "Zure kontuaren egoera aktibazio zain dago.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Zure ekarpen osoa zuzenean plugin garatzaileari joango zaio; Open WebUI-k ez du ehunekorik hartzen. Hala ere, aukeratutako finantzaketa plataformak bere komisioak izan ditzake.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/fa-IR/translation.json b/src/lib/i18n/locales/fa-IR/translation.json index fe356747aa..1bc4077445 100644 --- a/src/lib/i18n/locales/fa-IR/translation.json +++ b/src/lib/i18n/locales/fa-IR/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "محدودیت کاراکتر برای ورودی تولید تکمیل خودکار", "Chart new frontiers": "ترسیم مرزهای جدید", "Chat": "گفتگو", + "Chat archived.": "", "Chat Background Image": "تصویر پس\u200cزمینهٔ گفتگو", "Chat Bubble UI": "رابط کاربری حبابی گفتگو", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "جلوه محو شدن برای متن جریانی", "Failed to add file.": "خطا در افزودن پرونده", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "خطا در اتصال به سرور ابزار OpenAPI {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "تولید عنوان ناموفق بود", "Failed to import models": "وارد کردن مدل\u200cها ناموفق بود", "Failed to load chat preview": "بارگیری پیش\u200cنمایش چت ناموفق بود", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "بارگیری محتوای فایل ناموفق بود.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "انتقال چت ناموفق بود", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "خواندن محتوای کلیپ بورد ناموفق بود", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "محتوای HTML، CSS یا JavaScript یافت نشد.", "No inference engine with management support found": "موتور استنتاج با پشتیبانی مدیریت یافت نشد", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "دانشی یافت نشد", "No memories to clear": "حافظه\u200cای برای پاک کردن وجود ندارد", @@ -1320,6 +1325,7 @@ "No results": "نتیجه\u200cای یافت نشد", "No results found": "نتیجه\u200cای یافت نشد", "No search query generated": "پرسوجوی جستجویی ایجاد نشده است", + "No servers detected": "", "No skills found": "", "No source available": "منبعی در دسترس نیست", "No sources found": "هیچ منبعی یافت نشد", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "لطفاً منتظر بمانید تا همه فایل\u200cها آپلود شوند.", "Port": "پورت", + "Ports": "", "Positive attitude": "نظرات مثبت", "Prefer not to say": "ترجیح می\u200cدهم نگویم", "Prefix ID": "شناسه پیشوند", @@ -1571,6 +1578,7 @@ "Response splitting": "تقسیم پاسخ", "Response Watermark": "واترمارک پاسخ", "Responses": "", + "Restart": "", "Result": "نتیجه", "RESULT": "نتیجه", "Retrieval": "بازیابی", @@ -1583,6 +1591,7 @@ "Role": "نقش", "RTL": "RTL", "Run": "اجرا", + "Run All": "", "Running": "در حال اجرا", "Running...": "در حال اجرا...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "شروع یک مکالمه جدید", "Start of the channel": "آغاز کانال", "Start Tag": "تگ شروع", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "شما اکنون وارد شده\u200cاید.", "Your Account": "حساب کاربری شما", "Your account status is currently pending activation.": "وضعیت حساب شما در حال حاضر در انتظار فعال\u200cسازی است.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "تمام مشارکت شما مستقیماً به توسعه\u200cدهنده افزونه می\u200cرسد؛ Open WebUI هیچ درصدی دریافت نمی\u200cکند. با این حال، پلتفرم تأمین مالی انتخاب شده ممکن است کارمزد خود را داشته باشد.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/fi-FI/translation.json b/src/lib/i18n/locales/fi-FI/translation.json index 9c88959965..78d02d0aa2 100644 --- a/src/lib/i18n/locales/fi-FI/translation.json +++ b/src/lib/i18n/locales/fi-FI/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Automaattisen täydennyksen syötteen merkkiraja", "Chart new frontiers": "Kartoita uusia rajapintoja", "Chat": "Keskustelu", + "Chat archived.": "", "Chat Background Image": "Keskustelun taustakuva", "Chat Bubble UI": "Keskustelu-pallojen käyttöliittymä", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Häivytystehoste suoratoistetulle tekstille", "Failed to add file.": "Tiedoston lisääminen epäonnistui.", "Failed to add members": "Jäsenten lisääminen epäonnistui", + "Failed to archive chat.": "", "Failed to attach file": "Tiedoston liittäminen epäonnistui", "Failed to clear status": "Tilan tyhjentäminen epäonnistui", "Failed to connect to {{URL}} OpenAPI tool server": "Yhdistäminen {{URL}} OpenAPI työkalu palvelimeen epäonnistui", @@ -836,9 +838,11 @@ "Failed to generate title": "Otsikon luonti epäonnistui", "Failed to import models": "Mallien tuonti epäonnistui", "Failed to load chat preview": "Keskustelun esikatselun lataaminen epäonnistui", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV tiedoston lataaminen epäonnistui. Yritä ladata se sen sijaan.", "Failed to load file content.": "Tiedoston sisällön lataaminen epäonnistui.", "Failed to load Interface settings": "Käyttöliittymän asetusten lataaminen epäonnistui", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Keskustelun siirto epäonnistui", "Failed to process URL: {{url}}": "Verkko-osoitteen käsittely epäonnistui: {{url}}", "Failed to read clipboard contents": "Leikepöydän sisällön lukeminen epäonnistui", @@ -1305,6 +1309,7 @@ "No history available": "Historiaa ei saatavilla", "No HTML, CSS, or JavaScript content found.": "HTML-, CSS- tai JavaScript-sisältöä ei löytynyt.", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "Tietokantoja ei löytynyt.", "No knowledge found": "Tietoa ei löytynyt", "No memories to clear": "Ei muistia tyhjennettäväksi", @@ -1320,6 +1325,7 @@ "No results": "Ei tuloksia", "No results found": "Ei tuloksia", "No search query generated": "Hakukyselyä ei luotu", + "No servers detected": "", "No skills found": "Taitoja ei löytynyt", "No source available": "Lähdettä ei saatavilla", "No sources found": "Lähteitä ei löytynyt", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "Valitse vähintään yksi käyttäjä suoraviestikanavalle.", "Please wait until all files are uploaded.": "Odota kunnes kaikki tiedostot ovat ladattu.", "Port": "Portti", + "Ports": "", "Positive attitude": "Positiivinen asenne", "Prefer not to say": "En halua sanoa", "Prefix ID": "Etuliite-ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Vastauksen jakaminen", "Response Watermark": "Vastauksen vesileima", "Responses": "", + "Restart": "", "Result": "Tulos", "RESULT": "Tulos", "Retrieval": "Haku", @@ -1583,6 +1591,7 @@ "Role": "Rooli", "RTL": "RTL", "Run": "Suorita", + "Run All": "", "Running": "Käynnissä", "Running...": "Käynnissä...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "Suorittaa upotustehtäviä samanaikaisesti käsittelyn nopeuttamiseksi. Poista käytöstä, jos kutsurajoituksesta tulee ongelma.", @@ -1773,6 +1782,7 @@ "Start a new conversation": "Aloita uusi keskustelu", "Start of the channel": "Kanavan alku", "Start Tag": "Aloitus tagi", + "Starting kernel...": "", "Status": "Tila", "Status cleared successfully": "Tila poistettu onnistuneesti", "Status updated successfully": "Tila päivitetty onnistuneesti", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Olet nyt kirjautunut sisään.", "Your Account": "Tilisi", "Your account status is currently pending activation.": "Tilisi tila on tällä hetkellä odottaa aktivointia.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Koko panoksesi menee suoraan lisäosan kehittäjälle; Open WebUI ei pidätä prosenttiosuutta. Valittu rahoitusalusta voi kuitenkin periä omia maksujaan.", "Your message text or inputs": "Viestisi teksti tai syöteet", "Your usage stats have been successfully synced.": "Käyttötilastosi on synkronoitu onnistuneesti.", diff --git a/src/lib/i18n/locales/fr-CA/translation.json b/src/lib/i18n/locales/fr-CA/translation.json index 2aba6bacd3..d7a80ee90b 100644 --- a/src/lib/i18n/locales/fr-CA/translation.json +++ b/src/lib/i18n/locales/fr-CA/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Limite de caractères pour la génération des suggestions", "Chart new frontiers": "Tracer de nouvelles frontières", "Chat": "Conversation", + "Chat archived.": "", "Chat Background Image": "Image d'arrière-plan de la fenêtre de la conversation", "Chat Bubble UI": "Bulles de conversation", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Échec de l'ajout du fichier.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Échec de la connexion au serveur d'outils OpenAPI {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "Échec du chargement du contenu du fichier", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Échec de la lecture du contenu du presse-papiers", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Aucun contenu HTML, CSS ou JavaScript trouvé.", "No inference engine with management support found": "Aucun moteur d'inférence avec support trouvé", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Aucune connaissance trouvée", "No memories to clear": "Aucun souvenir à effacer", @@ -1320,6 +1325,7 @@ "No results": "Aucun résultat trouvé", "No results found": "Aucun résultat trouvé", "No search query generated": "Aucune requête de recherche générée", + "No servers detected": "", "No skills found": "", "No source available": "Aucune source n'est disponible", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Port", + "Ports": "", "Positive attitude": "Attitude positive", "Prefer not to say": "", "Prefix ID": "ID de préfixe", @@ -1571,6 +1578,7 @@ "Response splitting": "Fractionnement de la réponse", "Response Watermark": "Filigramme de la réponse", "Responses": "", + "Restart": "", "Result": "Résultat", "RESULT": "Résultat", "Retrieval": "Récupération", @@ -1584,6 +1592,7 @@ "Role": "Rôle", "RTL": "RTL", "Run": "Exécuter", + "Run All": "", "Running": "Exécution", "Running...": "Exécution...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1774,6 +1783,7 @@ "Start a new conversation": "", "Start of the channel": "Début du canal", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2118,6 +2128,8 @@ "You're now logged in.": "Vous êtes désormais connecté.", "Your Account": "", "Your account status is currently pending activation.": "Votre statut de compte est actuellement en attente d'activation.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "L'intégralité de votre contribution ira directement au développeur du plugin ; Open WebUI ne prend aucun pourcentage. Cependant, la plateforme de financement choisie peut avoir ses propres frais.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/fr-FR/translation.json b/src/lib/i18n/locales/fr-FR/translation.json index 3f24312660..c123b3d967 100644 --- a/src/lib/i18n/locales/fr-FR/translation.json +++ b/src/lib/i18n/locales/fr-FR/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Limite de caractères pour la génération des suggestions", "Chart new frontiers": "Tracer de nouvelles frontières", "Chat": "Conversation", + "Chat archived.": "", "Chat Background Image": "Image d'arrière-plan de la fenêtre de la conversation", "Chat Bubble UI": "Bulles de conversation", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Effet de fondu pour le texte en streaming", "Failed to add file.": "Échec de l'ajout du fichier.", "Failed to add members": "Échec de l'ajout des membres", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Échec de la connexion au serveur d'outils OpenAPI {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "Échec de la génération du titre", "Failed to import models": "Échec de l'importation des modèles", "Failed to load chat preview": "Échec du chargement de l'aperçu du chat", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "Échec du chargement du contenu du fichier", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Échec du déplacement du chat", "Failed to process URL: {{url}}": "Échec du traitement de l'URL : {{url}}", "Failed to read clipboard contents": "Échec de la lecture du contenu du presse-papiers", @@ -1305,6 +1309,7 @@ "No history available": "Aucun historique disponible", "No HTML, CSS, or JavaScript content found.": "Aucun contenu HTML, CSS ou JavaScript trouvé.", "No inference engine with management support found": "Aucun moteur d'inférence avec support trouvé", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Aucune connaissance trouvée", "No memories to clear": "Aucun souvenir à effacer", @@ -1320,6 +1325,7 @@ "No results": "Aucun résultat trouvé", "No results found": "Aucun résultat trouvé", "No search query generated": "Aucune requête de recherche générée", + "No servers detected": "", "No skills found": "Aucun skill trouvé", "No source available": "Aucune source n'est disponible", "No sources found": "Aucune source trouvée", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "Veuillez sélectionner au moins un utilisateur pour un canal de message direct.", "Please wait until all files are uploaded.": "Veuillez patienter jusqu'à ce que tous les fichiers soient téléchargés.", "Port": "Port", + "Ports": "", "Positive attitude": "Attitude positive", "Prefer not to say": "Je préfère ne pas répondre", "Prefix ID": "ID de préfixe", @@ -1571,6 +1578,7 @@ "Response splitting": "Fractionnement de la réponse", "Response Watermark": "Filigramme de la réponse", "Responses": "", + "Restart": "", "Result": "Résultat", "RESULT": "Résultat", "Retrieval": "Récupération", @@ -1584,6 +1592,7 @@ "Role": "Rôle", "RTL": "RTL", "Run": "Exécuter", + "Run All": "", "Running": "Exécution", "Running...": "Exécution...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1774,6 +1783,7 @@ "Start a new conversation": "Démarrer une nouvelle conversation", "Start of the channel": "Début du canal", "Start Tag": "Balise de départ", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "Statut effacé avec succès", "Status updated successfully": "Statut mis à jour avec succès", @@ -1984,7 +1994,7 @@ "Upload Pipeline": "Pipeline de téléchargement", "Upload profile image": "", "Upload Progress": "Progression de l'envoi", - "Upload Progress: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)": "Progression du téléchargement : {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)", + "Upload Progress: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)": "Progression du téléchargement\u00a0: {{uploadedFiles}}/{{totalFiles}} ({{percentage}}%)", "Uploaded files or images": "Les fichiers ou images téléversés", "Uploading file...": "Téléversement du fichier en cours...", "Uploading...": "Téléversement en cours...", @@ -2017,7 +2027,7 @@ "Using Entire Document": "Utilisation du document entier", "Using Focused Retrieval": "Utilisation de la récupération ciblée", "Using the default arena model with all models. Click the plus button to add custom models.": "Utilisation du modèle d'arène par défaut avec tous les modèles. Cliquez sur le bouton plus pour ajouter des modèles personnalisés.", - "Valid time units:": "Unités de temps valides :", + "Valid time units:": "Unités de temps valides\u00a0:", "Validate certificate": "Valider le certificat", "Valves": "Vannes", "Valves updated": "Vannes mises à jour", @@ -2118,6 +2128,8 @@ "You're now logged in.": "Vous êtes désormais connecté.", "Your Account": "Votre compte", "Your account status is currently pending activation.": "Votre statut de compte est actuellement en attente d'activation.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "L'intégralité de votre contribution ira directement au développeur du plugin ; Open WebUI ne prend aucun pourcentage. Cependant, la plateforme de financement choisie peut avoir ses propres frais.", "Your message text or inputs": "Vos messages envoyés", "Your usage stats have been successfully synced.": "Vos statistiques d'utilisation ont été synchronisées avec succès.", diff --git a/src/lib/i18n/locales/gl-ES/translation.json b/src/lib/i18n/locales/gl-ES/translation.json index 28023e96de..27c9b3d58b 100644 --- a/src/lib/i18n/locales/gl-ES/translation.json +++ b/src/lib/i18n/locales/gl-ES/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Limite de caracteres para a entrada de xeneración do autocompletado", "Chart new frontiers": "Dibuxar novas fronteiras", "Chat": "Chat", + "Chat archived.": "", "Chat Background Image": "Imaxe de fondo do Chat", "Chat Bubble UI": "Burbuxa do chat UI", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Non pudo agregarse o Arquivo.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Non pudo Lerse o contido do portapapeles", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "No se encontró contido HTML, CSS, o JavaScript.", "No inference engine with management support found": "No se encontró un motor de inferencia con soporte de gestión", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "No se encontrou ningún coñecemento", "No memories to clear": "Non hay memorias que limpar", @@ -1320,6 +1325,7 @@ "No results": "No se han encontrado resultados", "No results found": "No se han encontrado resultados", "No search query generated": "No se ha generado ninguna consulta de búsqueda", + "No servers detected": "", "No skills found": "", "No source available": "Non ten fuente disponible", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Puerto", + "Ports": "", "Positive attitude": "Actitud positiva", "Prefer not to say": "", "Prefix ID": "ID de prefijo", @@ -1571,6 +1578,7 @@ "Response splitting": "División de respostas", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "Resultado", "RESULT": "Resultado", "Retrieval": "recuperación", @@ -1583,6 +1591,7 @@ "Role": "Rol", "RTL": "RTL", "Run": "Executar", + "Run All": "", "Running": "Executando", "Running...": "Executando...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Inicio da canle", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Vostede ahora está conectado.", "Your Account": "", "Your account status is currently pending activation.": "O estado da sua conta actualmente encontrase pendente de activación.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "A sua contribución completa irá directamente o desarrollador do plugin; Open WebUI non toma ningun porcentaxe. Sin embargo, a plataforma de financiación elegida podría ter as suas propias tarifas.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/he-IL/translation.json b/src/lib/i18n/locales/he-IL/translation.json index 5cf3acab1e..a6b061d054 100644 --- a/src/lib/i18n/locales/he-IL/translation.json +++ b/src/lib/i18n/locales/he-IL/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "צ'אט", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "UI של תיבת הדיבור", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "קריאת תוכן הלוח נכשלה", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "לא נמצאו תוצאות", "No results found": "לא נמצאו תוצאות", "No search query generated": "לא נוצרה שאילתת חיפוש", + "No servers detected": "", "No skills found": "", "No source available": "אין מקור זמין", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "גישה חיובית", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "תוצאה", "Retrieval": "", @@ -1584,6 +1592,7 @@ "Role": "תפקיד", "RTL": "RTL", "Run": "", + "Run All": "", "Running": "", "Running...": "פועל...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1774,6 +1783,7 @@ "Start a new conversation": "", "Start of the channel": "תחילת הערוץ", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2118,6 +2128,8 @@ "You're now logged in.": "כעת אתה מחובר.", "Your Account": "", "Your account status is currently pending activation.": "", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/hi-IN/translation.json b/src/lib/i18n/locales/hi-IN/translation.json index d8395b259d..d1576fca2d 100644 --- a/src/lib/i18n/locales/hi-IN/translation.json +++ b/src/lib/i18n/locales/hi-IN/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "चैट करें", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "चैट बॉली", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "क्लिपबोर्ड सामग्री पढ़ने में विफल", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "कोई परिणाम नहीं मिला", "No results found": "कोई परिणाम नहीं मिला", "No search query generated": "कोई खोज क्वेरी जनरेट नहीं हुई", + "No servers detected": "", "No skills found": "", "No source available": "कोई स्रोत उपलब्ध नहीं है", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "सकारात्मक रवैया", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "परिणाम", "Retrieval": "", @@ -1583,6 +1591,7 @@ "Role": "भूमिका", "RTL": "RTL", "Run": "", + "Run All": "", "Running": "", "Running...": "चल रहा है...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "चैनल की शुरुआत", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "अब आप लॉग इन हो गए हैं", "Your Account": "", "Your account status is currently pending activation.": "", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/hr-HR/translation.json b/src/lib/i18n/locales/hr-HR/translation.json index 476c684122..e6dadaba52 100644 --- a/src/lib/i18n/locales/hr-HR/translation.json +++ b/src/lib/i18n/locales/hr-HR/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "Razgovor", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "Razgovor - Bubble UI", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Neuspješno čitanje sadržaja međuspremnika", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Nema rezultata", "No results found": "Nema rezultata", "No search query generated": "Nije generiran upit za pretraživanje", + "No servers detected": "", "No skills found": "", "No source available": "Nema dostupnog izvora", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "Pozitivan stav", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "REZULTAT", "Retrieval": "", @@ -1584,6 +1592,7 @@ "Role": "Uloga", "RTL": "RTL", "Run": "", + "Run All": "", "Running": "Pokrenuto", "Running...": "Pokrenuto...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1774,6 +1783,7 @@ "Start a new conversation": "", "Start of the channel": "Početak kanala", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2118,6 +2128,8 @@ "You're now logged in.": "Sada ste prijavljeni.", "Your Account": "", "Your account status is currently pending activation.": "Status vašeg računa trenutno čeka aktivaciju.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/hu-HU/translation.json b/src/lib/i18n/locales/hu-HU/translation.json index 74a5b75d55..0a210ed323 100644 --- a/src/lib/i18n/locales/hu-HU/translation.json +++ b/src/lib/i18n/locales/hu-HU/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Karakterlimit az automatikus kiegészítés bemenetéhez", "Chart new frontiers": "Új határok feltérképezése", "Chat": "Beszélgetés", + "Chat archived.": "", "Chat Background Image": "Beszélgetés háttérkép", "Chat Bubble UI": "Beszélgetés buborék felület", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Nem sikerült hozzáadni a fájlt.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Nem sikerült csatlakozni a {{URL}} OpenAPI eszköszerverhez", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Nem sikerült olvasni a vágólap tartalmát", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Nem található HTML, CSS vagy JavaScript tartalom.", "No inference engine with management support found": "Nem található kezelést támogató következtetési motor", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Nem található tudásbázis", "No memories to clear": "Nincs törlendő memória", @@ -1320,6 +1325,7 @@ "No results": "Nincs találat", "No results found": "Nincs találat", "No search query generated": "Nem generálódott keresési lekérdezés", + "No servers detected": "", "No skills found": "", "No source available": "Nincs elérhető forrás", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Port", + "Ports": "", "Positive attitude": "Pozitív hozzáállás", "Prefer not to say": "", "Prefix ID": "Előtag azonosító", @@ -1571,6 +1578,7 @@ "Response splitting": "Válasz felosztás", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "Eredmény", "RESULT": "Eredmény", "Retrieval": "Visszakeresés", @@ -1583,6 +1591,7 @@ "Role": "Szerep", "RTL": "RTL", "Run": "Futtatás", + "Run All": "", "Running": "Fut", "Running...": "Fut...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "A csatorna eleje", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Sikeresen bejelentkezett.", "Your Account": "", "Your account status is currently pending activation.": "Fiókja jelenleg aktiválásra vár.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "A teljes hozzájárulása közvetlenül a bővítmény fejlesztőjéhez kerül; az Open WebUI nem vesz le százalékot. Azonban a választott támogatási platformnak lehetnek saját díjai.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/id-ID/translation.json b/src/lib/i18n/locales/id-ID/translation.json index 7dde9a33ad..6e78717c3f 100644 --- a/src/lib/i18n/locales/id-ID/translation.json +++ b/src/lib/i18n/locales/id-ID/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "Obrolan", + "Chat archived.": "", "Chat Background Image": "Gambar Latar Belakang Obrolan", "Chat Bubble UI": "UI Gelembung Obrolan", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Gagal membaca konten papan klip", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Tidak ada hasil yang ditemukan", "No results found": "Tidak ada hasil yang ditemukan", "No search query generated": "Tidak ada permintaan pencarian yang dibuat", + "No servers detected": "", "No skills found": "", "No source available": "Tidak ada sumber yang tersedia", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "Sikap positif", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "HASIL", "Retrieval": "", @@ -1582,6 +1590,7 @@ "Role": "Peran", "RTL": "RTL", "Run": "", + "Run All": "", "Running": "Berjalan", "Running...": "Berjalan...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1772,6 +1781,7 @@ "Start a new conversation": "", "Start of the channel": "Awal saluran", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2116,6 +2126,8 @@ "You're now logged in.": "Anda sekarang sudah masuk.", "Your Account": "", "Your account status is currently pending activation.": "Status akun Anda saat ini sedang menunggu aktivasi.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/ie-GA/translation.json b/src/lib/i18n/locales/ie-GA/translation.json index f03feb1c42..d711c5fbe1 100644 --- a/src/lib/i18n/locales/ie-GA/translation.json +++ b/src/lib/i18n/locales/ie-GA/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Teorainn charachtair le haghaidh ionchur giniúna uathchríochnaithe", "Chart new frontiers": "Cairt teorainneacha nua", "Chat": "Comhrá", + "Chat archived.": "", "Chat Background Image": "Íomhá Cúlra Comhrá", "Chat Bubble UI": "Comhrá Bubble UI", "Chat Completions": "Críochnuithe Comhrá", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Éifeacht Céimnithe le haghaidh Sruthú Téacs", "Failed to add file.": "Theip ar an gcomhad a chur leis.", "Failed to add members": "Theip ar bhaill a chur leis", + "Failed to archive chat.": "", "Failed to attach file": "Theip ar an gcomhad a cheangal", "Failed to clear status": "Theip ar an stádas a ghlanadh", "Failed to connect to {{URL}} OpenAPI tool server": "Theip ar nascadh le {{URL}} freastalaí uirlisí OpenAPI", @@ -836,9 +838,11 @@ "Failed to generate title": "Theip ar an teideal a ghiniúint", "Failed to import models": "Theip ar samhail a iompórtáil", "Failed to load chat preview": "Theip ar réamhamharc comhrá a lódáil", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "Theip ar an gcomhad Excel/CSV a lódáil. Déan iarracht é a íoslódáil ina ionad.", "Failed to load file content.": "Theip ar lódáil ábhar an chomhaid.", "Failed to load Interface settings": "Theip ar shocruithe an Chomhéadain a lódáil", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Theip ar an gcomhrá a bhogadh", "Failed to process URL: {{url}}": "Theip ar phróiseáil an URL: {{url}}", "Failed to read clipboard contents": "Theip ar ábhar gearrthaisce a lé", @@ -1305,6 +1309,7 @@ "No history available": "Níl aon stair ar fáil", "No HTML, CSS, or JavaScript content found.": "Níor aimsíodh aon ábhar HTML, CSS nó JavaScript.", "No inference engine with management support found": "Níor aimsíodh aon inneall tátail le tacaíocht bhainistíochta", + "No kernel": "", "No knowledge bases found.": "Níor aimsíodh aon bhunachair eolais.", "No knowledge found": "Níor aimsíodh aon eolas", "No memories to clear": "Gan cuimhní cinn a ghlanadh", @@ -1320,6 +1325,7 @@ "No results": "Níl aon torthaí le fáil", "No results found": "Níl aon torthaí le fáil", "No search query generated": "Ní ghintear aon cheist cuardaigh", + "No servers detected": "", "No skills found": "Níor aimsíodh aon scileanna", "No source available": "Níl aon fhoinse ar fáil", "No sources found": "Níor aimsíodh aon fhoinsí", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "Roghnaigh úsáideoir amháin ar a laghad don chainéal Teachtaireachtaí Díreacha.", "Please wait until all files are uploaded.": "Fan go dtí go mbeidh na comhaid go léir uaslódáilte.", "Port": "Port", + "Ports": "", "Positive attitude": "Dearcadh dearfach", "Prefer not to say": "Is fearr liom gan a rá", "Prefix ID": "Aitheantas Réimír", @@ -1571,6 +1578,7 @@ "Response splitting": "Scoilt freagartha", "Response Watermark": "Comhartha Uisce Freagartha", "Responses": "Freagraí", + "Restart": "", "Result": "Toradh", "RESULT": "Toradh", "Retrieval": "Aisghabháil", @@ -1583,6 +1591,7 @@ "Role": "Ról", "RTL": "RTL", "Run": "Rith", + "Run All": "", "Running": "Ag rith", "Running...": "Ag rith...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "Ritheann sé tascanna leabaithe ag an am céanna chun luas a chur leis an bpróiseáil. Múch é má bhíonn teorainneacha ráta ina bhfadhb.", @@ -1773,6 +1782,7 @@ "Start a new conversation": "Tosaigh comhrá nua", "Start of the channel": "Tús an chainéil", "Start Tag": "Clib Tosaigh", + "Starting kernel...": "", "Status": "Stádas", "Status cleared successfully": "Glanadh an stádais go rathúil", "Status updated successfully": "Nuashonraíodh an stádas go rathúil", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Tá tú logáilte isteach anois.", "Your Account": "Do Chuntas", "Your account status is currently pending activation.": "Tá stádas do chuntais ar feitheamh faoi ghníomhachtú.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Rachaidh do ranníocaíocht iomlán go díreach chuig an bhforbróir breiseán; Ní ghlacann Open WebUI aon chéatadán. Mar sin féin, d'fhéadfadh a tháillí féin a bheith ag an ardán maoinithe roghnaithe.", "Your message text or inputs": "Téacs nó ionchur do theachtaireachta", "Your usage stats have been successfully synced.": "Tá do staitisticí úsáide sioncronaithe go rathúil.", diff --git a/src/lib/i18n/locales/it-IT/translation.json b/src/lib/i18n/locales/it-IT/translation.json index 5c262434af..56cd7836b3 100644 --- a/src/lib/i18n/locales/it-IT/translation.json +++ b/src/lib/i18n/locales/it-IT/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Limite di caratteri per l'input di generazione dell'autocompletamento", "Chart new frontiers": "Traccia nuove frontiere", "Chat": "Chat", + "Chat archived.": "", "Chat Background Image": "Immagine di sfondo chat", "Chat Bubble UI": "UI bubble chat", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Impossibile aggiungere il file.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Impossibile connettersi al server dello strumento OpenAPI {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "Impossibile caricare il contenuto del file.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Impossibile leggere il contenuto degli appunti", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Nessun contenuto HTML, CSS o JavaScript trovato.", "No inference engine with management support found": "Nessun motore di inferenza con supporto per la gestione trovato", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Nessuna conoscenza trovata", "No memories to clear": "Nessun ricordo da cancellare", @@ -1320,6 +1325,7 @@ "No results": "Nessun risultato trovato", "No results found": "Nessun risultato trovato", "No search query generated": "Nessuna query di ricerca generata", + "No servers detected": "", "No skills found": "", "No source available": "Nessuna fonte disponibile", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Porta", + "Ports": "", "Positive attitude": "Attitudine positiva", "Prefer not to say": "", "Prefix ID": "ID prefisso", @@ -1571,6 +1578,7 @@ "Response splitting": "Divisione della risposta", "Response Watermark": "Watermark della richiesta", "Responses": "", + "Restart": "", "Result": "Risultato", "RESULT": "Risultato", "Retrieval": "Recupero ricordo", @@ -1584,6 +1592,7 @@ "Role": "Ruolo", "RTL": "RTL", "Run": "Esegui", + "Run All": "", "Running": "In esecuzione", "Running...": "In esecuzione...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1774,6 +1783,7 @@ "Start a new conversation": "", "Start of the channel": "Inizio del canale", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2118,6 +2128,8 @@ "You're now logged in.": "Ora hai effettuato l'accesso.", "Your Account": "", "Your account status is currently pending activation.": "Lo stato del tuo account è attualmente in attesa di attivazione.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Il tuo intero contributo andrà direttamente allo sviluppatore del plugin; Open WebUI non prende alcuna percentuale. Tuttavia, la piattaforma di finanziamento scelta potrebbe avere le proprie commissioni.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/ja-JP/translation.json b/src/lib/i18n/locales/ja-JP/translation.json index 062f6c7b00..0532d958b8 100644 --- a/src/lib/i18n/locales/ja-JP/translation.json +++ b/src/lib/i18n/locales/ja-JP/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "オートコンプリート生成入力の文字数の制限", "Chart new frontiers": "新しいフロンティアを切り開く", "Chat": "チャット", + "Chat archived.": "", "Chat Background Image": "チャットの背景画像", "Chat Bubble UI": "チャットバブルUI", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "ストリームテキストのフェーディング効果", "Failed to add file.": "ファイルの追加に失敗しました。", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "{{URL}} OpenAPIツールサーバーへの接続に失敗しました。", @@ -836,9 +838,11 @@ "Failed to generate title": "タイトルの生成に失敗しました。", "Failed to import models": "", "Failed to load chat preview": "チャットプレビューを読み込めませんでした。", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "ファイルの内容を読み込めませんでした。", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "チャットの移動に失敗しました。", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "クリップボードの内容を読み取れませんでした。", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "HTML、CSS、またはJavaScriptの内容が見つかりません。", "No inference engine with management support found": "管理サポートのある推論エンジンが見つかりません。", + "No kernel": "", "No knowledge bases found.": "ナレッジベースが見つかりません", "No knowledge found": "ナレッジベースが見つかりません", "No memories to clear": "クリアするメモリがありません", @@ -1320,6 +1325,7 @@ "No results": "結果が見つかりません", "No results found": "結果が見つかりません", "No search query generated": "検索クエリは生成されません", + "No servers detected": "", "No skills found": "", "No source available": "使用可能なソースがありません", "No sources found": "ソースが見つかりません", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "ファイルがすべてアップロードされるまでお待ちください。", "Port": "ポート", + "Ports": "", "Positive attitude": "ポジティブな態度", "Prefer not to say": "回答しない", "Prefix ID": "Prefix ID", @@ -1571,6 +1578,7 @@ "Response splitting": "応答の分割", "Response Watermark": "応答のウォーターマーク", "Responses": "", + "Restart": "", "Result": "結果", "RESULT": "結果", "Retrieval": "検索", @@ -1582,6 +1590,7 @@ "Role": "ロール", "RTL": "RTL", "Run": "実行", + "Run All": "", "Running": "実行中", "Running...": "実行中...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1772,6 +1781,7 @@ "Start a new conversation": "新しい会話を開始", "Start of the channel": "チャンネルの開始", "Start Tag": "", + "Starting kernel...": "", "Status": "ステータス", "Status cleared successfully": "正常にステータスをクリアしました", "Status updated successfully": "正常にステータスを更新しました", @@ -2116,6 +2126,8 @@ "You're now logged in.": "ログインしました。", "Your Account": "あなたのアカウント", "Your account status is currently pending activation.": "あなたのアカウント状態は現在登録認証待ちです。", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "あなたの全ての寄付はプラグイン開発者へ直接送られます。Open WebUI は手数料を一切取りません。ただし、選択した資金提供プラットフォーム側に手数料が発生する場合があります。", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/ka-GE/translation.json b/src/lib/i18n/locales/ka-GE/translation.json index ce7cdb61f1..78cf199339 100644 --- a/src/lib/i18n/locales/ka-GE/translation.json +++ b/src/lib/i18n/locales/ka-GE/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "ახალი საზღვრების დახაზვა", "Chat": "ჩატი", + "Chat archived.": "", "Chat Background Image": "ჩატის ფონის გამოსახულება", "Chat Bubble UI": "ჩატის ბუშტის ინტერფეისი", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "ფაილის დამატების შეცდომა.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "სათაურის გენერაცია ჩავარდა", "Failed to import models": "მოდელების შემოტანა ჩავარდა", "Failed to load chat preview": "ვიდეოს მინიატურის ჩატვირთვა ჩავარდა", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "ფაილის შემცველობის ჩატვირთვა ჩავარდა.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "ჩატის გადატანა ჩავარდა", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "ბუფერის შემცველობის წაკითხვა ჩავარდა", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "ცოდნა აღმოჩენილი არაა", "No memories to clear": "გასასუფთავებელი მოგონებების გარეშე", @@ -1320,6 +1325,7 @@ "No results": "შედეგების გარეშე", "No results found": "შედეგების გარეშე", "No search query generated": "ძებნის მოთხოვნა არ შექმნილა", + "No servers detected": "", "No skills found": "", "No source available": "წყარო ხელმისაწვდომი არაა", "No sources found": "წყაროები აღმოჩენილი არაა", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "პორტი", + "Ports": "", "Positive attitude": "პოზიტიური დამოკიდებულება", "Prefer not to say": "მირჩევნია, არ ვთქვა", "Prefix ID": "პრეფიქსის ID", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "შედეგი", "RESULT": "შედეგი", "Retrieval": "მიღება", @@ -1583,6 +1591,7 @@ "Role": "როლი", "RTL": "RTL", "Run": "გაშვება", + "Run All": "", "Running": "გაშვებულია", "Running...": "გაშვებულია...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "არხის დასაწყისი", "Start Tag": "დაწყების ჭდე", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "ახლა შესული ბრძანდებით.", "Your Account": "თქვენი ანგარიში", "Your account status is currently pending activation.": "თქვენი ანგარიშის სტატუსი ამჟამად ელოდება აქტივაციას.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/kab-DZ/translation.json b/src/lib/i18n/locales/kab-DZ/translation.json index 887101bedb..ee36320599 100644 --- a/src/lib/i18n/locales/kab-DZ/translation.json +++ b/src/lib/i18n/locales/kab-DZ/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "Asqerdec", + "Chat archived.": "", "Chat Background Image": "Tugna n ugilal n udiwenni", "Chat Bubble UI": "Agrudem n tembulin n udiwenni", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Tecceḍ tmerna n ufaylu.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Ur yessaweḍ ara ad yeqqen ɣer {{URL}} n uqeddac n yifecka OpenAPI", @@ -836,9 +838,11 @@ "Failed to generate title": "Ur yessaweḍ ara ad d-yawi azwel", "Failed to import models": "", "Failed to load chat preview": "Yecceḍ usali n teskant n udiwenni", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "Ur yessaweḍ ara ad d-yessali agbur n yifuyla.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Tuccḍa deg unkaz n udiwenni", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Ur yessaweḍ ara ad iɣer agbur n tfelwit", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Ulac agbur HTML, CSS neɣ JavaScript i d-yufraren.", "No inference engine with management support found": "Ulac amsedday n unalkam s tallelt n usefrek i yettwafen", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Ulac tamussni i yettwafen", "No memories to clear": "Ulac aktayen ibanen", @@ -1320,6 +1325,7 @@ "No results": "Ulac igmaḍ yettwafen", "No results found": "Ulac igmaḍ yettwafen", "No search query generated": "Ulac tuttra n unadi yettusirwen", + "No servers detected": "", "No skills found": "", "No source available": "Ulac aɣbalu yettwafen", "No sources found": "Ulac iɣbula yettwafen", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "Ttxil-k·m, ṛǧu alamma ulin-d akk ifuyla.", "Port": "Tawwurt", + "Ports": "", "Positive attitude": "", "Prefer not to say": "Smenyafeɣ ur d-qqareɣ ara", "Prefix ID": "Asulay ID n uzwir", @@ -1571,6 +1578,7 @@ "Response splitting": "Beṭṭu n tririt", "Response Watermark": "Ticreḍt tafrawant n tririt", "Responses": "", + "Restart": "", "Result": "Agmuḍ", "RESULT": "Agmuḍ", "Retrieval": "Anadi", @@ -1583,6 +1591,7 @@ "Role": "Tamlilt", "RTL": "RTL", "Run": "Selkem", + "Run All": "", "Running": "Aselkem", "Running...": "Aselkem...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Tazwara n ubadu", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Aql-ik teqqned imir-a.", "Your Account": "Amiḍan-ik·im", "Your account status is currently pending activation.": "Addad-nnem n umiḍan atan yettṛaju armad.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/ko-KR/translation.json b/src/lib/i18n/locales/ko-KR/translation.json index d15647355c..234638867c 100644 --- a/src/lib/i18n/locales/ko-KR/translation.json +++ b/src/lib/i18n/locales/ko-KR/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "자동 완성 생성 입력 문자 제한", "Chart new frontiers": "새로운 영역 개척", "Chat": "채팅", + "Chat archived.": "", "Chat Background Image": "채팅 배경 이미지", "Chat Bubble UI": "버블형 채팅 UI", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "스트리밍 텍스트에 대한 페이드 효과", "Failed to add file.": "파일추가에 실패했습니다", "Failed to add members": "멤버 추가에 실패했습니다", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "상태 초기화에 실패했습니다", "Failed to connect to {{URL}} OpenAPI tool server": "{{URL}} OpenAPI 도구 서버 연결 실패", @@ -836,9 +838,11 @@ "Failed to generate title": "제목 생성 실패", "Failed to import models": "모델 가져오기 실패", "Failed to load chat preview": "채팅 미리보기 로드 실패", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "파일 내용 로드 실패.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "채팅 이동 실패", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "클립보드 내용 가져오기를 실패하였습니다", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "HTML, CSS, JavaScript이 발견되지 않았습니다", "No inference engine with management support found": "관리 지원이 포함된 추론 엔진을 찾을 수 없습니다", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "지식 기반을 찾을 수 없습니다", "No memories to clear": "메모리를 정리할 수 없습니다", @@ -1320,6 +1325,7 @@ "No results": "결과가 없습니다", "No results found": "결과를 찾을 수 없습니다", "No search query generated": "검색어가 생성되지 않았습니다", + "No servers detected": "", "No skills found": "", "No source available": "사용 가능한 소스가 없습니다.", "No sources found": "소스를 찾을 수 없습니다", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "1:1 메시지 채널에 참여할 사용자를 최소 한 명 선택해주세요.", "Please wait until all files are uploaded.": "모든 파일이 업로드될 때까지 기다려 주세요.", "Port": "포트", + "Ports": "", "Positive attitude": "긍정적인 자세", "Prefer not to say": "언급하고 싶지 않습니다.", "Prefix ID": "Prefix ID", @@ -1571,6 +1578,7 @@ "Response splitting": "응답 나누기", "Response Watermark": "응답 워터마크", "Responses": "", + "Restart": "", "Result": "결과", "RESULT": "결과", "Retrieval": "검색", @@ -1582,6 +1590,7 @@ "Role": "역할", "RTL": "RTL", "Run": "실행", + "Run All": "", "Running": "실행 중", "Running...": "실행 중...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1772,6 +1781,7 @@ "Start a new conversation": "새 대화 시작", "Start of the channel": "채널 시작", "Start Tag": "시작 태그", + "Starting kernel...": "", "Status": "상태", "Status cleared successfully": "상태 초기화에 성공했습니다", "Status updated successfully": "상태 업데이트에 성공했습니다", @@ -2116,6 +2126,8 @@ "You're now logged in.": "로그인되었습니다.", "Your Account": "계정", "Your account status is currently pending activation.": "현재 계정은 아직 활성화되지 않았습니다.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "당신의 모든 기여는 곧바로 플러그인 개발자에게 갑니다; Open WebUI는 수수료를 받지 않습니다. 다만, 선택한 후원 플랫폼은 수수료를 가져갈 수 있습니다.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/lt-LT/translation.json b/src/lib/i18n/locales/lt-LT/translation.json index e6354753bb..b6195ff803 100644 --- a/src/lib/i18n/locales/lt-LT/translation.json +++ b/src/lib/i18n/locales/lt-LT/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "Pokalbis", + "Chat archived.": "", "Chat Background Image": "Pokalbio galinė užsklanda", "Chat Bubble UI": "Pokalbio burbulo sąsaja", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Nepavyko perskaityti kopijuoklės", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Rezultatų nerasta", "No results found": "Rezultatų nerasta", "No search query generated": "Paieškos užklausa nesugeneruota", + "No servers detected": "", "No skills found": "", "No source available": "Šaltinių nerasta", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "Pozityvus elgesys", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "REZULTATAS", "Retrieval": "", @@ -1585,6 +1593,7 @@ "Role": "Rolė", "RTL": "RTL", "Run": "", + "Run All": "", "Running": "Veikia", "Running...": "Veikia...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1775,6 +1784,7 @@ "Start a new conversation": "", "Start of the channel": "Kanalo pradžia", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2119,6 +2129,8 @@ "You're now logged in.": "Esate prisijungę.", "Your Account": "", "Your account status is currently pending activation.": "Jūsų paskyra laukia administratoriaus patvirtinimo.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Jūsų finansinis prisidėjimas tiesiogiai keliaus modulio kūrėjui.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/lv-LV/translation.json b/src/lib/i18n/locales/lv-LV/translation.json index 5b2210c835..1d1f4724ae 100644 --- a/src/lib/i18n/locales/lv-LV/translation.json +++ b/src/lib/i18n/locales/lv-LV/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Rakstzīmju ierobežojums automātiskās pabeigšanas ievadei", "Chart new frontiers": "Atklāj jaunas robežas", "Chat": "Tērzēšana", + "Chat archived.": "", "Chat Background Image": "Tērzēšanas fona attēls", "Chat Bubble UI": "Tērzēšanas burbuļa saskarne", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Izbalēšanas efekts straumēšanas tekstam", "Failed to add file.": "Neizdevās pievienot failu.", "Failed to add members": "Neizdevās pievienot dalībniekus", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "Neizdevās notīrīt statusu", "Failed to connect to {{URL}} OpenAPI tool server": "Neizdevās savienoties ar {{URL}} OpenAPI rīku serveri", @@ -836,9 +838,11 @@ "Failed to generate title": "Neizdevās ģenerēt virsrakstu", "Failed to import models": "Neizdevās importēt modeļus", "Failed to load chat preview": "Neizdevās ielādēt tērzēšanas priekšskatījumu", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "Neizdevās ielādēt Excel/CSV failu. Lūdzu, mēģiniet to lejupielādēt.", "Failed to load file content.": "Neizdevās ielādēt faila saturu.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Neizdevās pārvietot tērzēšanu", "Failed to process URL: {{url}}": "Neizdevās apstrādāt URL: {{url}}", "Failed to read clipboard contents": "Neizdevās nolasīt starpliktuves saturu", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "HTML, CSS vai JavaScript saturs nav atrasts.", "No inference engine with management support found": "Nav atrasts secinājumu dzinējs ar pārvaldības atbalstu", + "No kernel": "", "No knowledge bases found.": "Zināšanu bāzes nav atrastas.", "No knowledge found": "Zināšanau bāze nav atrasta", "No memories to clear": "Nav atmiņu, ko notīrīt", @@ -1320,6 +1325,7 @@ "No results": "Nav rezultātu", "No results found": "Rezultāti nav atrasti", "No search query generated": "Meklēšanas vaicājums nav ģenerēts", + "No servers detected": "", "No skills found": "", "No source available": "Avots nav pieejams", "No sources found": "Avoti nav atrasti", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "Lūdzu, izvēlieties vismaz vienu lietotāju tiešo ziņojumu kanālam.", "Please wait until all files are uploaded.": "Lūdzu, pagaidiet, līdz visi faili ir augšupielādēti.", "Port": "Ports", + "Ports": "", "Positive attitude": "Pozitīva attieksme", "Prefer not to say": "Nevēlos atklāt", "Prefix ID": "Prefiksa ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Atbilžu sadalīšana", "Response Watermark": "Atbildes ūdenszīme", "Responses": "", + "Restart": "", "Result": "Rezultāts", "RESULT": "REZULTĀTS", "Retrieval": "Izgūšana", @@ -1584,6 +1592,7 @@ "Role": "Loma", "RTL": "RTL", "Run": "Palaist", + "Run All": "", "Running": "Darbojas", "Running...": "Darbojas...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "Palaiž iegulšanas uzdevumus vienlaicīgi, lai paātrinātu apstrādi. Izslēdziet, ja rodas ātruma ierobežojumu problēmas.", @@ -1774,6 +1783,7 @@ "Start a new conversation": "Sākt jaunu sarunu", "Start of the channel": "Kanāla sākums", "Start Tag": "Sākuma tags", + "Starting kernel...": "", "Status": "Statuss", "Status cleared successfully": "Statuss veiksmīgi notīrīts", "Status updated successfully": "Statuss veiksmīgi atjaunināts", @@ -2118,6 +2128,8 @@ "You're now logged in.": "Jūs tagad esat pieteicies.", "Your Account": "Jūsu konts", "Your account status is currently pending activation.": "Jūsu konta statuss pašlaik gaida aktivizēšanu.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Visa jūsu iemaksa nonāks tieši pie spraudņa izstrādātāja; Open WebUI neņem nekādu procentu. Tomēr izvēlētajai finansējuma platformai var būt savas maksas.", "Your message text or inputs": "Jūsu ziņojuma teksts vai ievades", "Your usage stats have been successfully synced.": "Jūsu lietošanas statistika ir veiksmīgi sinhronizēta.", diff --git a/src/lib/i18n/locales/ms-MY/translation.json b/src/lib/i18n/locales/ms-MY/translation.json index 476fa44174..b6459c4817 100644 --- a/src/lib/i18n/locales/ms-MY/translation.json +++ b/src/lib/i18n/locales/ms-MY/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "Perbualan", + "Chat archived.": "", "Chat Background Image": "Imej Latar Belakang Perbualan", "Chat Bubble UI": "Antaramuka Buih Perbualan", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Gagal membaca konten papan klip", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Tiada keputusan dijumpai", "No results found": "Tiada keputusan dijumpai", "No search query generated": "Tiada pertanyaan carian dijana", + "No servers detected": "", "No skills found": "", "No source available": "Tiada sumber tersedia", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "Sikap positif", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "KEPUTUSAN", "Retrieval": "", @@ -1582,6 +1590,7 @@ "Role": "Peranan", "RTL": "RTL", "Run": "Jalankan", + "Run All": "", "Running": "Sedang dijalankan", "Running...": "Sedang dijalankan...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1772,6 +1781,7 @@ "Start a new conversation": "", "Start of the channel": "Permulaan saluran", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2116,6 +2126,8 @@ "You're now logged in.": "Anda kini telah log masuk.", "Your Account": "", "Your account status is currently pending activation.": "Status akaun anda ialah sedang menunggu pengaktifan.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Seluruh sumbangan anda akan dihantar terus kepada pembangun 'plugin'; Open WebUI tidak mengambil sebarang peratusan keuntungan daripadanya. Walau bagaimanapun, platform pembiayaan yang dipilih mungkin mempunyai caj tersendiri.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/nb-NO/translation.json b/src/lib/i18n/locales/nb-NO/translation.json index 4516858509..d4ced2a235 100644 --- a/src/lib/i18n/locales/nb-NO/translation.json +++ b/src/lib/i18n/locales/nb-NO/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Begrensning av tegn for generering av autofullføring", "Chart new frontiers": "Kartlegg ny områder", "Chat": "Chat", + "Chat archived.": "", "Chat Background Image": "Bakgrunnsbilde for chat", "Chat Bubble UI": "Grensesnitt for chat-boble", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Kan ikke legge til filen.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Kan ikke lese utklippstavlens innhold", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Finner ikke noe HTML, CSS- eller JavaScript-innhold.", "No inference engine with management support found": "Fant ingen konklusjonsmotor med støtte for administrasjon", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Finner ingen kunnskaper", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Finner ingen resultater", "No results found": "Finner ingen resultater", "No search query generated": "Ingen søkespørringer er generert", + "No servers detected": "", "No skills found": "", "No source available": "Ingen kilde tilgjengelig", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Port", + "Ports": "", "Positive attitude": "Positiv holdning", "Prefer not to say": "", "Prefix ID": "Prefiks-ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Oppdeling av svar", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "Resultat", "RESULT": "Resultat", "Retrieval": "", @@ -1583,6 +1591,7 @@ "Role": "Rolle", "RTL": "RTL", "Run": "Kjør", + "Run All": "", "Running": "Kjører", "Running...": "Kjører...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Starten av kanalen", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Du er nå logget inn.", "Your Account": "", "Your account status is currently pending activation.": "Status på kontoen din er for øyeblikket ventende på aktivering.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Hele beløpet går uavkortet til utvikleren av tillegget. Open WebUI mottar ikke deler av beløpet. Den valgte betalingsplattformen kan ha gebyrer.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/nl-NL/translation.json b/src/lib/i18n/locales/nl-NL/translation.json index 1475aa0ff9..886395fea4 100644 --- a/src/lib/i18n/locales/nl-NL/translation.json +++ b/src/lib/i18n/locales/nl-NL/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Karakterlimiet voor automatische generatieinvoer", "Chart new frontiers": "Verken nieuwe grenzen", "Chat": "Chat", + "Chat archived.": "", "Chat Background Image": "Chatachtergrond", "Chat Bubble UI": "Chatbubble-UI", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Het is niet gelukt om het bestand toe te voegen.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Kan geen verbinding maken met {{URL}} OpenAPI gereedschapserver", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Kan klembord inhoud niet lezen", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Geen HTML, CSS, of JavaScript inhoud gevonden", "No inference engine with management support found": "Geen inferentie-engine met beheerondersteuning gevonden", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Geen kennis gevonden", "No memories to clear": "Geen herinneringen om op te ruimen", @@ -1320,6 +1325,7 @@ "No results": "Geen resultaten gevonden", "No results found": "Geen resultaten gevonden", "No search query generated": "Geen zoekopdracht gegenereerd", + "No servers detected": "", "No skills found": "", "No source available": "Geen bron beschikbaar", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Poort", + "Ports": "", "Positive attitude": "Positieve houding", "Prefer not to say": "", "Prefix ID": "Voorvoegsel-ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Antwoord splitsing", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "Resultaat", "RESULT": "Resultaat", "Retrieval": "Ophalen", @@ -1583,6 +1591,7 @@ "Role": "Rol", "RTL": "RNL", "Run": "Uitvoeren", + "Run All": "", "Running": "Aan het uitvoeren", "Running...": "Aan het uitvoeren...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Begin van het kanaal", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Je bent nu ingelogd.", "Your Account": "", "Your account status is currently pending activation.": "Je accountstatus wacht nu op activatie", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Je volledige bijdrage gaat direct naar de ontwikkelaar van de plugin; Open WebUI neemt hier geen deel van. Het gekozen financieringsplatform kan echter wel zijn eigen kosten hebben.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/pa-IN/translation.json b/src/lib/i18n/locales/pa-IN/translation.json index 5cb4cb5ed1..3edbf74bd8 100644 --- a/src/lib/i18n/locales/pa-IN/translation.json +++ b/src/lib/i18n/locales/pa-IN/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "ਗੱਲਬਾਤ", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "ਗੱਲਬਾਤ ਬਬਲ UI", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "ਕਲਿੱਪਬੋਰਡ ਸਮੱਗਰੀ ਪੜ੍ਹਣ ਵਿੱਚ ਅਸਫਲ", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "ਕੋਈ ਨਤੀਜੇ ਨਹੀਂ ਮਿਲੇ", "No results found": "ਕੋਈ ਨਤੀਜੇ ਨਹੀਂ ਮਿਲੇ", "No search query generated": "ਕੋਈ ਖੋਜ ਪੁੱਛਗਿੱਛ ਤਿਆਰ ਨਹੀਂ ਕੀਤੀ ਗਈ", + "No servers detected": "", "No skills found": "", "No source available": "ਕੋਈ ਸਰੋਤ ਉਪਲਬਧ ਨਹੀਂ", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "ਸਕਾਰਾਤਮਕ ਰਵੱਈਆ", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "ਨਤੀਜਾ", "Retrieval": "", @@ -1583,6 +1591,7 @@ "Role": "ਭੂਮਿਕਾ", "RTL": "RTL", "Run": "", + "Run All": "", "Running": "", "Running...": "ਚੱਲ ਰਿਹਾ ਹੈ...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "ਚੈਨਲ ਦੀ ਸ਼ੁਰੂਆਤ", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "ਤੁਸੀਂ ਹੁਣ ਲੌਗ ਇਨ ਹੋ ਗਏ ਹੋ।", "Your Account": "", "Your account status is currently pending activation.": "", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/pl-PL/translation.json b/src/lib/i18n/locales/pl-PL/translation.json index 5494b0ecb4..da19789867 100644 --- a/src/lib/i18n/locales/pl-PL/translation.json +++ b/src/lib/i18n/locales/pl-PL/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Limit znaków dla wejścia autouzupełniania", "Chart new frontiers": "Poznawaj nowe możliwości", "Chat": "Czat", + "Chat archived.": "", "Chat Background Image": "Tło czatu", "Chat Bubble UI": "Wygląd dymków czatu", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Efekt zanikania generowanego tekstu", "Failed to add file.": "Nie udało się dodać pliku.", "Failed to add members": "Nie udało się dodać członków", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "Nie udało się wyczyścić statusu", "Failed to connect to {{URL}} OpenAPI tool server": "Nie udało się połączyć z serwerem narzędzi OpenAPI {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "Nie udało się wygenerować tytułu", "Failed to import models": "Nie udało się zaimportować modeli", "Failed to load chat preview": "Nie udało się załadować podglądu czatu", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "Nie udało się załadować pliku Excel/CSV. Spróbuj go pobrać.", "Failed to load file content.": "Nie udało się załadować zawartości pliku.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Nie udało się przenieść czatu", "Failed to process URL: {{url}}": "Nie udało się przetworzyć URL: {{url}}", "Failed to read clipboard contents": "Nie udało się odczytać schowka", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Nie znaleziono treści HTML, CSS ani JS.", "No inference engine with management support found": "Nie znaleziono silnika wnioskowania ze wsparciem zarządzania", + "No kernel": "", "No knowledge bases found.": "Nie znaleziono baz wiedzy.", "No knowledge found": "Nie znaleziono wiedzy", "No memories to clear": "Brak danych w pamięci do wyczyszczenia", @@ -1320,6 +1325,7 @@ "No results": "Brak wyników", "No results found": "Brak wyników", "No search query generated": "Nie wygenerowano zapytania wyszukiwania", + "No servers detected": "", "No skills found": "", "No source available": "Brak dostępnego źródła", "No sources found": "Nie znaleziono źródeł", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "Wybierz co najmniej jednego użytkownika do czatu prywatnego.", "Please wait until all files are uploaded.": "Poczekaj na przesłanie wszystkich plików.", "Port": "Port", + "Ports": "", "Positive attitude": "Pozytywne nastawienie", "Prefer not to say": "Wolę nie mówić", "Prefix ID": "Prefix ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Podział odpowiedzi", "Response Watermark": "Znak wodny odpowiedzi", "Responses": "", + "Restart": "", "Result": "Wynik", "RESULT": "WYNIK", "Retrieval": "Retrieval (Pobieranie)", @@ -1585,6 +1593,7 @@ "Role": "Rola", "RTL": "RTL (Od prawej)", "Run": "Uruchom", + "Run All": "", "Running": "Działa", "Running...": "Działa...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "Uruchamia zadania embeddingu współbieżnie. Wyłącz, jeśli masz limity API.", @@ -1775,6 +1784,7 @@ "Start a new conversation": "Rozpocznij nową rozmowę", "Start of the channel": "Początek kanału", "Start Tag": "Tag startowy", + "Starting kernel...": "", "Status": "Status", "Status cleared successfully": "Status wyczyszczony pomyślnie", "Status updated successfully": "Status zaktualizowany pomyślnie", @@ -2119,6 +2129,8 @@ "You're now logged in.": "Zalogowano pomyślnie.", "Your Account": "Twoje konto", "Your account status is currently pending activation.": "Twoje konto oczekuje na aktywację.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Cała wpłata trafia do twórcy pluginu; Open WebUI nie pobiera prowizji. Wybrana platforma płatnicza może jednak naliczać własne opłaty.", "Your message text or inputs": "Treść wiadomości lub dane wejściowe", "Your usage stats have been successfully synced.": "Twoje statystyki użycia zostały pomyślnie zsynchronizowane.", diff --git a/src/lib/i18n/locales/pt-BR/translation.json b/src/lib/i18n/locales/pt-BR/translation.json index daa7378fd1..74d0febaf7 100644 --- a/src/lib/i18n/locales/pt-BR/translation.json +++ b/src/lib/i18n/locales/pt-BR/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Limite de caracteres para entrada de geração de preenchimento automático", "Chart new frontiers": "Trace novas fronteiras", "Chat": "Chat", + "Chat archived.": "", "Chat Background Image": "Imagem de Fundo do Chat", "Chat Bubble UI": "Interface de Bolha de Chat", "Chat Completions": "Gerar Resposta", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Efeito de Fade para texto em streaming", "Failed to add file.": "Falha ao adicionar arquivo.", "Failed to add members": "Falha ao adicionar membros", + "Failed to archive chat.": "", "Failed to attach file": "Falha ao anexar arquivo", "Failed to clear status": "Falha ao limpar o status", "Failed to connect to {{URL}} OpenAPI tool server": "Falha ao conectar ao servidor da ferramenta OpenAPI {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "Falha ao gerar título", "Failed to import models": "Falha ao importar modelos", "Failed to load chat preview": "Falha ao carregar a pré-visualização do chat", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "Não foi possível carregar o arquivo Excel/CSV. Tente baixá-lo em vez disso.", "Failed to load file content.": "Falha ao carregar o conteúdo do arquivo.", "Failed to load Interface settings": "Falha ao carregar configurações da Interface", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Falha ao mover o chat", "Failed to process URL: {{url}}": "Falha ao processar URL: {{url}}", "Failed to read clipboard contents": "Falha ao ler o conteúdo da área de transferência", @@ -1305,6 +1309,7 @@ "No history available": "Não há histórico disponível.", "No HTML, CSS, or JavaScript content found.": "Nenhum conteúdo HTML, CSS ou JavaScript encontrado.", "No inference engine with management support found": "Nenhum mecanismo de inferência com suporte de gerenciamento encontrado", + "No kernel": "", "No knowledge bases found.": "Nenhuma base de conhecimento encontrada.", "No knowledge found": "Nenhum conhecimento encontrado", "No memories to clear": "Nenhuma memória para limpar", @@ -1320,6 +1325,7 @@ "No results": "Nenhum resultado encontrado", "No results found": "Nenhum resultado encontrado", "No search query generated": "Nenhuma consulta de pesquisa gerada", + "No servers detected": "", "No skills found": "Nenhuma skill encontrada", "No source available": "Nenhuma fonte disponível", "No sources found": "Nenhuma fonte encontrada", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "Por favor, selecione pelo menos um usuário para o canal de Mensagens Diretas.", "Please wait until all files are uploaded.": "Aguarde até que todos os arquivos sejam enviados.", "Port": "Porta", + "Ports": "", "Positive attitude": "Atitude positiva", "Prefer not to say": "Prefiro não dizer", "Prefix ID": "Prefixo ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Divisão da Resposta", "Response Watermark": "Marca d'água de resposta", "Responses": "Respostas", + "Restart": "", "Result": "Resultado", "RESULT": "Resultado", "Retrieval": "Recuperação", @@ -1584,6 +1592,7 @@ "Role": "Função", "RTL": "Direita para Esquerda", "Run": "Executar", + "Run All": "", "Running": "Executando", "Running...": "Executando...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "Executa tarefas de incorporação simultaneamente para acelerar o processamento. Desative se os limites de taxa se tornarem um problema.", @@ -1774,6 +1783,7 @@ "Start a new conversation": "Iniciar uma nova conversa", "Start of the channel": "Início do canal", "Start Tag": "Tag inicial", + "Starting kernel...": "", "Status": "Status", "Status cleared successfully": "Status liberado com sucesso", "Status updated successfully": "Status atualizado com sucesso", @@ -2118,6 +2128,8 @@ "You're now logged in.": "Você agora está logado.", "Your Account": "Sua conta", "Your account status is currently pending activation.": "O status da sua conta está atualmente aguardando ativação.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Toda a sua contribuição irá diretamente para o desenvolvedor do plugin; o Open WebUI não retém nenhuma porcentagem. No entanto, a plataforma de financiamento escolhida pode ter suas próprias taxas.", "Your message text or inputs": "Seu texto de mensagem ou entradas", "Your usage stats have been successfully synced.": "Suas estatísticas de uso foram sincronizadas com sucesso.", diff --git a/src/lib/i18n/locales/pt-PT/translation.json b/src/lib/i18n/locales/pt-PT/translation.json index e1aa139957..dc7efc5700 100644 --- a/src/lib/i18n/locales/pt-PT/translation.json +++ b/src/lib/i18n/locales/pt-PT/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "Conversa", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "Bolha UI da Conversa", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Falha ao ler o conteúdo da área de transferência", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Não foram encontrados resultados", "No results found": "Não foram encontrados resultados", "No search query generated": "Não foi gerada nenhuma consulta de pesquisa", + "No servers detected": "", "No skills found": "", "No source available": "Nenhuma fonte disponível", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "Atitude Positiva", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "RESULTADO", "Retrieval": "", @@ -1584,6 +1592,7 @@ "Role": "Função", "RTL": "RTL", "Run": "", + "Run All": "", "Running": "A correr", "Running...": "A correr...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1774,6 +1783,7 @@ "Start a new conversation": "", "Start of the channel": "Início do canal", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2118,6 +2128,8 @@ "You're now logged in.": "Você agora está conectado.", "Your Account": "", "Your account status is currently pending activation.": "O status da sua conta está atualmente com a ativação pendente.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/ro-RO/translation.json b/src/lib/i18n/locales/ro-RO/translation.json index 973e54d5af..2b953f16bb 100644 --- a/src/lib/i18n/locales/ro-RO/translation.json +++ b/src/lib/i18n/locales/ro-RO/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "Conversație", + "Chat archived.": "", "Chat Background Image": "Imagine de Fundal pentru Conversație", "Chat Bubble UI": "Interfață cu Bule de Conversație", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Eșec la adăugarea fișierului.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Citirea conținutului clipboard-ului a eșuat", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Niciun conținut HTML, CSS sau JavaScript găsit.", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Nu au fost găsite informații.", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Nu au fost găsite rezultate", "No results found": "Nu au fost găsite rezultate", "No search query generated": "Nu a fost generată nicio interogare de căutare", + "No servers detected": "", "No skills found": "", "No source available": "Nicio sursă disponibilă", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "Atitudine pozitivă", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "Împărțirea răspunsurilor", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "Rezultat", "RESULT": "Rezultat", "Retrieval": "", @@ -1584,6 +1592,7 @@ "Role": "Rol", "RTL": "RTL", "Run": "Execută", + "Run All": "", "Running": "Rulează", "Running...": "Rulează...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1774,6 +1783,7 @@ "Start a new conversation": "", "Start of the channel": "Începutul canalului", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2118,6 +2128,8 @@ "You're now logged in.": "Acum ești autentificat.", "Your Account": "", "Your account status is currently pending activation.": "Statusul contului dvs. este în așteptare pentru activare.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Întreaga dvs. contribuție va merge direct la dezvoltatorul plugin-ului; Open WebUI nu ia niciun procent. Cu toate acestea, platforma de finanțare aleasă ar putea avea propriile taxe.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/ru-RU/translation.json b/src/lib/i18n/locales/ru-RU/translation.json index a966f6d728..7e36725824 100644 --- a/src/lib/i18n/locales/ru-RU/translation.json +++ b/src/lib/i18n/locales/ru-RU/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Ограничение количества символов для ввода при генерации автозаполнения", "Chart new frontiers": "Наметьте новые границы", "Chat": "Чат", + "Chat archived.": "", "Chat Background Image": "Фоновое изображение чата", "Chat Bubble UI": "Bubble UI чат", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "Эффект затухания для потокового текста", "Failed to add file.": "Не удалось добавить файл.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Не удалось подключиться к серверу инструмента OpenAI {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "Не удалось сгенерировать заголовок", "Failed to import models": "", "Failed to load chat preview": "Не удалось загрузить предпросмотр чата", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "Не удалось загрузить содержимое файла.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "Не удалось переместить чат", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Не удалось прочитать содержимое буфера обмена", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Содержимое в формате HTML, CSS или JavaScript не найдено.", "No inference engine with management support found": "Механизм логического вывода с поддержкой управления не найден", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Знания не найдены", "No memories to clear": "Нет воспоминаний, которые нужно было бы очистить", @@ -1320,6 +1325,7 @@ "No results": "Результатов не найдено", "No results found": "Результатов не найдено", "No search query generated": "Поисковый запрос не сгенерирован", + "No servers detected": "", "No skills found": "", "No source available": "Нет доступных источников", "No sources found": "Источники не найдены", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "Пожалуйста, подождите, пока все файлы будут загружены.", "Port": "Порт", + "Ports": "", "Positive attitude": "Позитивный настрой", "Prefer not to say": "Предпочитаю не говорить", "Prefix ID": "ID префикса", @@ -1571,6 +1578,7 @@ "Response splitting": "Разделение ответов", "Response Watermark": "Водяной знак ответа", "Responses": "", + "Restart": "", "Result": "Результат", "RESULT": "Результат", "Retrieval": "Поиск", @@ -1585,6 +1593,7 @@ "Role": "Роль", "RTL": "RTL", "Run": "Запустить", + "Run All": "", "Running": "Выполняется", "Running...": "Выполняется...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1775,6 +1784,7 @@ "Start a new conversation": "", "Start of the channel": "Начало канала", "Start Tag": "Начальный тег", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2119,6 +2129,8 @@ "You're now logged in.": "Вы вошли в систему.", "Your Account": "Ваш аккаунт", "Your account status is currently pending activation.": "В настоящее время ваша учетная запись ожидает активации.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Весь ваш взнос будет направлен непосредственно разработчику плагина; Open WebUI не взимает никаких процентов. Однако выбранная платформа финансирования может иметь свои собственные сборы.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/sk-SK/translation.json b/src/lib/i18n/locales/sk-SK/translation.json index 14cce2feae..631818be15 100644 --- a/src/lib/i18n/locales/sk-SK/translation.json +++ b/src/lib/i18n/locales/sk-SK/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "Chat", + "Chat archived.": "", "Chat Background Image": "Obrázok pozadia chatu", "Chat Bubble UI": "Používateľské rozhranie bublín chatu (Chat Bubble UI)", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Nepodarilo sa pridať súbor.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Nepodarilo sa prečítať obsah schránky", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Nebola nájdená žiadny obsah HTML, CSS ani JavaScript.", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "Neboli nájdené žiadne znalostné databázy.", "No knowledge found": "Neboli nájdené žiadne znalosti", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Neboli nájdené žiadne výsledky", "No results found": "Neboli nájdené žiadne výsledky", "No search query generated": "Nebola vygenerovaná žiadna vyhľadávacia otázka.", + "No servers detected": "", "No skills found": "", "No source available": "Nie je dostupný žiadny zdroj.", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "Pozitívny prístup", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "Rozdelenie odpovede", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "Výsledok", "RESULT": "Výsledok", "Retrieval": "", @@ -1585,6 +1593,7 @@ "Role": "Funkcia", "RTL": "RTL", "Run": "Spustiť", + "Run All": "", "Running": "Spúšťanie", "Running...": "Spúšťanie...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1775,6 +1784,7 @@ "Start a new conversation": "", "Start of the channel": "Začiatok kanála", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2119,6 +2129,8 @@ "You're now logged in.": "Teraz ste prihlásený(-á).", "Your Account": "Váš účet", "Your account status is currently pending activation.": "Stav vášho účtu je aktuálne čakajúci na aktiváciu.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Celý váš príspevok pôjde priamo vývojárovi pluginu; Open WebUI si neberie žiadne percento. Zvolená platforma na financovanie však môže mať vlastné poplatky.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/sr-RS/translation.json b/src/lib/i18n/locales/sr-RS/translation.json index 39c9d05530..1a0a7bd106 100644 --- a/src/lib/i18n/locales/sr-RS/translation.json +++ b/src/lib/i18n/locales/sr-RS/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "Откриј нове границе", "Chat": "Ћаскање", + "Chat archived.": "", "Chat Background Image": "Позадинска слика ћаскања", "Chat Bubble UI": "Прочеље балона ћаскања", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Неуспешно читање садржаја оставе", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Нема резултата", "No results found": "Нема резултата", "No search query generated": "Није генерисан упит за претрагу", + "No servers detected": "", "No skills found": "", "No source available": "Нема доступног извора", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "Позитиван став", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "Исход", "RESULT": "Исход", "Retrieval": "", @@ -1584,6 +1592,7 @@ "Role": "Улога", "RTL": "ДНЛ", "Run": "Покрени", + "Run All": "", "Running": "Покрећем", "Running...": "Покрећем...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1774,6 +1783,7 @@ "Start a new conversation": "", "Start of the channel": "Почетак канала", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2118,6 +2128,8 @@ "You're now logged in.": "Сада сте пријављени.", "Your Account": "", "Your account status is currently pending activation.": "", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/sv-SE/translation.json b/src/lib/i18n/locales/sv-SE/translation.json index 95c7e54535..1459d67bf8 100644 --- a/src/lib/i18n/locales/sv-SE/translation.json +++ b/src/lib/i18n/locales/sv-SE/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Teckengräns för inmatning av automatisk komplettering", "Chart new frontiers": "Utforska nya gränser", "Chat": "Chatt", + "Chat archived.": "", "Chat Background Image": "Bakgrundsbild för chatt", "Chat Bubble UI": "UI för Chatbubblor", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Misslyckades med att lägga till fil.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Misslyckades med att ansluta till {{URL}} OpenAPI-verktygsserver", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "Misslyckades med att läsa in filinnehåll.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Misslyckades med att läsa urklippsinnehåll", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Inget HTML-, CSS- eller JavaScript-innehåll hittades.", "No inference engine with management support found": "Ingen inferensmotor med stöd för hantering hittades", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Ingen kunskapsbas hittades", "No memories to clear": "Inga minnen att rensa", @@ -1320,6 +1325,7 @@ "No results": "Inga resultat hittades", "No results found": "Inga resultat hittades", "No search query generated": "Ingen sökfråga genererad", + "No servers detected": "", "No skills found": "", "No source available": "Ingen tillgänglig källa", "No sources found": "Inga källor hittades", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "Vänta tills alla filer har laddats upp.", "Port": "Port", + "Ports": "", "Positive attitude": "Positivt inställning", "Prefer not to say": "Föredrar att inte att säga", "Prefix ID": "Prefix-ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Svarsdelning", "Response Watermark": "Svarsvattenstämpel", "Responses": "", + "Restart": "", "Result": "Resultat", "RESULT": "Resultat", "Retrieval": "Hämtning", @@ -1583,6 +1591,7 @@ "Role": "Roll", "RTL": "RTL", "Run": "Kör", + "Run All": "", "Running": "Kör", "Running...": "Kör...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "Starta en ny konversation", "Start of the channel": "Början av kanalen", "Start Tag": "Starta en tagg", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Du är nu inloggad.", "Your Account": "Ditt konto", "Your account status is currently pending activation.": "Ditt konto väntar på att bli aktiverat", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Hela ditt bidrag går direkt till pluginutvecklaren; Open WebUI tar ingen procentandel. Däremot kan den valda finansieringsplattformen ha egna avgifter.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/th-TH/translation.json b/src/lib/i18n/locales/th-TH/translation.json index 6cae379db6..4092f0e7fd 100644 --- a/src/lib/i18n/locales/th-TH/translation.json +++ b/src/lib/i18n/locales/th-TH/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "ขีดจำกัดจำนวนอักขระสำหรับอินพุตการสร้างคำอัตโนมัติ", "Chart new frontiers": "สำรวจพรมแดนใหม่", "Chat": "แชท", + "Chat archived.": "", "Chat Background Image": "ภาพพื้นหลังแชท", "Chat Bubble UI": "ส่วนติดต่อผู้ใช้แบบฟองแชท", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "เอฟเฟ็กต์เฟดสำหรับข้อความสตรีมมิ่ง", "Failed to add file.": "ไม่สามารถเพิ่มไฟล์ได้", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "เชื่อมต่อกับเซิร์ฟเวอร์เครื่องมือ OpenAPI ที่ {{URL}} ไม่สำเร็จ", @@ -836,9 +838,11 @@ "Failed to generate title": "สร้างชื่อไม่สำเร็จ", "Failed to import models": "นำเข้าโมเดลไม่สำเร็จ", "Failed to load chat preview": "ไม่สามารถโหลดตัวอย่างแชทได้", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "โหลดเนื้อหาไฟล์ไม่สำเร็จ", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "ย้ายแชทไม่สำเร็จ", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "อ่านเนื้อหาคลิปบอร์ดไม่สำเร็จ", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "ไม่พบเนื้อหา HTML, CSS หรือ JavaScript", "No inference engine with management support found": "ไม่พบเอนจินอนุมานที่รองรับการจัดการ", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "ไม่พบฐานความรู้", "No memories to clear": "ไม่มีความจำให้ลบ", @@ -1320,6 +1325,7 @@ "No results": "ไม่มีผลลัพธ์", "No results found": "ไม่มีผลลัพธ์", "No search query generated": "ไม่มีการสร้างคำค้นหา", + "No servers detected": "", "No skills found": "", "No source available": "ไม่มีแหล่งที่มา", "No sources found": "ไม่พบแหล่งข้อมูล", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "โปรดรอจนกว่าไฟล์ทั้งหมดจะอัปโหลดเสร็จสิ้น", "Port": "พอร์ต", + "Ports": "", "Positive attitude": "ทัศนคติเชิงบวก", "Prefer not to say": "ไม่ต้องการระบุ", "Prefix ID": "รหัสคำนำหน้า", @@ -1571,6 +1578,7 @@ "Response splitting": "การแยกข้อความตอบกลับ", "Response Watermark": "ลายน้ำของคำตอบ", "Responses": "", + "Restart": "", "Result": "ผลลัพธ์", "RESULT": "ผลลัพธ์", "Retrieval": "การดึงข้อมูล", @@ -1582,6 +1590,7 @@ "Role": "บทบาท", "RTL": "ขวาไปซ้าย", "Run": "เรียกใช้", + "Run All": "", "Running": "กำลังทำงาน", "Running...": "กำลังทำงาน...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1772,6 +1781,7 @@ "Start a new conversation": "เริ่มการสนทนาใหม่", "Start of the channel": "จุดเริ่มต้นของช่อง", "Start Tag": "แท็กเริ่มต้น", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2116,6 +2126,8 @@ "You're now logged in.": "คุณเข้าสู่ระบบแล้ว", "Your Account": "บัญชีของคุณ", "Your account status is currently pending activation.": "สถานะบัญชีของคุณกำลังรอการเปิดใช้งาน", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "การสนับสนุนทั้งหมดของคุณจะถูกส่งไปยังนักพัฒนาปลั๊กอินโดยตรง Open WebUI จะไม่หักส่วนแบ่งใดๆ อย่างไรก็ตาม แพลตฟอร์มการระดมทุนที่คุณเลือกอาจมีการเก็บค่าธรรมเนียมในส่วนของตนเอง", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/tk-TM/translation.json b/src/lib/i18n/locales/tk-TM/translation.json index e5b18b2d33..b8d605fa9c 100644 --- a/src/lib/i18n/locales/tk-TM/translation.json +++ b/src/lib/i18n/locales/tk-TM/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "Çat", + "Chat archived.": "", "Chat Background Image": "", "Chat Bubble UI": "Çat Bubble UI", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "Netije ýok", "No results found": "", "No search query generated": "", + "No servers detected": "", "No skills found": "", "No source available": "", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "", "RESULT": "NETIJE", "Retrieval": "", @@ -1583,6 +1591,7 @@ "Role": "Roli", "RTL": "", "Run": "", + "Run All": "", "Running": "", "Running...": "Işleýär...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Kanal başy", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "", "Your Account": "", "Your account status is currently pending activation.": "", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/tr-TR/translation.json b/src/lib/i18n/locales/tr-TR/translation.json index fe8d75d0d9..9dddccb9cd 100644 --- a/src/lib/i18n/locales/tr-TR/translation.json +++ b/src/lib/i18n/locales/tr-TR/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Otomatik tamamlama üretimi girişi için karakter sınırı", "Chart new frontiers": "", "Chat": "Sohbet", + "Chat archived.": "", "Chat Background Image": "Sohbet Arka Plan Resmi", "Chat Bubble UI": "Sohbet Balonu Arayüzü", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Dosya eklenemedi.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Pano içeriği okunamadı", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "HTML, CSS veya JavaScript içeriği bulunamadı.", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Bilgi bulunamadı", "No memories to clear": "Temizlenecek bellek yok", @@ -1320,6 +1325,7 @@ "No results": "Sonuç bulunamadı", "No results found": "Sonuç bulunamadı", "No search query generated": "Hiç arama sorgusu oluşturulmadı", + "No servers detected": "", "No skills found": "", "No source available": "Kaynak mevcut değil", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Port", + "Ports": "", "Positive attitude": "Olumlu yaklaşım", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "Yanıt bölme", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "Sonuç", "RESULT": "Sonuç", "Retrieval": "", @@ -1583,6 +1591,7 @@ "Role": "Rol", "RTL": "Sağdan Sola", "Run": "Çalıştır", + "Run All": "", "Running": "Çalışıyor", "Running...": "Çalışıyor...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Kanalın başlangıcı", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Şimdi giriş yaptınız.", "Your Account": "Hesabınız", "Your account status is currently pending activation.": "Hesap durumunuz şu anda etkinleştirilmeyi bekliyor.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Tüm katkınız doğrudan eklenti geliştiricisine gidecektir; Open WebUI herhangi bir yüzde almaz. Ancak seçilen finansman platformunun kendi ücretleri olabilir.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/ug-CN/translation.json b/src/lib/i18n/locales/ug-CN/translation.json index 9f2850956c..56dccac739 100644 --- a/src/lib/i18n/locales/ug-CN/translation.json +++ b/src/lib/i18n/locales/ug-CN/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "ئاپتوماتىك تولدۇرۇش كىرگۈزۈشنىڭ ھەرپ چەكى", "Chart new frontiers": "يېڭى چېگرىلارنى پىلانلاش", "Chat": "سۆھبەت", + "Chat archived.": "", "Chat Background Image": "سۆھبەت ئارقا كۆرۈنۈش رەسىمى", "Chat Bubble UI": "سۆھبەت كۆپۈك كۆرۈنمە يۈزى ", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "ھۆججەت قوشۇش مەغلۇپ بولدى.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "{{URL}} OpenAPI قورال مۇلازىمېتىرىغا ئۇلىنىش مەغلۇپ بولدى", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "ھۆججەت مەزمۇنى يۈكلەش مەغلۇپ بولدى.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "چاپلاش تاختىسى مەزمۇنىنى ئوقۇش مەغلۇپ بولدى", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "HTML، CSS ياكى JavaScript مەزمۇنى تېپىلمىدى.", "No inference engine with management support found": "باشقۇرۇشنى قوللايدىغان يەكۈن ماتورى تېپىلمىدى", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "بىلىم تېپىلمىدى", "No memories to clear": "تازلاشقا ئەسلەتمە يوق", @@ -1320,6 +1325,7 @@ "No results": "نەتىجە تېپىلمىدى", "No results found": "نەتىجە تېپىلمىدى", "No search query generated": "ئىزدەش سۇئالى ھاسىل قىلىنمىدى", + "No servers detected": "", "No skills found": "", "No source available": "مەنبە يوق", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "ئېغىز", + "Ports": "", "Positive attitude": "ئىجابىي پوزىتسىيە", "Prefer not to say": "", "Prefix ID": "Prefix ID", @@ -1571,6 +1578,7 @@ "Response splitting": "ئىنكاسنى بۆلۈش", "Response Watermark": "ئىنكاس سۇ بەلگىسى", "Responses": "", + "Restart": "", "Result": "نەتىجە", "RESULT": "نەتىجە", "Retrieval": "قايتۇرۇش", @@ -1583,6 +1591,7 @@ "Role": "رول", "RTL": "RTL (ئوڭدىن سولغا)", "Run": "ئىجرا قىلىش", + "Run All": "", "Running": "ئىجرا قىلىنىۋاتىدۇ", "Running...": "ئىجرا قىلىنىۋاتىدۇ...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "قانالنىڭ باشلانغىنى", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "سىز كىرىپ بولدىڭىز.", "Your Account": "", "Your account status is currently pending activation.": "ھېساباتىڭىزنىڭ ھازىرقى ھالىتى ئاكتىپلىنىشنى كۈتۈۋاتىدۇ.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "تۆلەم پۇلىڭىز بىۋاسىتە قىستۇرما تەرەققىياتچىسىغا بېرىلىدۇ؛ Open WebUI ھېچقانداق پىرسېنت ئالمايدۇ. بىراق تاللانغان مالىيە پلاتفورمىسىنىڭ ئۆزىنىڭ ھەققى بولۇشى مۇمكىن.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/uk-UA/translation.json b/src/lib/i18n/locales/uk-UA/translation.json index a8d81194d8..4d6f5c2060 100644 --- a/src/lib/i18n/locales/uk-UA/translation.json +++ b/src/lib/i18n/locales/uk-UA/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Ліміт символів для введення при генерації автозаповнення", "Chart new frontiers": "Відкривати нові горизонти", "Chat": "Чат", + "Chat archived.": "", "Chat Background Image": "Фонове зображення чату", "Chat Bubble UI": "Чат у вигляді бульбашок", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Не вдалося додати файл.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Не вдалося підключитися до серверу інструментів OpenAPI {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Не вдалося прочитати вміст буфера обміну", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "HTML, CSS або JavaScript контент не знайдено.", "No inference engine with management support found": "Не знайдено двигуна висновків з підтримкою керування", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Знання не знайдено.", "No memories to clear": "Немає спогадів для очищення", @@ -1320,6 +1325,7 @@ "No results": "Не знайдено жодного результату", "No results found": "Не знайдено жодного результату", "No search query generated": "Пошуковий запит не сформовано", + "No servers detected": "", "No skills found": "", "No source available": "Джерело не доступне", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Порт", + "Ports": "", "Positive attitude": "Позитивне ставлення", "Prefer not to say": "", "Prefix ID": "ID префікса", @@ -1571,6 +1578,7 @@ "Response splitting": "Розбиття відповіді", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "Результат", "RESULT": "Результат", "Retrieval": "Пошук", @@ -1585,6 +1593,7 @@ "Role": "Роль", "RTL": "RTL", "Run": "Запустити", + "Run All": "", "Running": "Виконується", "Running...": "Виконується...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1775,6 +1784,7 @@ "Start a new conversation": "", "Start of the channel": "Початок каналу", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2119,6 +2129,8 @@ "You're now logged in.": "Ви увійшли в систему.", "Your Account": "", "Your account status is currently pending activation.": "Статус вашого облікового запису наразі очікує на активацію.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Весь ваш внесок піде безпосередньо розробнику плагіна; Open WebUI не бере жодних відсотків. Однак, обрана платформа фінансування може мати свої власні збори.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/ur-PK/translation.json b/src/lib/i18n/locales/ur-PK/translation.json index b6c34c9ef4..679bfa601b 100644 --- a/src/lib/i18n/locales/ur-PK/translation.json +++ b/src/lib/i18n/locales/ur-PK/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "", "Chart new frontiers": "", "Chat": "چیٹ", + "Chat archived.": "", "Chat Background Image": "چیٹ پس منظر کی تصویر", "Chat Bubble UI": "چیٹ بلبل انٹرفیس", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "فائل شامل کرنے میں ناکام", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "کلپ بورڈ مواد کو پڑھنے میں ناکام", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "کوئی HTML، CSS، یا جاوا اسکرپٹ مواد نہیں ملا", "No inference engine with management support found": "", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "کوئی معلومات نہیں ملی", "No memories to clear": "", @@ -1320,6 +1325,7 @@ "No results": "کوئی نتائج نہیں ملے", "No results found": "کوئی نتائج نہیں ملے", "No search query generated": "کوئی تلاش کی درخواست نہیں بنائی گئی", + "No servers detected": "", "No skills found": "", "No source available": "ماخذ دستیاب نہیں ہے", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "", + "Ports": "", "Positive attitude": "مثبت رویہ", "Prefer not to say": "", "Prefix ID": "", @@ -1571,6 +1578,7 @@ "Response splitting": "جواب کو تقسیم کرنا", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "نتیجہ", "RESULT": "نتیجہ", "Retrieval": "", @@ -1583,6 +1591,7 @@ "Role": "کردار", "RTL": "آر ٹی ایل", "Run": "چلائیں", + "Run All": "", "Running": "چل رہا ہے", "Running...": "چل رہا ہے...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "چینل کی شروعات", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "آپ اب لاگ ان ہو چکے ہیں", "Your Account": "", "Your account status is currently pending activation.": "آپ کے اکاؤنٹ کی حالت فی الحال فعال ہونے کے منتظر ہے", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "آپ کی پوری شراکت براہ راست پلگ ان ڈیولپر کو جائے گی؛ اوپن ویب یو آئی کوئی فیصد نہیں لیتی تاہم، منتخب کردہ فنڈنگ پلیٹ فارم کی اپنی فیس ہو سکتی ہیں", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/uz-Cyrl-UZ/translation.json b/src/lib/i18n/locales/uz-Cyrl-UZ/translation.json index a686a8bdc3..f35c516c93 100644 --- a/src/lib/i18n/locales/uz-Cyrl-UZ/translation.json +++ b/src/lib/i18n/locales/uz-Cyrl-UZ/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Автоматик тўлдиришни яратиш учун белгилар чегараси", "Chart new frontiers": "Янги чегараларни белгиланг", "Chat": "Чат", + "Chat archived.": "", "Chat Background Image": "Чат фон расми", "Chat Bubble UI": "Сhat Bubble Интерфейси", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Файл қўшиб бўлмади.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "{{УРЛ}} ОпенАПИ асбоб серверига уланиб бўлмади", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "Файл таркибини юклаб бўлмади.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Буфер таркибини ўқиб бўлмади", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "HTML, CСС ёки ЖаваСcрипт контенти топилмади.", "No inference engine with management support found": "Бошқарув ёрдами билан хулоса чиқариш механизми топилмади", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Ҳеч қандай билим топилмади", "No memories to clear": "Тозалаш учун хотиралар йўқ", @@ -1320,6 +1325,7 @@ "No results": "Ҳеч қандай натижа топилмади", "No results found": "Ҳеч қандай натижа топилмади", "No search query generated": "Ҳеч қандай қидирув сўрови яратилмади", + "No servers detected": "", "No skills found": "", "No source available": "Манба мавжуд эмас", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Порт", + "Ports": "", "Positive attitude": "Ижобий муносабат", "Prefer not to say": "", "Prefix ID": "Префикс идентификатори", @@ -1571,6 +1578,7 @@ "Response splitting": "Жавобни ажратиш", "Response Watermark": "Жавоб сув белгиси", "Responses": "", + "Restart": "", "Result": "Натижа", "RESULT": "Натижа", "Retrieval": "Қидирув", @@ -1583,6 +1591,7 @@ "Role": "Рол", "RTL": "RTL", "Run": "Ишга тушириш", + "Run All": "", "Running": "Ишлаётган", "Running...": "Ишлаётган...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Канал боши", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Сиз энди тизимга кирдингиз.", "Your Account": "", "Your account status is currently pending activation.": "Ҳисобингиз ҳолати ҳозирда фаоллаштиришни кутмоқда.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Сизнинг барча ҳиссангиз тўғридан-тўғри плагин ишлаб чиқарувчисига ўтади; Open WebUI ҳеч қандай фоизни олмайди. Бироқ, танланган молиялаштириш платформаси ўз тўловларига эга бўлиши мумкин.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/uz-Latn-Uz/translation.json b/src/lib/i18n/locales/uz-Latn-Uz/translation.json index 033271e9a6..2af10b56d4 100644 --- a/src/lib/i18n/locales/uz-Latn-Uz/translation.json +++ b/src/lib/i18n/locales/uz-Latn-Uz/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Avtomatik toʻldirishni yaratish uchun belgilar chegarasi", "Chart new frontiers": "Yangi chegaralarni belgilang", "Chat": "Chat", + "Chat archived.": "", "Chat Background Image": "Chat fon rasmi", "Chat Bubble UI": "Chat Bubble UI", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Fayl qo‘shib bo‘lmadi.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "{{URL}} OpenAPI asbob serveriga ulanib boʻlmadi", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "Fayl tarkibini yuklab bo‘lmadi.", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Bufer tarkibini o‘qib bo‘lmadi", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "HTML, CSS yoki JavaScript kontenti topilmadi.", "No inference engine with management support found": "Boshqaruv yordami bilan xulosa chiqarish mexanizmi topilmadi", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Hech qanday bilim topilmadi", "No memories to clear": "Tozalash uchun xotiralar yo'q", @@ -1320,6 +1325,7 @@ "No results": "Hech qanday natija topilmadi", "No results found": "Hech qanday natija topilmadi", "No search query generated": "Hech qanday qidiruv soʻrovi yaratilmadi", + "No servers detected": "", "No skills found": "", "No source available": "Manba mavjud emas", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Port", + "Ports": "", "Positive attitude": "Ijobiy munosabat", "Prefer not to say": "", "Prefix ID": "Prefiks identifikatori", @@ -1571,6 +1578,7 @@ "Response splitting": "Javobni ajratish", "Response Watermark": "Javob suv belgisi", "Responses": "", + "Restart": "", "Result": "Natija", "RESULT": "Natija", "Retrieval": "Qidiruv", @@ -1583,6 +1591,7 @@ "Role": "Rol", "RTL": "RTL", "Run": "Yugurish", + "Run All": "", "Running": "Yugurish", "Running...": "Yugurish...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1773,6 +1782,7 @@ "Start a new conversation": "", "Start of the channel": "Kanal boshlanishi", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2117,6 +2127,8 @@ "You're now logged in.": "Siz endi tizimga kirdingiz.", "Your Account": "", "Your account status is currently pending activation.": "Hisobingiz holati hozirda faollashtirishni kutmoqda.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Sizning barcha hissangiz to'g'ridan-to'g'ri plagin ishlab chiqaruvchisiga o'tadi; Open WebUI hech qanday foizni olmaydi. Biroq, tanlangan moliyalashtirish platformasi o'z to'lovlariga ega bo'lishi mumkin.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/vi-VN/translation.json b/src/lib/i18n/locales/vi-VN/translation.json index 02475c3aa3..637321ef3a 100644 --- a/src/lib/i18n/locales/vi-VN/translation.json +++ b/src/lib/i18n/locales/vi-VN/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "Giới hạn ký tự cho đầu vào tạo tự động hoàn thành", "Chart new frontiers": "Vẽ nên những giới hạn mới", "Chat": "Trò chuyện", + "Chat archived.": "", "Chat Background Image": "Hình nền trò chuyện", "Chat Bubble UI": "Bảng chat", "Chat Completions": "", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "", "Failed to add file.": "Không thể thêm tệp.", "Failed to add members": "", + "Failed to archive chat.": "", "Failed to attach file": "", "Failed to clear status": "", "Failed to connect to {{URL}} OpenAPI tool server": "Không thể kết nối đến máy chủ công cụ OpenAPI {{URL}}", @@ -836,9 +838,11 @@ "Failed to generate title": "", "Failed to import models": "", "Failed to load chat preview": "", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "", "Failed to load file content.": "", "Failed to load Interface settings": "", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Không thể đọc nội dung clipboard", @@ -1305,6 +1309,7 @@ "No history available": "", "No HTML, CSS, or JavaScript content found.": "Không tìm thấy nội dung HTML, CSS hoặc JavaScript.", "No inference engine with management support found": "Không tìm thấy engine suy luận nào có hỗ trợ quản lý", + "No kernel": "", "No knowledge bases found.": "", "No knowledge found": "Không tìm thấy kiến thức", "No memories to clear": "Không có bộ nhớ nào để xóa", @@ -1320,6 +1325,7 @@ "No results": "Không tìm thấy kết quả", "No results found": "Không tìm thấy kết quả", "No search query generated": "Không có truy vấn tìm kiếm nào được tạo ra", + "No servers detected": "", "No skills found": "", "No source available": "Không có nguồn", "No sources found": "", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "", "Please wait until all files are uploaded.": "", "Port": "Cổng", + "Ports": "", "Positive attitude": "Thái độ tích cực", "Prefer not to say": "", "Prefix ID": "Tiền tố ID", @@ -1571,6 +1578,7 @@ "Response splitting": "Phân tách phản hồi", "Response Watermark": "", "Responses": "", + "Restart": "", "Result": "Kết quả", "RESULT": "Kết quả", "Retrieval": "Truy xuất", @@ -1582,6 +1590,7 @@ "Role": "Vai trò", "RTL": "RTL", "Run": "Thực hiện", + "Run All": "", "Running": "Đang chạy", "Running...": "Đang chạy...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "", @@ -1772,6 +1781,7 @@ "Start a new conversation": "", "Start of the channel": "Đầu kênh", "Start Tag": "", + "Starting kernel...": "", "Status": "", "Status cleared successfully": "", "Status updated successfully": "", @@ -2116,6 +2126,8 @@ "You're now logged in.": "Bạn đã đăng nhập.", "Your Account": "", "Your account status is currently pending activation.": "Tài khoản của bạn hiện đang ở trạng thái chờ kích hoạt.", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Toàn bộ đóng góp của bạn sẽ được chuyển trực tiếp đến nhà phát triển plugin; Open WebUI không lấy bất kỳ tỷ lệ phần trăm nào. Tuy nhiên, nền tảng được chọn tài trợ có thể có phí riêng.", "Your message text or inputs": "", "Your usage stats have been successfully synced.": "", diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json index 4c1ec974bf..9fac1d692e 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "输入框内容自动补全输入的字符限制", "Chart new frontiers": "开辟前沿", "Chat": "对话", + "Chat archived.": "", "Chat Background Image": "对话背景图片", "Chat Bubble UI": "以聊天气泡的形式显示对话内容", "Chat Completions": "Chat Completions", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "流式输出内容时启用动态渐显效果", "Failed to add file.": "添加文件失败", "Failed to add members": "添加成员失败", + "Failed to archive chat.": "", "Failed to attach file": "文件上传失败", "Failed to clear status": "清除状态失败", "Failed to connect to {{URL}} OpenAPI tool server": "连接到 {{URL}} OpenAPI 工具服务器失败", @@ -836,9 +838,11 @@ "Failed to generate title": "生成标题失败", "Failed to import models": "导入模型配置失败", "Failed to load chat preview": "对话预览加载失败", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "加载 Excel/CSV 文件失败,请尝试直接下载文件。", "Failed to load file content.": "文件内容加载失败", "Failed to load Interface settings": "“界面设置”数据加载失败", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "移动对话失败", "Failed to process URL: {{url}}": "处理链接失败: {{url}}", "Failed to read clipboard contents": "读取剪贴板内容失败", @@ -1305,6 +1309,7 @@ "No history available": "暂无历史记录", "No HTML, CSS, or JavaScript content found.": "未找到 HTML、CSS 或 JavaScript 内容。", "No inference engine with management support found": "未找到支持管理的推理引擎", + "No kernel": "", "No knowledge bases found.": "未找到知识库", "No knowledge found": "未找到知识", "No memories to clear": "记忆为空,无须清理", @@ -1320,6 +1325,7 @@ "No results": "未找到结果", "No results found": "未找到结果", "No search query generated": "未生成搜索查询", + "No servers detected": "", "No skills found": "没有找到技能", "No source available": "没有可用引用来源", "No sources found": "未找到任何引用来源", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "请至少选择一个用户以创建私聊频道。", "Please wait until all files are uploaded.": "请等待所有文件上传完毕。", "Port": "端口", + "Ports": "", "Positive attitude": "态度积极", "Prefer not to say": "暂不透露", "Prefix ID": "模型 ID 前缀", @@ -1571,6 +1578,7 @@ "Response splitting": "拆分回答", "Response Watermark": "复制时添加水印", "Responses": "Responses", + "Restart": "", "Result": "结果", "RESULT": "结果", "Retrieval": "检索", @@ -1582,6 +1590,7 @@ "Role": "角色", "RTL": "从右至左", "Run": "运行", + "Run All": "", "Running": "运行中", "Running...": "运行中...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "并行运行嵌入任务以加快处理速度。如果遇到限速问题,请关闭此选项。", @@ -1772,6 +1781,7 @@ "Start a new conversation": "开始新对话", "Start of the channel": "频道起点", "Start Tag": "起始标签", + "Starting kernel...": "", "Status": "状态", "Status cleared successfully": "状态已清除", "Status updated successfully": "状态已更新", @@ -2116,6 +2126,8 @@ "You're now logged in.": "已登录。", "Your Account": "您的账号", "Your account status is currently pending activation.": "您的账号当前状态为待激活", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "您的全部捐款将直接给到插件开发者,Open WebUI 不会收取任何分成。但众筹平台可能会有服务费。", "Your message text or inputs": "您的消息文本或输入", "Your usage stats have been successfully synced.": "已成功同步您的使用统计数据。", diff --git a/src/lib/i18n/locales/zh-TW/translation.json b/src/lib/i18n/locales/zh-TW/translation.json index 0fb0346019..996b4d48da 100644 --- a/src/lib/i18n/locales/zh-TW/translation.json +++ b/src/lib/i18n/locales/zh-TW/translation.json @@ -282,6 +282,7 @@ "Character limit for autocomplete generation input": "自動完成產生輸入的字元限制", "Chart new frontiers": "探索新領域", "Chat": "對話", + "Chat archived.": "", "Chat Background Image": "對話背景圖片", "Chat Bubble UI": "對話氣泡介面", "Chat Completions": "對話續寫", @@ -822,6 +823,7 @@ "Fade Effect for Streaming Text": "串流文字淡入效果", "Failed to add file.": "新增檔案失敗。", "Failed to add members": "新增成員失敗", + "Failed to archive chat.": "", "Failed to attach file": "檔案上傳失敗", "Failed to clear status": "清除狀態失敗", "Failed to connect to {{URL}} OpenAPI tool server": "無法連線至 {{URL}} OpenAPI 工具伺服器", @@ -836,9 +838,11 @@ "Failed to generate title": "產生標題失敗", "Failed to import models": "匯入模型失敗", "Failed to load chat preview": "對話預覽載入失敗", + "Failed to load DOCX file. Please try downloading it instead.": "", "Failed to load Excel/CSV file. Please try downloading it instead.": "無法載入 Excel/CSV 檔案。請嘗試直接下載檔案。", "Failed to load file content.": "載入檔案內容失敗。", "Failed to load Interface settings": "「介面設定」資料載入失敗", + "Failed to load PPTX file. Please try downloading it instead.": "", "Failed to move chat": "移動對話失敗", "Failed to process URL: {{url}}": "處理連結失敗:{{url}}", "Failed to read clipboard contents": "讀取剪貼簿內容失敗", @@ -1305,6 +1309,7 @@ "No history available": "暫無歷史紀錄", "No HTML, CSS, or JavaScript content found.": "未找到 HTML、CSS 或 JavaScript 內容。", "No inference engine with management support found": "未找到支援管理功能的推理引擎", + "No kernel": "", "No knowledge bases found.": "未找到知識庫", "No knowledge found": "未找到知識", "No memories to clear": "沒有記憶可清除", @@ -1320,6 +1325,7 @@ "No results": "沒有結果", "No results found": "未找到任何結果", "No search query generated": "未產生搜尋查詢", + "No servers detected": "", "No skills found": "找不到任何技能", "No source available": "無可用來源", "No sources found": "未找到任何來源", @@ -1475,6 +1481,7 @@ "Please select at least one user for Direct Message channel.": "請至少選擇一位使用者以建立直接訊息頻道。", "Please wait until all files are uploaded.": "請等待所有檔案上傳完畢。", "Port": "連接埠", + "Ports": "", "Positive attitude": "積極的態度", "Prefer not to say": "不想透露", "Prefix ID": "前置 ID", @@ -1571,6 +1578,7 @@ "Response splitting": "回應分割", "Response Watermark": "回應浮水印", "Responses": "回答", + "Restart": "", "Result": "結果", "RESULT": "結果", "Retrieval": "檢索", @@ -1582,6 +1590,7 @@ "Role": "角色", "RTL": "從右到左", "Run": "執行", + "Run All": "", "Running": "正在執行", "Running...": "正在執行...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "同時執行嵌入任務以加快處理速度。如果遇到速率限制問題,請關閉此功能。", @@ -1772,6 +1781,7 @@ "Start a new conversation": "開始新對話", "Start of the channel": "頻道起點", "Start Tag": "起始標籤", + "Starting kernel...": "", "Status": "狀態", "Status cleared successfully": "狀態已清除", "Status updated successfully": "狀態已更新", @@ -2116,6 +2126,8 @@ "You're now logged in.": "您已登入。", "Your Account": "您的帳號", "Your account status is currently pending activation.": "您的帳號目前正在等待啟用。", + "Your browser does not support the audio tag.": "", + "Your browser does not support the video tag.": "", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "您的所有貢獻將會直接交給外掛開發者;Open WebUI 不會收取任何抽成。然而,所選擇的贊助平臺可能有其自身的費用。", "Your message text or inputs": "您的訊息文字或輸入", "Your usage stats have been successfully synced.": "已成功同步您的使用統計資料。", diff --git a/src/lib/utils/codeHighlight.ts b/src/lib/utils/codeHighlight.ts index 0e33dd3872..23861bc77b 100644 --- a/src/lib/utils/codeHighlight.ts +++ b/src/lib/utils/codeHighlight.ts @@ -186,4 +186,3 @@ export async function highlightCode(code: string, filePath: string): Promise { - let s = ''; - let n = i; - while (n >= 0) { - s = String.fromCharCode(65 + (n % 26)) + s; - n = Math.floor(n / 26) - 1; - } - return s; + let s = ''; + let n = i; + while (n >= 0) { + s = String.fromCharCode(65 + (n % 26)) + s; + n = Math.floor(n / 26) - 1; + } + return s; }; /** Escape HTML entities */ const esc = (v: unknown): string => { - if (v === null || v === undefined || v === '') return ' '; - return String(v).replace(/&/g, '&').replace(//g, '>'); + if (v === null || v === undefined || v === '') return ' '; + return String(v).replace(/&/g, '&').replace(//g, '>'); }; export interface ExcelTableResult { - html: string; - rowCount: number; - colCount: number; + html: string; + rowCount: number; + colCount: number; } /** @@ -38,49 +38,51 @@ export interface ExcelTableResult { * Uses sheet_to_json with header:1 for a raw 2D array. */ export async function excelToTable(worksheet: WorkSheet): Promise { - const XLSX = await import('xlsx'); - const rows: unknown[][] = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: '' }); + const XLSX = await import('xlsx'); + const rows: unknown[][] = XLSX.utils.sheet_to_json(worksheet, { header: 1, defval: '' }); - if (rows.length === 0) { - return { html: '
#
 
', rowCount: 0, colCount: 0 }; - } + if (rows.length === 0) { + return { + html: '
 
', + rowCount: 0, + colCount: 0 + }; + } - // Determine column count from the widest row - const colCount = rows.reduce((max, row) => Math.max(max, row.length), 0); - const rowCount = rows.length; + // Determine column count from the widest row + const colCount = rows.reduce((max, row) => Math.max(max, row.length), 0); + const rowCount = rows.length; - const parts: string[] = []; - parts.push(''); + const parts: string[] = []; + parts.push('
'); - // Column letter header row - parts.push(''); - parts.push(''); // corner cell - for (let c = 0; c < colCount; c++) { - parts.push(``); - } - parts.push(''); + // Column letter header row + parts.push(''); + parts.push(''); // corner cell + for (let c = 0; c < colCount; c++) { + parts.push(``); + } + parts.push(''); - // Data rows - parts.push(''); - for (let r = 0; r < rowCount; r++) { - const row = rows[r]; - parts.push(''); - parts.push(``); - for (let c = 0; c < colCount; c++) { - const val = c < row.length ? row[c] : ''; - const isNum = typeof val === 'number'; - parts.push( - `${esc(val)}` - ); - } - parts.push(''); - } - parts.push('
${colLetter(c)}
${colLetter(c)}
${r + 1}
'); + // Data rows + parts.push(''); + for (let r = 0; r < rowCount; r++) { + const row = rows[r]; + parts.push(''); + parts.push(`${r + 1}`); + for (let c = 0; c < colCount; c++) { + const val = c < row.length ? row[c] : ''; + const isNum = typeof val === 'number'; + parts.push(`${esc(val)}`); + } + parts.push(''); + } + parts.push(''); - const DOMPurify = (await import('dompurify')).default; - return { - html: DOMPurify.sanitize(parts.join('')), - rowCount, - colCount - }; + const DOMPurify = (await import('dompurify')).default; + return { + html: DOMPurify.sanitize(parts.join('')), + rowCount, + colCount + }; } diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 455594b65c..5a0f899ffc 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -275,7 +275,6 @@ export const canvasPixelTest = () => { return true; }; - let resizeImageWarmupDone = false; /** * Draws an image to a canvas at the given dimensions and returns a data URL. @@ -285,7 +284,7 @@ async function resizeImageToDataURL( img: HTMLImageElement, width: number, height: number, - mimeType = 'image/jpeg', + mimeType = 'image/jpeg' ): Promise { const canvas = document.createElement('canvas'); canvas.width = width; @@ -294,22 +293,23 @@ async function resizeImageToDataURL( const toDataURL = () => canvas.toDataURL(mimeType); - if (!resizeImageWarmupDone && canvas.toBlob && /android|iphone|ipad|ipod/i.test(navigator?.userAgent)) { + if ( + !resizeImageWarmupDone && + canvas.toBlob && + /android|iphone|ipad|ipod/i.test(navigator?.userAgent) + ) { resizeImageWarmupDone = true; return new Promise((resolve) => { - canvas.toBlob( - (blob) => { - if (!blob) { - resolve(toDataURL()); - return; - } - const reader = new FileReader(); - reader.onload = () => resolve(String(reader.result)); - reader.onerror = () => resolve(toDataURL()); - reader.readAsDataURL(blob); - }, - mimeType, - ); + canvas.toBlob((blob) => { + if (!blob) { + resolve(toDataURL()); + return; + } + const reader = new FileReader(); + reader.onload = () => resolve(String(reader.result)); + reader.onerror = () => resolve(toDataURL()); + reader.readAsDataURL(blob); + }, mimeType); }); } return Promise.resolve(toDataURL()); @@ -393,9 +393,9 @@ export const generateInitialsImage = (name) => { const initials = sanitizedName.length > 0 ? sanitizedName[0] + - (sanitizedName.split(' ').length > 1 - ? sanitizedName[sanitizedName.lastIndexOf(' ') + 1] - : '') + (sanitizedName.split(' ').length > 1 + ? sanitizedName[sanitizedName.lastIndexOf(' ') + 1] + : '') : ''; ctx.fillText(initials.toUpperCase(), canvas.width / 2, canvas.height / 2); @@ -551,10 +551,10 @@ export const compareVersion = (latest, current) => { return current === '0.0.0' ? false : current.localeCompare(latest, undefined, { - numeric: true, - sensitivity: 'case', - caseFirst: 'upper' - }) < 0; + numeric: true, + sensitivity: 'case', + caseFirst: 'upper' + }) < 0; }; export const extractCurlyBraceWords = (text) => { diff --git a/src/lib/utils/pptxToHtml.ts b/src/lib/utils/pptxToHtml.ts index 193469ddc5..045ac70001 100644 --- a/src/lib/utils/pptxToHtml.ts +++ b/src/lib/utils/pptxToHtml.ts @@ -11,249 +11,247 @@ const EMU_PER_PX = 9525; const emuToPx = (emu: number) => Math.round(emu / EMU_PER_PX); -const parseEmu = (val: string | null | undefined): number => - val ? parseInt(val, 10) || 0 : 0; +const parseEmu = (val: string | null | undefined): number => (val ? parseInt(val, 10) || 0 : 0); /** Load a data URI into an Image element and wait for it. */ const loadImage = (src: string): Promise => - new Promise((resolve, reject) => { - const img = new Image(); - img.onload = () => resolve(img); - img.onerror = () => reject(new Error('Failed to load image')); - img.src = src; - }); + new Promise((resolve, reject) => { + const img = new Image(); + img.onload = () => resolve(img); + img.onerror = () => reject(new Error('Failed to load image')); + img.src = src; + }); /** * Convert PPTX ArrayBuffer → array of PNG data URL strings, one per slide. */ export async function pptxToImages( - buffer: ArrayBuffer + buffer: ArrayBuffer ): Promise<{ images: string[]; width: number; height: number }> { - const JSZip = (await import('jszip')).default; - const zip = await JSZip.loadAsync(buffer); - - // ── Read slide dimensions from presentation.xml ────────────────── - let slideW = 960; - let slideH = 540; - const presXml = zip.file('ppt/presentation.xml'); - if (presXml) { - const presText = await presXml.async('text'); - const presDoc = new DOMParser().parseFromString(presText, 'application/xml'); - const sldSz = presDoc.getElementsByTagName('p:sldSz')[0]; - if (sldSz) { - slideW = emuToPx(parseEmu(sldSz.getAttribute('cx'))); - slideH = emuToPx(parseEmu(sldSz.getAttribute('cy'))); - } - } - - // ── Collect media files (images) as base64 data URIs ───────────── - const media: Record = {}; - const mediaFiles = Object.keys(zip.files).filter((f) => f.startsWith('ppt/media/')); - await Promise.all( - mediaFiles.map(async (path) => { - const file = zip.file(path); - if (!file) return; - const base64 = await file.async('base64'); - const ext = path.split('.').pop()?.toLowerCase() ?? ''; - const mime = - ext === 'png' - ? 'image/png' - : ext === 'gif' - ? 'image/gif' - : ext === 'svg' - ? 'image/svg+xml' - : ext === 'emf' || ext === 'wmf' - ? 'image/x-emf' - : 'image/jpeg'; - media[path] = `data:${mime};base64,${base64}`; - }) - ); - - // ── Discover slide files ───────────────────────────────────────── - const slideFiles = Object.keys(zip.files) - .filter((f) => /^ppt\/slides\/slide\d+\.xml$/.test(f)) - .sort((a, b) => { - const na = parseInt(a.match(/slide(\d+)/)?.[1] ?? '0'); - const nb = parseInt(b.match(/slide(\d+)/)?.[1] ?? '0'); - return na - nb; - }); - - const images: string[] = []; - - for (const slidePath of slideFiles) { - const slideText = await zip.file(slidePath)!.async('text'); - const slideDoc = new DOMParser().parseFromString(slideText, 'application/xml'); - - // Load relationship file for this slide to resolve image references - const slideNum = slidePath.match(/slide(\d+)/)?.[1]; - const relsPath = `ppt/slides/_rels/slide${slideNum}.xml.rels`; - const rels: Record = {}; - const relsFile = zip.file(relsPath); - if (relsFile) { - const relsText = await relsFile.async('text'); - const relsDoc = new DOMParser().parseFromString(relsText, 'application/xml'); - const relEls = relsDoc.getElementsByTagName('Relationship'); - for (let i = 0; i < relEls.length; i++) { - const rel = relEls[i]; - const id = rel.getAttribute('Id') ?? ''; - const target = rel.getAttribute('Target') ?? ''; - if (target.startsWith('../')) { - rels[id] = 'ppt/' + target.replace('../', ''); - } else { - rels[id] = target; - } - } - } - - // ── Create canvas and render slide ─────────────────────────── - const canvas = document.createElement('canvas'); - canvas.width = slideW; - canvas.height = slideH; - const ctx = canvas.getContext('2d')!; - - // White background - ctx.fillStyle = '#ffffff'; - ctx.fillRect(0, 0, slideW, slideH); - - const spTree = slideDoc.getElementsByTagName('p:spTree')[0]; - if (!spTree) { - images.push(canvas.toDataURL('image/png')); - continue; - } - - const shapes = [ - ...Array.from(spTree.getElementsByTagName('p:sp')), - ...Array.from(spTree.getElementsByTagName('p:pic')) - ]; - - for (const shape of shapes) { - const xfrm = - shape.getElementsByTagName('a:xfrm')[0] ?? - shape.getElementsByTagName('p:xfrm')[0]; - if (!xfrm) continue; - - const off = xfrm.getElementsByTagName('a:off')[0]; - const ext = xfrm.getElementsByTagName('a:ext')[0]; - if (!off || !ext) continue; - - const x = emuToPx(parseEmu(off.getAttribute('x'))); - const y = emuToPx(parseEmu(off.getAttribute('y'))); - const w = emuToPx(parseEmu(ext.getAttribute('cx'))); - const h = emuToPx(parseEmu(ext.getAttribute('cy'))); - - if (w === 0 && h === 0) continue; - - // ── Picture ────────────────────────────────────────────── - const blipFill = shape.getElementsByTagName('p:blipFill')[0]; - if (blipFill) { - const blip = blipFill.getElementsByTagName('a:blip')[0]; - if (blip) { - const rEmbed = blip.getAttribute('r:embed') ?? ''; - const mediaPath = rels[rEmbed]; - const dataUri = mediaPath ? media[mediaPath] : ''; - if (dataUri && !dataUri.includes('image/x-emf')) { - try { - const img = await loadImage(dataUri); - ctx.drawImage(img, x, y, w, h); - } catch { - // Skip images that fail to load - } - } - } - continue; - } - - // ── Text shape ─────────────────────────────────────────── - const txBody = shape.getElementsByTagName('p:txBody')[0]; - if (!txBody) continue; - - ctx.save(); - ctx.rect(x, y, w, h); - ctx.clip(); - - const paragraphs = txBody.getElementsByTagName('a:p'); - let cursorY = y; - const defaultFontSize = 12; - - for (let pi = 0; pi < paragraphs.length; pi++) { - const para = paragraphs[pi]; - const runs = para.getElementsByTagName('a:r'); - - if (runs.length === 0) { - cursorY += defaultFontSize * 1.5; - continue; - } - - // Calculate max font size in this paragraph for line height - let maxFontPt = defaultFontSize; - for (let ri = 0; ri < runs.length; ri++) { - const rPr = runs[ri].getElementsByTagName('a:rPr')[0]; - if (rPr) { - const sz = rPr.getAttribute('sz'); - if (sz) { - const pt = parseInt(sz, 10) / 100; - if (pt > maxFontPt) maxFontPt = pt; - } - } - } - - const lineHeight = maxFontPt * 1.4; - cursorY += maxFontPt; // baseline offset - - let cursorX = x + 4; // small left padding - - for (let ri = 0; ri < runs.length; ri++) { - const run = runs[ri]; - const rPr = run.getElementsByTagName('a:rPr')[0]; - const text = run.getElementsByTagName('a:t')[0]?.textContent ?? ''; - if (!text) continue; - - let fontPt = defaultFontSize; - let bold = false; - let italic = false; - let color = '#000000'; - - if (rPr) { - if (rPr.getAttribute('b') === '1') bold = true; - if (rPr.getAttribute('i') === '1') italic = true; - const sz = rPr.getAttribute('sz'); - if (sz) fontPt = parseInt(sz, 10) / 100; - const solidFill = rPr.getElementsByTagName('a:solidFill')[0]; - if (solidFill) { - const srgb = solidFill.getElementsByTagName('a:srgbClr')[0]; - if (srgb) { - const val = srgb.getAttribute('val'); - if (val) color = `#${val}`; - } - } - } - - ctx.font = `${italic ? 'italic ' : ''}${bold ? 'bold ' : ''}${fontPt}pt Calibri, Arial, sans-serif`; - ctx.fillStyle = color; - ctx.textBaseline = 'alphabetic'; - - // Simple word-wrap within the shape bounds - const words = text.split(/(\s+)/); - for (const word of words) { - const metrics = ctx.measureText(word); - if (cursorX + metrics.width > x + w && cursorX > x + 4) { - cursorX = x + 4; - cursorY += lineHeight; - } - if (cursorY > y + h) break; - ctx.fillText(word, cursorX, cursorY); - cursorX += metrics.width; - } - } - - cursorY += lineHeight * 0.4; // paragraph spacing - } - - ctx.restore(); - } - - images.push(canvas.toDataURL('image/png')); - } - - return { images, width: slideW, height: slideH }; + const JSZip = (await import('jszip')).default; + const zip = await JSZip.loadAsync(buffer); + + // ── Read slide dimensions from presentation.xml ────────────────── + let slideW = 960; + let slideH = 540; + const presXml = zip.file('ppt/presentation.xml'); + if (presXml) { + const presText = await presXml.async('text'); + const presDoc = new DOMParser().parseFromString(presText, 'application/xml'); + const sldSz = presDoc.getElementsByTagName('p:sldSz')[0]; + if (sldSz) { + slideW = emuToPx(parseEmu(sldSz.getAttribute('cx'))); + slideH = emuToPx(parseEmu(sldSz.getAttribute('cy'))); + } + } + + // ── Collect media files (images) as base64 data URIs ───────────── + const media: Record = {}; + const mediaFiles = Object.keys(zip.files).filter((f) => f.startsWith('ppt/media/')); + await Promise.all( + mediaFiles.map(async (path) => { + const file = zip.file(path); + if (!file) return; + const base64 = await file.async('base64'); + const ext = path.split('.').pop()?.toLowerCase() ?? ''; + const mime = + ext === 'png' + ? 'image/png' + : ext === 'gif' + ? 'image/gif' + : ext === 'svg' + ? 'image/svg+xml' + : ext === 'emf' || ext === 'wmf' + ? 'image/x-emf' + : 'image/jpeg'; + media[path] = `data:${mime};base64,${base64}`; + }) + ); + + // ── Discover slide files ───────────────────────────────────────── + const slideFiles = Object.keys(zip.files) + .filter((f) => /^ppt\/slides\/slide\d+\.xml$/.test(f)) + .sort((a, b) => { + const na = parseInt(a.match(/slide(\d+)/)?.[1] ?? '0'); + const nb = parseInt(b.match(/slide(\d+)/)?.[1] ?? '0'); + return na - nb; + }); + + const images: string[] = []; + + for (const slidePath of slideFiles) { + const slideText = await zip.file(slidePath)!.async('text'); + const slideDoc = new DOMParser().parseFromString(slideText, 'application/xml'); + + // Load relationship file for this slide to resolve image references + const slideNum = slidePath.match(/slide(\d+)/)?.[1]; + const relsPath = `ppt/slides/_rels/slide${slideNum}.xml.rels`; + const rels: Record = {}; + const relsFile = zip.file(relsPath); + if (relsFile) { + const relsText = await relsFile.async('text'); + const relsDoc = new DOMParser().parseFromString(relsText, 'application/xml'); + const relEls = relsDoc.getElementsByTagName('Relationship'); + for (let i = 0; i < relEls.length; i++) { + const rel = relEls[i]; + const id = rel.getAttribute('Id') ?? ''; + const target = rel.getAttribute('Target') ?? ''; + if (target.startsWith('../')) { + rels[id] = 'ppt/' + target.replace('../', ''); + } else { + rels[id] = target; + } + } + } + + // ── Create canvas and render slide ─────────────────────────── + const canvas = document.createElement('canvas'); + canvas.width = slideW; + canvas.height = slideH; + const ctx = canvas.getContext('2d')!; + + // White background + ctx.fillStyle = '#ffffff'; + ctx.fillRect(0, 0, slideW, slideH); + + const spTree = slideDoc.getElementsByTagName('p:spTree')[0]; + if (!spTree) { + images.push(canvas.toDataURL('image/png')); + continue; + } + + const shapes = [ + ...Array.from(spTree.getElementsByTagName('p:sp')), + ...Array.from(spTree.getElementsByTagName('p:pic')) + ]; + + for (const shape of shapes) { + const xfrm = + shape.getElementsByTagName('a:xfrm')[0] ?? shape.getElementsByTagName('p:xfrm')[0]; + if (!xfrm) continue; + + const off = xfrm.getElementsByTagName('a:off')[0]; + const ext = xfrm.getElementsByTagName('a:ext')[0]; + if (!off || !ext) continue; + + const x = emuToPx(parseEmu(off.getAttribute('x'))); + const y = emuToPx(parseEmu(off.getAttribute('y'))); + const w = emuToPx(parseEmu(ext.getAttribute('cx'))); + const h = emuToPx(parseEmu(ext.getAttribute('cy'))); + + if (w === 0 && h === 0) continue; + + // ── Picture ────────────────────────────────────────────── + const blipFill = shape.getElementsByTagName('p:blipFill')[0]; + if (blipFill) { + const blip = blipFill.getElementsByTagName('a:blip')[0]; + if (blip) { + const rEmbed = blip.getAttribute('r:embed') ?? ''; + const mediaPath = rels[rEmbed]; + const dataUri = mediaPath ? media[mediaPath] : ''; + if (dataUri && !dataUri.includes('image/x-emf')) { + try { + const img = await loadImage(dataUri); + ctx.drawImage(img, x, y, w, h); + } catch { + // Skip images that fail to load + } + } + } + continue; + } + + // ── Text shape ─────────────────────────────────────────── + const txBody = shape.getElementsByTagName('p:txBody')[0]; + if (!txBody) continue; + + ctx.save(); + ctx.rect(x, y, w, h); + ctx.clip(); + + const paragraphs = txBody.getElementsByTagName('a:p'); + let cursorY = y; + const defaultFontSize = 12; + + for (let pi = 0; pi < paragraphs.length; pi++) { + const para = paragraphs[pi]; + const runs = para.getElementsByTagName('a:r'); + + if (runs.length === 0) { + cursorY += defaultFontSize * 1.5; + continue; + } + + // Calculate max font size in this paragraph for line height + let maxFontPt = defaultFontSize; + for (let ri = 0; ri < runs.length; ri++) { + const rPr = runs[ri].getElementsByTagName('a:rPr')[0]; + if (rPr) { + const sz = rPr.getAttribute('sz'); + if (sz) { + const pt = parseInt(sz, 10) / 100; + if (pt > maxFontPt) maxFontPt = pt; + } + } + } + + const lineHeight = maxFontPt * 1.4; + cursorY += maxFontPt; // baseline offset + + let cursorX = x + 4; // small left padding + + for (let ri = 0; ri < runs.length; ri++) { + const run = runs[ri]; + const rPr = run.getElementsByTagName('a:rPr')[0]; + const text = run.getElementsByTagName('a:t')[0]?.textContent ?? ''; + if (!text) continue; + + let fontPt = defaultFontSize; + let bold = false; + let italic = false; + let color = '#000000'; + + if (rPr) { + if (rPr.getAttribute('b') === '1') bold = true; + if (rPr.getAttribute('i') === '1') italic = true; + const sz = rPr.getAttribute('sz'); + if (sz) fontPt = parseInt(sz, 10) / 100; + const solidFill = rPr.getElementsByTagName('a:solidFill')[0]; + if (solidFill) { + const srgb = solidFill.getElementsByTagName('a:srgbClr')[0]; + if (srgb) { + const val = srgb.getAttribute('val'); + if (val) color = `#${val}`; + } + } + } + + ctx.font = `${italic ? 'italic ' : ''}${bold ? 'bold ' : ''}${fontPt}pt Calibri, Arial, sans-serif`; + ctx.fillStyle = color; + ctx.textBaseline = 'alphabetic'; + + // Simple word-wrap within the shape bounds + const words = text.split(/(\s+)/); + for (const word of words) { + const metrics = ctx.measureText(word); + if (cursorX + metrics.width > x + w && cursorX > x + 4) { + cursorX = x + 4; + cursorY += lineHeight; + } + if (cursorY > y + h) break; + ctx.fillText(word, cursorX, cursorY); + cursorX += metrics.width; + } + } + + cursorY += lineHeight * 0.4; // paragraph spacing + } + + ctx.restore(); + } + + images.push(canvas.toDataURL('image/png')); + } + + return { images, width: slideW, height: slideH }; } From b9c0a9c3bf93fa6a4c1fd871304d90eab72eb432 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sat, 7 Mar 2026 23:16:43 +0100 Subject: [PATCH 062/114] enh: prevent models from always using internal knowledge base search first (#22264) Some models always primarily use the internal knowledge base first before deviating to the web search tool --- backend/open_webui/tools/builtin.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/backend/open_webui/tools/builtin.py b/backend/open_webui/tools/builtin.py index eec760fe01..7427592380 100644 --- a/backend/open_webui/tools/builtin.py +++ b/backend/open_webui/tools/builtin.py @@ -155,8 +155,7 @@ async def search_web( ) -> str: """ Search the public web for information. Best for current events, external references, - or topics not covered in internal documents. If knowledge base tools are available, - consider checking those first for internal information. + or topics not covered in internal documents. :param query: The search query to look up :param count: Number of results to return (default: 5) From fbf315e624ce64053928c69e2dd61fb2fca9a036 Mon Sep 17 00:00:00 2001 From: alifurkanstahl <180474740+alifurkanstahl@users.noreply.github.com> Date: Sat, 7 Mar 2026 23:31:23 +0100 Subject: [PATCH 063/114] i18n: expand Turkish translations across missing frontend UI strings (#22360) * feat(i18n): add Turkish translations for access and add-action strings * feat(i18n): add Turkish translations for access, permission, and upload strings * feat(i18n): add Turkish translations for API, archive, and attach strings * feat(i18n): add Turkish translations for chat and channel UI strings * feat(i18n): add Turkish translations for common UI actions and dialogs * feat(i18n): add Turkish translations for copy, create, and delete UI strings * feat(i18n): add Turkish translations for display, download, and edit UI strings * feat(i18n): add Turkish translations for form inputs, errors, and file UI string * feat(i18n): add Turkish translations for skill-related UI strings * i18n: add Turkish translations for settings-related UI strings * i18n: add Turkish translations for terminal-related UI strings * i18n: add Turkish translations for misc frontend UI strings * i18n: add Turkish translations for search-related UI strings --------- Co-authored-by: MSI I9 12900KS RTX --- src/lib/i18n/locales/tr-TR/translation.json | 718 ++++++++++---------- 1 file changed, 359 insertions(+), 359 deletions(-) diff --git a/src/lib/i18n/locales/tr-TR/translation.json b/src/lib/i18n/locales/tr-TR/translation.json index 9dddccb9cd..42c2b98fed 100644 --- a/src/lib/i18n/locales/tr-TR/translation.json +++ b/src/lib/i18n/locales/tr-TR/translation.json @@ -4,141 +4,141 @@ "(e.g. `sh webui.sh --api --api-auth username_password`)": "(örn. `sh webui.sh --api --api-auth username_password`)", "(e.g. `sh webui.sh --api`)": "(örn. `sh webui.sh --api`)", "(latest)": "(en son)", - "(leave blank for to use commercial endpoint)": "", + "(leave blank for to use commercial endpoint)": "Ticari uç noktayı kullanmak için boş bırakın", "[Last] dddd [at] h:mm A": "", "[Today at] h:mm A": "", "[Yesterday at] h:mm A": "", "{{ models }}": "{{ models }}", - "{{COUNT}} Available Tools": "", - "{{COUNT}} characters": "", - "{{COUNT}} extracted lines": "", - "{{COUNT}} files": "", - "{{COUNT}} hidden lines": "", - "{{COUNT}} members": "", + "{{COUNT}} Available Tools": "{{COUNT}} Kullanılabilir Araç", + "{{COUNT}} characters": "{{COUNT}} karakter", + "{{COUNT}} extracted lines": "{{COUNT}} çıkarılan satır", + "{{COUNT}} files": "{{COUNT}} dosya", + "{{COUNT}} hidden lines": "{{COUNT}} gizli satır", + "{{COUNT}} members": "{{COUNT}} üye", "{{COUNT}} Replies": "{{COUNT}} Yanıt", - "{{COUNT}} Rows": "", - "{{COUNT}} Sources": "", - "{{COUNT}} words": "", + "{{COUNT}} Rows": "{{COUNT}} satır", + "{{COUNT}} Sources": "{{COUNT}} kaynak", + "{{COUNT}} words": "{{COUNT}} kelime", "{{COUNT}}d_time_ago": "", "{{COUNT}}h_time_ago": "", "{{COUNT}}m_time_ago": "", "{{COUNT}}w_time_ago": "", "{{COUNT}}y_time_ago": "", "{{LOCALIZED_DATE}} at {{LOCALIZED_TIME}}": "", - "{{model}} download has been canceled": "", - "{{modelName}} profile image": "", - "{{NAMES}} reacted with {{REACTION}}": "", + "{{model}} download has been canceled": "{{model}} indirme işlemi iptal edildi", + "{{modelName}} profile image": "{{modelName}} profil resmi", + "{{NAMES}} reacted with {{REACTION}}": "{{NAMES}}, {{REACTION}} ile tepki verdi", "{{user}}'s Chats": "{{user}}'ın Sohbetleri", "{{webUIName}} Backend Required": "{{webUIName}} Arka-uç Gerekli", "*Prompt node ID(s) are required for image generation": "*Görüntü oluşturma için düğüm kimlikleri gereklidir", - "1 Source": "", - "1m_time_ago": "", - "A collaboration channel where people join as members": "", - "A discussion channel where access is controlled by groups and permissions": "", + "1 Source": "1 Kaynak", + "1m_time_ago": "1 dk önce", + "A collaboration channel where people join as members": "İnsanların üye olarak katıldığı bir iş birliği kanalı", + "A discussion channel where access is controlled by groups and permissions": "Erişimin gruplar ve izinlerle kontrol edildiği bir tartışma kanalı", "A new version (v{{LATEST_VERSION}}) is now available.": "Yeni bir sürüm (v{{LATEST_VERSION}}) artık mevcut.", - "A private conversation between you and selected users": "", + "A private conversation between you and selected users": "Sizinle seçili kullanıcılar arasında özel bir konuşma", "A task model is used when performing tasks such as generating titles for chats and web search queries": "Bir görev modeli, sohbetler ve web arama sorguları için başlık oluşturma gibi görevleri yerine getirirken kullanılır", "a user": "bir kullanıcı", "About": "Hakkında", - "Accept Autocomplete Generation\nJump to Prompt Variable": "", + "Accept Autocomplete Generation\nJump to Prompt Variable": "Otomatik Tamamlama Oluşturmayı Kabul Et\nPrompt Değişkenine Git", "Access": "Erişim", "Access Control": "Erişim Kontrolü", - "Access Grants": "", - "Access List": "", + "Access Grants": "Erişim İzinleri", + "Access List": "Erişim Listesi", "Accessible to all users": "Tüm kullanıcılara erişilebilir", "Account": "Hesap", "Account Activation Pending": "Hesap Aktivasyonu Bekleniyor", "Accurate information": "Doğru bilgi", - "Action": "", - "Action not found": "", + "Action": "Aksiyon", + "Action not found": "Aksiyon bulunamadı", "Action Required for Chat Log Storage": "Sohbet günlüğünü kaydetmek için işlem gerekli", "Actions": "Aksiyonlar", "Activate": "Aktif Et", "Activate this command by typing \"/{{COMMAND}}\" to chat input.": "Sohbet girişine \"/{{COMMAND}}\" yazarak bu komutu etkinleştirin.", "Active": "Etkin", "Active Users": "Aktif Kullanıcılar", - "Activity": "", + "Activity": "Etkinlik", "Add": "Ekle", "Add a model ID": "Bir model kimliği ekleyin", "Add a short description about what this model does": "Bu modelin ne yaptığı hakkında kısa bir açıklama ekleyin", "Add a tag": "Bir etiket ekleyin", - "Add a tag...": "", - "Add Access": "", + "Add a tag...": "Bir etiket ekleyin...", + "Add Access": "Erişim Ekle", "Add Arena Model": "Arena Modeli Ekle", "Add Connection": "Bağlantı Ekle", "Add Content": "İçerik Ekle", "Add content here": "Buraya içerik ekleyin", "Add Custom Parameter": "Özel Parametre Ekle", - "Add Custom Prompt": "", - "Add Details": "", + "Add Custom Prompt": "Özel Prompt Ekle", + "Add Details": "Ayrıntı Ekle", "Add Files": "Dosyalar Ekle", - "Add Image": "", - "Add Member": "", - "Add Members": "", + "Add Image": "Görsel Ekle", + "Add Member": "Üye Ekle", + "Add Members": "Üyeleri Ekle", "Add Memory": "Bellek Ekle", "Add Model": "Model Ekle", "Add Reaction": "Tepki Ekle", - "Add tag": "", + "Add tag": "Etiket ekle", "Add Tag": "Etiket Ekle", - "Add Terminal": "", - "Add Terminal Connection": "", + "Add Terminal": "Terminal Ekle", + "Add Terminal Connection": "Terminal Bağlantısı Ekle", "Add text content": "Metin içeriği ekleme", - "Add to favorites": "", + "Add to favorites": "Favorilere ekle", "Add User": "Kullanıcı Ekle", "Add User Group": "Kullanıcı Grubu Ekle", - "Add webpage": "", - "Add your Open Terminal URL and API key in Settings → Integrations.": "", + "Add webpage": "Web sayfası ekle", + "Add your Open Terminal URL and API key in Settings → Integrations.": "Open Terminal URL'nizi ve API anahtarınızı Ayarlar → Entegrasyonlar bölümünde girin.", "Additional Config": "Ek Yapılandırma", "Additional configuration options for marker. This should be a JSON string with key-value pairs. For example, '{\"key\": \"value\"}'. Supported keys include: disable_links, keep_pageheader_in_output, keep_pagefooter_in_output, filter_blank_pages, drop_repeated_text, layout_coverage_threshold, merge_threshold, height_tolerance, gap_threshold, image_threshold, min_line_length, level_count, default_level": "", - "Additional feedback comments": "", + "Additional feedback comments": "Ek geri bildirim yorumları", "Additional Parameters": "Ek Parametreler", "Adds filenames, titles, sections, and snippets into the BM25 text to improve lexical recall.": "", "Adjusting these settings will apply changes universally to all users.": "Bu ayarların yapılması, değişiklikleri tüm kullanıcılara evrensel olarak uygulayacaktır.", "admin": "yönetici", "Admin": "Yönetici", - "Admin Contact Email": "", + "Admin Contact Email": "Yönetici İletişim E-postası", "Admin Panel": "Yönetici Paneli", "Admin Settings": "Yönetici Ayarları", "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Yöneticiler her zaman tüm araçlara erişebilir; kullanıcıların çalışma alanındaki model başına atanmış araçlara ihtiyacı vardır.", - "Advanced": "", + "Advanced": "Gelişmiş", "Advanced Parameters": "Gelişmiş Parametreler", "Advanced parameters for MinerU parsing (enable_ocr, enable_formula, enable_table, language, model_version, page_ranges)": "", "Advanced Params": "Gelişmiş Parametreler", "After updating or changing the embedding model, you must reindex the knowledge base for the changes to take effect. You can do this using the \"Reindex\" button below.": "", "AI": "Yapay Zeka", "All": "Tüm", - "All chats have been unarchived.": "", - "All models are now hidden": "", - "All models are now visible": "", + "All chats have been unarchived.": "Tüm sohbetler arşivden çıkarıldı.", + "All models are now hidden": "Tüm modeller artık gizli", + "All models are now visible": "Tüm modeller artık görünür", "All models deleted successfully": "Tüm modeller başarıyla silindi", - "All time": "", - "All Users": "", - "Allow Call": "", + "All time": "Tüm zamanlar", + "All Users": "Tüm Kullanıcılar", + "Allow Call": "Aramaya İzin Ver", "Allow Chat Controls": "Sohbet Kontrollerine İzin Ver", "Allow Chat Delete": "Sohbet Silmeye İzin Ver", - "Allow Chat Edit": "Sohbet Silmeye İzin Ver", + "Allow Chat Edit": "Sohbet Düzenlemeye İzin Ver", "Allow Chat Export": "Sohbetin Dışa Aktarımına İzin Ver", - "Allow Chat Params": "", + "Allow Chat Params": "Sohbet Parametrelerine İzin Ver", "Allow Chat Share": "Sohbetin Paylaşılmasına İzin Ver", - "Allow Chat System Prompt": "", + "Allow Chat System Prompt": "Sohbet Sistem Promptuna İzin Ver", "Allow Chat Valves": "", - "Allow Continue Response": "", + "Allow Continue Response": "Yanıta Devam Etmeye İzin Ver", "Allow Delete Messages": "Mesaj Silmeye İzin Ver", "Allow File Upload": "Dosya Yüklemeye İzin Ver", "Allow Multiple Models in Chat": "Sohbette Birden Fazla Modele İzin Ver", - "Allow non-local voices": "Yerel olmayan seslere izin verin", - "Allow Rate Response": "", + "Allow non-local voices": "Yerel olmayan seslere izin ver", + "Allow Rate Response": "Yanıtı Değerlendirmeye İzin Ver", "Allow Regenerate Response": "Yanıtı Yeniden Oluşturmaya İzin Ver", - "Allow Sharing With Users": "", - "Allow Speech to Text": "", + "Allow Sharing With Users": "Kullanıcılarla Paylaşmaya İzin Ver", + "Allow Speech to Text": "Sesten Metne İzin Ver", "Allow Temporary Chat": "Geçici Sohbetlere İzin Ver", - "Allow Text to Speech": "", + "Allow Text to Speech": "Metinden Sese İzin Ver", "Allow User Location": "Kullanıcı Konumuna İzin Ver", "Allow Voice Interruption in Call": "Aramada Ses Kesintisine İzin Ver", - "Allow Web Upload": "", + "Allow Web Upload": "Web İçeriği Yüklemeye İzin Ver", "Allowed Endpoints": "İzin Verilen Uç Noktalar", - "Allowed File Extensions": "", - "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "", + "Allowed File Extensions": "İzin Verilen Dosya Uzantıları", + "Allowed file extensions for upload. Separate multiple extensions with commas. Leave empty for all file types.": "Yükleme için izin verilen dosya uzantıları. Birden fazla uzantıyı virgülle ayırın. Tüm dosya türleri için boş bırakın.", "Already have an account?": "Zaten bir hesabınız mı var?", "Alternative to the top_p, and aims to ensure a balance of quality and variety. The parameter p represents the minimum probability for a token to be considered, relative to the probability of the most likely token. For example, with p=0.05 and the most likely token having a probability of 0.9, logits with a value less than 0.045 are filtered out.": "", "Always": "Daima", @@ -147,56 +147,56 @@ "Always Play Notification Sound": "Her Zaman Bildirim Sesini Oynat", "Amazing": "Harika", "an assistant": "bir asistan", - "An error occurred while fetching the explanation": "", + "An error occurred while fetching the explanation": "Açıklama alınırken bir hata oluştu", "Analytics": "Analiz", "Analyzed": "Analiz edildi", "Analyzing...": "Analiz ediliyor...", "and {{COUNT}} more": "ve {{COUNT}} daha", "and create a new shared link.": "ve yeni bir paylaşılan bağlantı oluşturun.", "Android": "Android", - "Anyone": "", + "Anyone": "Herkes", "API Base URL": "API Temel URL", - "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "", + "API Base URL for Datalab Marker service. Defaults to: https://www.datalab.to/api/v1/marker": "Datalab Marker hizmeti için API temel URL'si. Varsayılan: https://www.datalab.to/api/v1/marker", "API Key": "API Anahtarı", "API Key created.": "API Anahtarı oluşturuldu.", "API Key Endpoint Restrictions": "API Anahtarı Uç Nokta Kısıtlamaları", "API keys": "API anahtarları", - "API Keys": "", - "API Mode": "", - "API Timeout": "", - "API Type": "", + "API Keys": "API Anahtarları", + "API Mode": "API Modu", + "API Timeout": "API Zaman Aşımı", + "API Type": "API Türü", "API Version": "API Sürümü", - "API Version is required": "", + "API Version is required": "API Sürümü gereklidir", "Application DN": "Uygulama DN", "Application DN Password": "Uygulama DN Parola", "applies to all users with the \"user\" role": "\"kullanıcı\" rolüne sahip tüm kullanıcılar için geçerlidir", "April": "Nisan", "Archive": "Arşiv", - "Archive All": "", + "Archive All": "Tümünü Arşivle", "Archive All Chats": "Tüm Sohbetleri Arşivle", "Archived Chats": "Arşivlenmiş Sohbetler", "archived-chat-export": "arşivlenmiş-sohbet-aktarımı", - "Are you sure you want to archive all chats? This action cannot be undone.": "", - "Are you sure you want to clear all memories? This action cannot be undone.": "", - "Are you sure you want to delete \"{{NAME}}\"?": "", - "Are you sure you want to delete all chats? This action cannot be undone.": "", + "Are you sure you want to archive all chats? This action cannot be undone.": "Tüm sohbetleri arşivlemek istediğinizden emin misiniz? Bu işlem geri alınamaz.", + "Are you sure you want to clear all memories? This action cannot be undone.": "Tüm bellekleri temizlemek istediğinizden emin misiniz? Bu işlem geri alınamaz.", + "Are you sure you want to delete \"{{NAME}}\"?": "\"{{NAME}}\" öğesini silmek istediğinizden emin misiniz?", + "Are you sure you want to delete all chats? This action cannot be undone.": "Tüm sohbetleri silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.", "Are you sure you want to delete this channel?": "Bu kanalı silmek istediğinizden emin misiniz?", "Are you sure you want to delete this message?": "Bu mesajı silmek istediğinizden emin misiniz?", - "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Bu sürümü silmek istediğinizden emin misiniz? Alt sürümler bu sürümün üst sürümüne yeniden bağlanacaktır.", "Are you sure you want to unarchive all archived chats?": "Arşivlenmiş tüm sohbetlerin arşivini kaldırmak istediğinizden emin misiniz?", "Arena Models": "Arena Modelleri", "Artifacts": "Eserler", - "Asc": "", + "Asc": "Artan", "Ask": "Sor", "Ask a question": "Bir soru sorun", "Assistant": "Asistan", "Async Embedding Processing": "", - "Attach File From Knowledge": "", - "Attach Knowledge": "", - "Attach Notes": "", - "Attach Webpage": "", + "Attach File From Knowledge": "Bilgi Tabanından Dosya Ekle", + "Attach Knowledge": "Bilgi Tabanı Ekle", + "Attach Notes": "Not Ekle", + "Attach Webpage": "Web sayfası ekle", "Attention to detail": "Ayrıntılara dikkat", - "Attribute for Mail": "", + "Attribute for Mail": "E-posta için Özellik", "Attribute for Username": "Kullanıcı Adı için Özellik", "Audio": "Ses", "August": "Ağustos", @@ -204,7 +204,7 @@ "Authenticate": "Kimlik Doğrulama", "Authentication": "Kimlik Doğrulama", "Auto": "Otomatik", - "Auto (Random)": "", + "Auto (Random)": "Otomatik (Rastgele)", "Auto-Copy Response to Clipboard": "Yanıtı Panoya Otomatik Kopyala", "Auto-playback response": "Yanıtı otomatik oynatma", "Autocomplete Generation": "Otomatik Tamamlama Üretimi", @@ -215,7 +215,7 @@ "AUTOMATIC1111 Base URL is required.": "AUTOMATIC1111 Temel URL gereklidir.", "Automatically inject system tools in native function calling mode (e.g., timestamps, memory, chat history, notes, etc.)": "", "Available list": "Mevcut liste", - "Available models": "", + "Available models": "Mevcut modeller", "Available Tools": "Mevcut Araçlar", "available users": "kullanılabilir kullanıcılar", "available!": "mevcut!", @@ -233,24 +233,24 @@ "before": "önce", "Being lazy": "Tembelleşiyor", "Beta": "Beta", - "Bing": "", + "Bing": "Bing", "Bing Search V7 Endpoint": "Bing Arama V7 Uç Noktası", "Bing Search V7 Subscription Key": "Bing Arama V7 Abonelik Anahtarı", - "Bio": "", - "Birth Date": "", + "Bio": "Biyografi", + "Birth Date": "Doğum Tarihi", "BM25 Weight": "", "Bocha Search API Key": "Bocha Arama API Anahtarı", "Bold": "Kalın", "Boosting or penalizing specific tokens for constrained responses. Bias values will be clamped between -100 and 100 (inclusive). (Default: none)": "", - "Brave": "", + "Brave": "Brave", "Brave Search API Key": "Brave Search API Anahtarı", - "Browse and query knowledge bases": "", - "Builtin Tools": "", - "Bullet List": "", - "Button ID": "", - "Button Label": "", - "Button Prompt": "", - "by {{name}}": "", + "Browse and query knowledge bases": "Bilgi tabanlarına göz at ve sorgula", + "Builtin Tools": "Yerleşik Araçlar", + "Bullet List": "Madde İşaretli Liste", + "Button ID": "Düğme Kimliği", + "Button Label": "Düğme Etiketi", + "Button Prompt": "Düğme Promptu", + "by {{name}}": "{{name}} tarafından", "By {{name}}": "{{name}} Tarafından", "Bypass Embedding and Retrieval": "", "Bypass Web Loader": "", @@ -260,22 +260,22 @@ "Call feature is not supported when using Web STT engine": "Web STT motoru kullanılırken arama özelliği desteklenmiyor", "Camera": "Kamera", "Cancel": "İptal", - "Cancel download of {{model}}": "", - "Cannot create an empty note.": "", - "Cannot delete the production version": "", + "Cancel download of {{model}}": "{{model}} indirmesini iptal et", + "Cannot create an empty note.": "Boş bir not oluşturulamaz.", + "Cannot delete the production version": "Üretim sürümü silinemez", "Capabilities": "Yetenekler", "Capture": "Kayıt", "Capture Audio": "Sesi Kaydet", "Certificate Path": "Sertifika Yolu", - "Change folder icon": "", + "Change folder icon": "Klasör simgesini değiştir", "Change Password": "Parola Değiştir", - "Change User Role": "", + "Change User Role": "Kullanıcı Rolünü Değiştir", "Channel": "Kanal", "Channel deleted successfully": "Kanal başarıyla silindi", "Channel Name": "Kanal Adı", - "Channel name cannot be empty.": "", - "Channel name must be less than 128 characters": "", - "Channel Type": "", + "Channel name cannot be empty.": "Kanal adı boş olamaz.", + "Channel name must be less than 128 characters": "Kanal adı 128 karakterden kısa olmalıdır", + "Channel Type": "Kanal Türü", "Channel updated successfully": "Kanal başarıyla güncellendi", "Channels": "Kanallar", "Character": "Karakter", @@ -285,17 +285,17 @@ "Chat archived.": "", "Chat Background Image": "Sohbet Arka Plan Resmi", "Chat Bubble UI": "Sohbet Balonu Arayüzü", - "Chat Completions": "", - "Chat Conversation": "", + "Chat Completions": "Sohbet Tamamlamaları", + "Chat Conversation": "Sohbet Konuşması", "Chat direction": "Sohbet Yönü", - "Chat exported successfully": "", - "Chat History": "", - "Chat ID": "", - "Chat moved successfully": "", + "Chat exported successfully": "Sohbet başarıyla dışa aktarıldı", + "Chat History": "Sohbet Geçmişi", + "Chat ID": "Sohbet Kimliği", + "Chat moved successfully": "Sohbet başarıyla taşındı", "Chat Permissions": "Sohbet İzinleri", "Chat Tags Auto-Generation": "Sohbet Etiketleri Otomatik Oluşturma", - "Chat unshared successfully.": "", - "chats": "", + "Chat unshared successfully.": "Sohbet paylaşımı başarıyla kaldırıldı.", + "chats": "sohbetler", "Chats": "Sohbetler", "Check Again": "Tekrar Kontrol Et", "Check for updates": "Güncellemeleri kontrol et", @@ -310,8 +310,8 @@ "Citations": "Alıntılar", "Clear memory": "Belleği temizle", "Clear Memory": "Belleği Temizle", - "Clear search": "", - "Clear status": "", + "Clear search": "Aramayı temizle", + "Clear status": "Durumu temizle", "click here": "buraya tıklayın", "Click here for filter guides.": "Filtre kılavuzları için buraya tıklayın.", "Click here for help.": "Yardım için buraya tıklayın.", @@ -325,21 +325,21 @@ "Click here to upload a workflow.json file.": "Bir workflow.json dosyası yüklemek için buraya tıklayın.", "click here.": "buraya tıklayın.", "Click on the user role button to change a user's role.": "Bir kullanıcının rolünü değiştirmek için kullanıcı rolü düğmesine tıklayın.", - "Click to copy ID": "", + "Click to copy ID": "Kimliği kopyalamak için tıklayın", "Clipboard write permission denied. Please check your browser settings to grant the necessary access.": "Panoya yazma izni reddedildi. Tarayıcı ayarlarını kontrol ederek gerekli izinleri sağlayabilirsiniz.", "Clone": "Klon", "Clone Chat": "Sohbeti Klonla", "Clone of {{TITLE}}": "{{TITLE}}'ın kopyası", "Close": "Kapat", - "Close Banner": "", - "Close chat controls": "", - "Close citation modal": "", - "Close Configure Connection Modal": "", - "Close feedback": "", - "Close modal": "", - "Close Modal": "", - "Close settings modal": "", - "Close Sidebar": "", + "Close Banner": "Afişi kapat", + "Close chat controls": "Sohbet kontrollerini kapat", + "Close citation modal": "Alıntı penceresini kapat", + "Close Configure Connection Modal": "Bağlantı Yapılandırma penceresini kapat", + "Close feedback": "Geri bildirimi kapat", + "Close modal": "Pencereyi kapat", + "Close Modal": "Pencereyi kapat", + "Close settings modal": "Ayarlar penceresini kapat", + "Close Sidebar": "Kenar çubuğunu kapat", "cloud": "", "CMU ARCTIC speaker embedding name": "", "Code Block": "", @@ -352,10 +352,10 @@ "Code Interpreter": "Kod Yorumlayıcısı", "Code Interpreter Engine": "Kod Yorumlama Motoru", "Code Interpreter Prompt Template": "Kod Yorumlama İstem Şablonu", - "Collaboration channel where people join as members": "", + "Collaboration channel where people join as members": "İnsanların üye olarak katıldığı bir iş birliği kanalı", "Collapse": "Daralt", "Collection": "Koleksiyon", - "Collections": "", + "Collections": "Koleksiyonlar", "Color": "Renk", "ComfyUI": "ComfyUI", "ComfyUI API Key": "ComfyUI API Anahtarı", @@ -364,13 +364,13 @@ "ComfyUI Workflow": "ComfyUI İş Akışı", "ComfyUI Workflow Nodes": "ComfyUI İş Akışı Düğümleri", "Comma separated Node Ids (e.g. 1 or 1,2)": "", - "command": "", + "command": "komut", "Command": "Komut", "Comment": "Yorum", "Commit Message": "", - "Community Reviews": "", + "Community Reviews": "Topluluk İncelemeleri", "Completions": "Tamamlamalar", - "Compress Images in Channels": "", + "Compress Images in Channels": "Kanallarda Görselleri Sıkıştır", "Concurrent Requests": "Eşzamanlı İstekler", "Config": "", "Config imported successfully": "", @@ -379,10 +379,10 @@ "Confirm Password": "Parolayı Onayla", "Confirm your action": "İşleminizi onaylayın", "Confirm your new password": "Yeni parolanızı onaylayın", - "Confirm Your Password": "", - "Connect to an AI provider to start chatting": "", - "Connect to Open Terminal instances to browse files and use them as always-on tools. Only one can be active at a time.": "", - "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "", + "Confirm Your Password": "Parolanızı Onaylayın", + "Connect to an AI provider to start chatting": "Sohbete başlamak için bir AI sağlayıcısına bağlanın", + "Connect to Open Terminal instances to browse files and use them as always-on tools. Only one can be active at a time.": "Dosyalara göz atmak ve bunları her zaman açık araçlar olarak kullanmak için Open Terminal örneklerine bağlanın. Aynı anda yalnızca biri etkin olabilir.", + "Connect to Open Terminal instances. All users will have access to file browsing and terminal tools through these servers.": "Open Terminal örneklerine bağlanın. Tüm kullanıcılar bu sunucular üzerinden dosya gezintisine ve terminal araçlarına erişebilecek.", "Connect to your own OpenAI compatible API endpoints.": "", "Connect to your own OpenAPI compatible external tool servers.": "Kendi OpenAPI uyumlu harici araç sunucularınıza bağlanın.", "Connection failed": "Bağlantı başarısız", @@ -404,14 +404,14 @@ "Control the repetition of token sequences in the generated text. A higher value (e.g., 1.5) will penalize repetitions more strongly, while a lower value (e.g., 1.1) will be more lenient. At 1, it is disabled.": "", "Controls": "Kontroller", "Controls the balance between coherence and diversity of the output. A lower value will result in more focused and coherent text.": "", - "Conversation saved successfully": "", + "Conversation saved successfully": "Konuşma başarıyla kaydedildi", "Copied": "Kopyalandı", "Copied link to clipboard": "Bağlantıyı panoya kopyalandı", "Copied shared chat URL to clipboard!": "Paylaşılan sohbet URL'si panoya kopyalandı!", "Copied to clipboard": "Panoya kopyalandı", "Copy": "Kopyala", - "Copy API Key": "", - "Copy content": "", + "Copy API Key": "API Anahtarını Kopyala", + "Copy content": "İçeriği kopyala", "Copy Formatted Text": "Biçimlenirilmiş Metni Kopyala", "Copy Last Code Block": "", "Copy Last Response": "", @@ -424,56 +424,56 @@ "Copy URL": "", "Copying to clipboard was successful!": "Panoya kopyalama başarılı!", "CORS must be properly configured by the provider to allow requests from Open WebUI.": "Open WebUI’dan gelen isteklerin kabul edilebilmesi için sağlayıcının CORS yapılandırmasının doğru şekilde yapılmış olması gerekir.", - "Could not read file.": "", + "Could not read file.": "Dosya okunamadı.", "Create": "Oluştur", "Create a knowledge base": "Bir bilgi tabanı oluştur", "Create a model": "Bir model oluştur", - "Create a new note": "", + "Create a new note": "Yeni bir not oluştur", "Create Account": "Hesap Oluştur", "Create Admin Account": "Yönetici Hesabı Oluştur", "Create Channel": "Kanal Oluştur", "Create Folder": "Klasör Oluştur", - "Create Image": "", + "Create Image": "Görsel Oluştur", "Create Knowledge": "Bilgi Oluştur", "Create Model": "Model Oluştur", "Create new key": "Yeni anahtar oluştur", "Create new secret key": "Yeni gizli anahtar oluştur", - "Create note": "", + "Create note": "Not oluştur", "Create Note": "Not Oluştur", "Create your first note by clicking on the plus button below.": "İlk notunuzu aşağıdaki artı düğmesine basarak oluşturun.", "Created at": "Oluşturulma tarihi", "Created At": "Şu Tarihte Oluşturuldu:", "Created by": "Şunun tarafından oluşturuldu:", "Created by you": "Senin tarafından oluşturuldu", - "Created on {{date}}": "", + "Created on {{date}}": "{{date}} tarihinde oluşturuldu", "CSV Import": "CSV İçe Aktarma", - "Ctrl+Enter to Send": "", + "Ctrl+Enter to Send": "Göndermek için Ctrl+Enter", "Current Model": "Mevcut Model", "Current Password": "Mevcut Parola", "Custom": "Özel", - "Custom description enabled": "", - "Custom Gender": "", + "Custom description enabled": "Özel açıklama etkin", + "Custom Gender": "Özel Cinsiyet", "Custom Parameter Name": "", "Custom Parameter Value": "", - "Daily Messages": "", + "Daily Messages": "Günlük Mesajlar", "Danger Zone": "Tehlikeli Bölge", "Dark": "Koyu", - "Data Controls": "", + "Data Controls": "Veri Kontrolleri", "Database": "Veritabanı", "Datalab Marker API": "", "DD/MM/YYYY": "GG/AA/YYYY", "DDGS Backend": "", "December": "Aralık", - "Decrease UI Scale": "", + "Decrease UI Scale": "Arayüz Ölçeğini Küçült", "Deepgram": "", "Default": "Varsayılan", "Default (Open AI)": "Varsayılan (Open AI)", "Default (SentenceTransformers)": "Varsayılan (SentenceTransformers)", - "Default action buttons will be used.": "", - "Default description enabled": "", - "Default Features": "", - "Default Filters": "", - "Default Group": "", + "Default action buttons will be used.": "Varsayılan işlem düğmeleri kullanılacak.", + "Default description enabled": "Varsayılan açıklama etkin", + "Default Features": "Varsayılan Özellikler", + "Default Filters": "Varsayılan Filtreler", + "Default Group": "Varsayılan Grup", "Default mode works with a wider range of models by calling tools once before execution. Native mode leverages the model's built-in tool-calling capabilities, but requires the model to inherently support this feature.": "Varsayılan mod, araçları yürütmeden önce bir kez çağırarak daha geniş bir model yelpazesiyle çalışır. Yerel mod, modelin yerleşik araç çağırma yeteneklerinden yararlanır, ancak modelin bu özelliği doğal olarak desteklemesini gerektirir.", "Default Model": "Varsayılan Model", "Default model updated": "Varsayılan model güncellendi", @@ -484,48 +484,48 @@ "Default to ALL": "TÜMÜ'nü varsayılan olarak", "Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "", "Default User Role": "Varsayılan Kullanıcı Rolü", - "Defaults": "", + "Defaults": "Varsayılanlar", "Delete": "Sil", "Delete a model": "Bir modeli sil", - "Delete All": "", + "Delete All": "Tümünü Sil", "Delete All Chats": "Tüm Sohbetleri Sil", - "Delete all contents inside this folder": "", + "Delete all contents inside this folder": "Bu klasördeki tüm içerikleri sil", "Delete Chat": "Sohbeti Sil", "Delete chat?": "Sohbeti sil?", - "Delete File": "", + "Delete File": "Dosyayı Sil", "Delete folder?": "Klasörü sil?", "Delete function?": "Fonksiyonu sil?", "Delete Message": "Mesajı Sil", "Delete message?": "Mesaj Silinsin mi?", - "Delete Model": "", + "Delete Model": "Modeli Sil", "Delete note?": "Not Silinsin mi?", "Delete prompt?": "Promptu sil?", - "Delete skill?": "", + "Delete skill?": "Yeteneği sil?", "delete this link": "bu bağlantıyı sil", "Delete tool?": "Aracı sil?", "Delete User": "Kullanıcıyı Sil", - "Delete Version": "", - "Deleted": "", + "Delete Version": "Sürümü Sil", + "Deleted": "Silindi", "Deleted {{deleteModelTag}}": "{{deleteModelTag}} silindi", "Deleted {{name}}": "{{name}} silindi", "Deleted User": "Kullanıcı Silindi", "Deployment names are required for Azure OpenAI": "", - "Desc": "", - "Describe the edit...": "", - "Describe the image...": "", - "Describe what changed...": "", + "Desc": "Azalan", + "Describe the edit...": "Düzenlemeyi açıklayın...", + "Describe the image...": "Görseli açıklayın...", + "Describe what changed...": "Nelerin değiştiğini açıklayın...", "Describe your knowledge base and objectives": "Bilgi tabanınızı ve hedeflerinizi açıklayın", "Description": "Açıklama", - "Detect Artifacts Automatically": "", + "Detect Artifacts Automatically": "Eserleri Otomatik Algıla", "Dictate": "", "Didn't fully follow instructions": "Talimatları tam olarak takip etmedi", "Direct": "Doğrudan", "Direct Connections": "Doğrudan Bağlantılar", - "Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "", - "Direct Message": "", - "Direct Tool Servers": "", - "Directory selection was cancelled": "", - "Disable All": "", + "Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "Doğrudan Bağlantılar, kullanıcıların kendi OpenAI uyumlu API uç noktalarına bağlanmasına olanak tanır.", + "Direct Message": "Doğrudan Mesaj", + "Direct Tool Servers": "Doğrudan Araç Sunucuları", + "Directory selection was cancelled": "Dizin seçimi iptal edildi", + "Disable All": "Tümünü Devre Dışı Bırak", "Disable Code Interpreter": "Kod Yorumlayıcıyı Devre Dışı Bırak", "Disable Image Extraction": "", "Disable image extraction from the PDF. If Use LLM is enabled, images will be automatically captioned. Defaults to False.": "", @@ -534,24 +534,24 @@ "Discover a model": "Bir model keşfedin", "Discover a prompt": "Bir prompt keşfedin", "Discover a tool": "Bir araç keşfedin", - "Discover how to use Open WebUI and seek support from the community.": "", + "Discover how to use Open WebUI and seek support from the community.": "Open WebUI'yi nasıl kullanacağınızı keşfedin ve topluluktan destek alın.", "Discover wonders": "Harikaları keşfedin", "Discover, download, and explore custom functions": "Özel fonksiyonları keşfedin, indirin ve inceleyin", "Discover, download, and explore custom prompts": "Özel promptları keşfedin, indirin ve inceleyin", "Discover, download, and explore custom tools": "Özel araçları keşfedin, indirin ve inceleyin", "Discover, download, and explore model presets": "Model ön ayarlarını keşfedin, indirin ve inceleyin", - "Discussion channel where access is based on groups and permissions": "", - "Display": "", - "Display chat title in tab": "", + "Discussion channel where access is based on groups and permissions": "Erişimin gruplar ve izinlere dayandığı bir tartışma kanalı", + "Display": "Görüntüle", + "Display chat title in tab": "Sekmede sohbet başlığını göster", "Display Emoji in Call": "Aramada Emoji Göster", - "Display Multi-model Responses in Tabs": "", + "Display Multi-model Responses in Tabs": "Çoklu model yanıtlarını sekmelerde göster", "Display the username instead of You in the Chat": "Sohbet'te Siz yerine kullanıcı adını göster", "Displays citations in the response": "Yanıtta alıntıları gösterir", - "Displays status updates (e.g., web search progress) in the response": "", + "Displays status updates (e.g., web search progress) in the response": "Yanıtta durum güncellemelerini gösterir (ör. web arama ilerlemesi)", "Dive into knowledge": "Bilgiye dalmak", "Do not install functions from sources you do not fully trust.": "Tamamen güvenmediğiniz kaynaklardan fonksiyonlar yüklemeyin.", "Do not install tools from sources you do not fully trust.": "Tamamen güvenmediğiniz kaynaklardan araçlar yüklemeyin.", - "Do you want to sync your usage stats with Open WebUI Community?": "", + "Do you want to sync your usage stats with Open WebUI Community?": "Kullanım istatistiklerinizi Open WebUI Community ile senkronize etmek istiyor musunuz?", "Docling": "Docling", "Docling Parameters": "", "Docling Server URL required.": "", @@ -560,9 +560,9 @@ "Document Intelligence endpoint required.": "", "Document Intelligence Model": "", "Documentation": "Dökümantasyon", - "Documents": "", + "Documents": "Belgeler", "does not make any external connections, and your data stays securely on your locally hosted server.": "herhangi bir harici bağlantı yapmaz ve verileriniz güvenli bir şekilde yerel olarak barındırılan sunucunuzda kalır.", - "Domain Filter List": "", + "Domain Filter List": "Alan Adı Filtre Listesi", "don't fetch random pipelines from sources you don't trust.": "Güvenmediğiniz kaynaklardan rastgele pipelines getirmeyin.", "Don't have an account?": "Hesabınız yok mu?", "don't install random functions from sources you don't trust.": "Tanımadığınız kaynaklardan rastgele fonksiyonlar yüklemeyin.", @@ -571,33 +571,33 @@ "Done": "Tamamlandı", "Download": "İndir", "Download & Delete": "İndir ve Sil", - "Download as JSON": "", + "Download as JSON": "JSON olarak indir", "Download as SVG": "SVG olarak İndir", "Download canceled": "İndirme iptal edildi", "Download Database": "Veritabanını İndir", - "Downloading stats...": "", + "Downloading stats...": "İstatistikler indiriliyor...", "Draw": "Çiz", - "Drop any files here to upload": "", - "Drop files here to upload": "", + "Drop any files here to upload": "Yüklemek için dosyaları buraya bırakın", + "Drop files here to upload": "Yüklemek için dosyaları buraya bırakın", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "örn. '30s', '10m'. Geçerli zaman birimleri 's', 'm', 'h'.", - "e.g. 'low', 'medium', 'high'": "", + "e.g. 'low', 'medium', 'high'": "örn. 'low', 'medium', 'high'", "e.g. \"json\" or a JSON schema": "örn. \"json\" veya JSON şablonu", "e.g. 60": "örn. 60", "e.g. A filter to remove profanity from text": "örn. Metinden küfürleri kaldırmak için bir filtre", - "e.g. about the Roman Empire": "", + "e.g. about the Roman Empire": "örn. Roma İmparatorluğu hakkında", "e.g. alloy, echo, shimmer": "", "e.g. Code Review Guidelines": "", "e.g. code-review-guidelines": "", - "e.g. en": "", + "e.g. en": "örn. en", "e.g. My Filter": "örn. Benim Filtrem", "e.g. My Tools": "örn. Benim Araçlarım", "e.g. my_filter": "örn. benim_filtrem", "e.g. my_tools": "örn. benim_araçlarım", - "e.g. pdf, docx, txt": "", - "e.g. Step-by-step instructions for code reviews": "", - "e.g. Tell me a fun fact": "", - "e.g. Tell me a fun fact about the Roman Empire": "", + "e.g. pdf, docx, txt": "örn. pdf, docx, txt", + "e.g. Step-by-step instructions for code reviews": "örn. Kod incelemeleri için adım adım talimatlar", + "e.g. Tell me a fun fact": "örn. Bana eğlenceli bir bilgi söyle", + "e.g. Tell me a fun fact about the Roman Empire": "örn. Bana Roma İmparatorluğu hakkında eğlenceli bir bilgi söyle", "e.g. Tools for performing various operations": " örn.Çeşitli işlemleri gerçekleştirmek için araçlar", "e.g., 3, 4, 5 (leave blank for default)": "örn. 3, 4, 5 (öntanımlı değer için boş bırakın)", "e.g., audio/wav,audio/mpeg,video/* (leave blank for defaults)": "", @@ -608,12 +608,12 @@ "Edit Channel": "Kanalı Düzenle", "Edit Connection": "Bağlantıyı Düzenle", "Edit Default Permissions": "Varsayılan İzinleri Düzenle", - "Edit Folder": "", - "Edit Image": "", - "Edit Last Message": "", + "Edit Folder": "Klasörü Düzenle", + "Edit Image": "Görseli Düzenle", + "Edit Last Message": "Son Mesajı Düzenle", "Edit Memory": "Belleği Düzenle", "Edit Prompt": "", - "Edit Terminal Connection": "", + "Edit Terminal Connection": "Terminal Bağlantısını Düzenle", "Edit User": "Kullanıcıyı Düzenle", "Edit User Group": "Kullanıcı Grubunu Düzenle", "Edit workflow.json content": "", @@ -630,7 +630,7 @@ "Embedding Concurrent Requests": "", "Embedding Model": "Gömme Modeli", "Embedding Model Engine": "Gömme Modeli Motoru", - "Enable All": "", + "Enable All": "Tümünü Etkinleştir", "Enable API Keys": "", "Enable autocomplete generation for chat messages": "Sohbet mesajları için otomatik tamamlama üretimini etkinleştir", "Enable Code Execution": "Kod Çalıştırmayı Etkinleştir", @@ -638,7 +638,7 @@ "Enable Community Sharing": "Topluluk Paylaşımını Etkinleştir", "Enable Memory Locking (mlock) to prevent model data from being swapped out of RAM. This option locks the model's working set of pages into RAM, ensuring that they will not be swapped out to disk. This can help maintain performance by avoiding page faults and ensuring fast data access.": "", "Enable Memory Mapping (mmap) to load model data. This option allows the system to use disk storage as an extension of RAM by treating disk files as if they were in RAM. This can improve model performance by allowing for faster data access. However, it may not work correctly with all systems and can consume a significant amount of disk space.": "", - "Enable Message Queue": "", + "Enable Message Queue": "Mesaj Kuyruğunu Etkinleştir", "Enable Message Rating": "Mesaj Değerlendirmeyi Etkinleştir", "Enable Mirostat sampling for controlling perplexity.": "", "Enable New Sign Ups": "Yeni Kayıtları Etkinleştir", @@ -648,7 +648,7 @@ "Endpoint URL": "Uçnokta URL", "Enforce Temporary Chat": "Geçici Sohbete Zorla", "Enhance": "İyileştir", - "Enrich Hybrid Search Text": "", + "Enrich Hybrid Search Text": "Hibrit Arama Metnini Zenginleştir", "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "CSV dosyanızın şu sırayla 4 sütun içerdiğinden emin olun: İsim, E-posta, Şifre, Rol.", "Enter {{role}} message here": "Buraya {{role}} mesajını girin", "Enter a detail about yourself for your LLMs to recall": "LLM'lerinizin hatırlaması için kendiniz hakkında bir bilgi girin", @@ -662,7 +662,7 @@ "Enter Application DN Password": "Uygulama DN Parolasını Girin", "Enter Bing Search V7 Endpoint": "Bing Arama V7 Uç Noktasını Girin", "Enter Bing Search V7 Subscription Key": "Bing Arama V7 Abonelik Anahtarını Girin", - "Enter Bocha Search API Key": "", + "Enter Bocha Search API Key": "Bocha Search API Anahtarını Girin", "Enter Brave Search API Key": "Brave Search API Anahtarını Girin", "Enter certificate path": "Sertifika yolunu girin", "Enter Chunk Min Size Target": "", @@ -683,10 +683,10 @@ "Enter Exa API Key": "", "Enter External Document Loader API Key": "", "Enter External Document Loader URL": "", - "Enter External Web Loader API Key": "", - "Enter External Web Loader URL": "", - "Enter External Web Search API Key": "", - "Enter External Web Search URL": "", + "Enter External Web Loader API Key": "Harici Web Yükleyici API Anahtarını Girin", + "Enter External Web Loader URL": "Harici Web Yükleyici URL'sini Girin", + "Enter External Web Search API Key": "Harici Web Arama API Anahtarını Girin", + "Enter External Web Search URL": "Harici Web Arama URL'sini Girin", "Enter Firecrawl API Base URL": "", "Enter Firecrawl API Key": "", "Enter Firecrawl Timeout": "", @@ -704,7 +704,7 @@ "Enter Jupyter Token": "", "Enter Jupyter URL": "", "Enter Kagi Search API Key": "Kagi Search API Anahtarını Girin", - "Enter Key Behavior": "", + "Enter Key Behavior": "Enter Tuşu Davranışı", "Enter language codes": "Dil kodlarını girin", "Enter MinerU API Key": "", "Enter Mistral API Base URL": "", @@ -715,10 +715,10 @@ "Enter name": "İsim girin", "Enter New Password": "Yeni Parola Girin", "Enter Number of Steps (e.g. 50)": "Adım Sayısını Girin (örn. 50)", - "Enter Ollama Cloud API Key": "", - "Enter Perplexity API Key": "", - "Enter Perplexity Search API URL": "", - "Enter Playwright Timeout": "", + "Enter Ollama Cloud API Key": "Ollama Cloud API Anahtarını Girin", + "Enter Perplexity API Key": "Perplexity API Anahtarını Girin", + "Enter Perplexity Search API URL": "Perplexity Search API URL'sini Girin", + "Enter Playwright Timeout": "Playwright Zaman Aşımını Girin", "Enter Playwright WebSocket URL": "", "Enter proxy URL (e.g. https://user:password@host:port)": "", "Enter reasoning effort": "", @@ -726,7 +726,7 @@ "Enter SearchApi API Key": "Arama-API Anahtarını Girin", "Enter SearchApi Engine": "Arama-API Motorunu Girin", "Enter Searxng Query URL": "Searxng Sorgu URL'sini girin", - "Enter Searxng search language": "", + "Enter Searxng search language": "Searxng arama dilini girin", "Enter Seed": " Tohum(seed) Girin", "Enter SerpApi API Key": "", "Enter SerpApi Engine": "", @@ -736,32 +736,32 @@ "Enter server host": "Sunucu ana bilgisayarını girin", "Enter server label": "Sunucu etiketini girin", "Enter server port": "Sunucu bağlantı noktasını girin", - "Enter skill instructions in markdown...": "", - "Enter Sougou Search API sID": "", - "Enter Sougou Search API SK": "", + "Enter skill instructions in markdown...": "Yetenek talimatlarını Markdown olarak girin...", + "Enter Sougou Search API sID": "Sougou Search API sID'sini Girin", + "Enter Sougou Search API SK": "Sougou Search API SK'sini Girin", "Enter stop sequence": "Durdurma dizisini girin", "Enter system prompt": "Sistem promptunu girin", "Enter system prompt here": "Sistem promptunu buraya girin.", "Enter Tavily API Key": "Tavily API Anahtarını Girin", "Enter Tavily Extract Depth": "", "Enter the public URL of your WebUI. This URL will be used to generate links in the notifications.": "", - "Enter the URL of the function to import": "", - "Enter the URL to import": "", + "Enter the URL of the function to import": "İçe aktarılacak fonksiyonun URL'sini girin", + "Enter the URL to import": "İçe aktarılacak URL'yi girin", "Enter Tika Server URL": "Tika Sunucu URL'sini Girin", - "Enter timeout in seconds": "", - "Enter to Send": "", + "Enter timeout in seconds": "Zaman aşımını saniye cinsinden girin", + "Enter to Send": "Göndermek için Enter", "Enter Top K": "Top K'yı girin", "Enter Top K Reranker": "", "Enter URL (e.g. http://127.0.0.1:7860/)": "URL'yi Girin (örn. http://127.0.0.1:7860/)", "Enter URL (e.g. http://localhost:11434)": "URL'yi Girin (e.g. http://localhost:11434)", - "Enter value": "", - "Enter value (true/false)": "", - "Enter Yacy Password": "", - "Enter Yacy URL (e.g. http://yacy.example.com:8090)": "", - "Enter Yacy Username": "", - "Enter Yandex Web Search API Key": "", - "Enter Yandex Web Search URL": "", - "Enter You.com API Key": "", + "Enter value": "Bir değer girin", + "Enter value (true/false)": "Bir değer girin (true/false)", + "Enter Yacy Password": "Yacy Parolasını Girin", + "Enter Yacy URL (e.g. http://yacy.example.com:8090)": "Yacy URL'sini Girin (örn. http://yacy.example.com:8090)", + "Enter Yacy Username": "Yacy Kullanıcı Adını Girin", + "Enter Yandex Web Search API Key": "Yandex Web Search API Anahtarını Girin", + "Enter Yandex Web Search URL": "Yandex Web Search URL'sini Girin", + "Enter You.com API Key": "You.com API Anahtarını Girin", "Enter your code here...": "Kodu buraya girin...", "Enter your current password": "Mevcut parolanızı girin", "Enter Your Email": "E-postanızı Girin", @@ -778,14 +778,14 @@ "Entra ID": "", "Error": "Hata", "ERROR": "HATA", - "Error accessing directory": "", + "Error accessing directory": "Dizine erişilirken hata oluştu", "Error accessing Google Drive: {{error}}": "Google Drive'a erişim hatası: {{error}}", - "Error accessing media devices.": "", - "Error starting recording.": "", + "Error accessing media devices.": "Medya cihazlarına erişirken hata oluştu.", + "Error starting recording.": "Kayıt başlatılırken hata oluştu.", "Error unloading model: {{error}}": "", "Error uploading file: {{error}}": "Dosya yüklenirken hata oluştu: {{error}}", - "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "", - "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "", + "Error: A model with the ID '{{modelId}}' already exists. Please select a different ID to proceed.": "Hata: '{{modelId}}' kimliğine sahip bir model zaten mevcut. Devam etmek için lütfen farklı bir kimlik seçin.", + "Error: Model ID cannot be empty. Please enter a valid ID to proceed.": "Hata: Model kimliği boş olamaz. Devam etmek için lütfen geçerli bir kimlik girin.", "Evaluations": "Değerlendirmeler", "Exa API Key": "Exa API Anahtarı", "Example: (&(objectClass=inetOrgPerson)(uid=%s))": "Örnek: (&(objectClass=inetOrgPerson)(uid=%s))", @@ -807,93 +807,93 @@ "Export All Chats (All Users)": "Tüm Sohbetleri Dışa Aktar (Tüm Kullanıcılar)", "Export chat (.json)": "Sohbeti dışa aktar (.json)", "Export Chats": "Sohbetleri Dışa Aktar", - "Export Config": "", - "Export Models": "", + "Export Config": "Yapılandırmayı Dışa Aktar", + "Export Models": "Modelleri Dışa Aktar", "Export Prompts": "", "Export to CSV": "CSV'ye Aktar", - "Export Tools": "", - "Export Users": "", - "External": "", - "External Document Loader URL required.": "", - "External Task Model": "", - "External Web Loader API Key": "", - "External Web Loader URL": "", - "External Web Search API Key": "", - "External Web Search URL": "", - "Fade Effect for Streaming Text": "", + "Export Tools": "Araçları Dışa Aktar", + "Export Users": "Kullanıcıları Dışa Aktar", + "External": "Harici", + "External Document Loader URL required.": "Harici Belge Yükleyici URL gerekli.", + "External Task Model": "Harici Görev Modeli", + "External Web Loader API Key": "Harici Web Yükleyici API Anahtarı", + "External Web Loader URL": "Harici Web Yükleyici URL'si", + "External Web Search API Key": "Harici Web Arama API Anahtarı", + "External Web Search URL": "Harici Web Arama URL'si", + "Fade Effect for Streaming Text": "Akış Metni için Solma Efekti", "Failed to add file.": "Dosya eklenemedi.", - "Failed to add members": "", + "Failed to add members": "Üyeler eklenemedi", "Failed to archive chat.": "", - "Failed to attach file": "", - "Failed to clear status": "", + "Failed to attach file": "Dosya eklenemedi", + "Failed to clear status": "Durum temizlenemedi", "Failed to connect to {{URL}} OpenAPI tool server": "", - "Failed to connect to {{URL}} terminal server": "", - "Failed to copy link": "", + "Failed to connect to {{URL}} terminal server": "{{URL}} terminal sunucusuna bağlanılamadı", + "Failed to copy link": "Bağlantı kopyalanamadı", "Failed to create API Key.": "API Anahtarı oluşturulamadı.", - "Failed to delete note": "", - "Failed to download image": "", - "Failed to extract content from the file: {{error}}": "", - "Failed to extract content from the file.": "", - "Failed to fetch models": "", - "Failed to generate title": "", - "Failed to import models": "", - "Failed to load chat preview": "", + "Failed to delete note": "Not silinemedi", + "Failed to download image": "Görsel indirilemedi", + "Failed to extract content from the file: {{error}}": "Dosyadan içerik çıkarılamadı: {{error}}", + "Failed to extract content from the file.": "Dosyadan içerik çıkarılamadı.", + "Failed to fetch models": "Modeller alınamadı", + "Failed to generate title": "Başlık oluşturulamadı", + "Failed to import models": "Modeller içe aktarılamadı", + "Failed to load chat preview": "Sohbet ön izlemesi yüklenemedi", "Failed to load DOCX file. Please try downloading it instead.": "", - "Failed to load Excel/CSV file. Please try downloading it instead.": "", - "Failed to load file content.": "", - "Failed to load Interface settings": "", + "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV dosyası yüklenemedi. Lütfen bunun yerine indirmeyi deneyin.", + "Failed to load file content.": "Dosya içeriği yüklenemedi.", + "Failed to load Interface settings": "Arayüz ayarları yüklenemedi", "Failed to load PPTX file. Please try downloading it instead.": "", - "Failed to move chat": "", + "Failed to move chat": "Sohbet taşınamadı", "Failed to process URL: {{url}}": "", "Failed to read clipboard contents": "Pano içeriği okunamadı", - "Failed to remove member": "", + "Failed to remove member": "Üye kaldırılamadı", "Failed to render diagram": "", "Failed to render visualization": "", - "Failed to save connections": "", + "Failed to save connections": "Bağlantılar kaydedilemedi", "Failed to save conversation": "Sohbet kaydedilemedi", "Failed to save models configuration": "Modeller yapılandırması kaydedilemedi", - "Failed to save terminal servers": "", - "Failed to unshare chat.": "", + "Failed to save terminal servers": "Terminal sunucuları kaydedilemedi", + "Failed to unshare chat.": "Sohbet paylaşımı kaldırılamadı.", "Failed to update settings": "Ayarlar güncellenemedi", - "Failed to update status": "", + "Failed to update status": "Durum güncellenemedi", "Failed to upload file.": "Dosya yüklenemedi.", "Features": "Özellikler", "Features Permissions": "Özellik Yetkileri", "February": "Şubat", - "Feedback": "", - "Feedback Activity": "", - "Feedback deleted successfully": "", - "Feedback Details": "", + "Feedback": "Geri Bildirim", + "Feedback Activity": "Geri Bildirim Etkinliği", + "Feedback deleted successfully": "Geri bildirim başarıyla silindi", + "Feedback Details": "Geri Bildirim Ayrıntıları", "Feedback History": "Geri Bildirim Geçmişi", "Feel free to add specific details": "Spesifik ayrıntılar eklemekten çekinmeyin", - "Female": "", + "Female": "Kadın", "File": "Dosya", "File added successfully.": "Dosya başarıyla eklendi.", - "File attached to chat": "", - "File browser": "", - "File content": "", + "File attached to chat": "Dosya sohbete eklendi", + "File browser": "Dosya tarayıcısı", + "File content": "Dosya içeriği", "File content updated successfully.": "Dosya içeriği başarıyla güncellendi.", - "File Context": "", - "File deleted successfully.": "", + "File Context": "Dosya Bağlamı", + "File deleted successfully.": "Dosya başarıyla silindi.", "File Mode": "Dosya Modu", - "File name": "", + "File name": "Dosya adı", "File not found.": "Dosya bulunamadı.", "File removed successfully.": "Dosya başarıyla kaldırıldı.", "File size should not exceed {{maxSize}} MB.": "Dosya boyutu {{maxSize}} MB'yi aşmamalıdır.", - "File Upload": "", + "File Upload": "Dosya Yükleme", "File uploaded successfully": "Dosya başarıyla yüklendi", - "File uploaded!": "", - "Filename": "", + "File uploaded!": "Dosya yüklendi!", + "Filename": "Dosya adı", "Files": "Dosyalar", "Filter": "", "Filter is now globally disabled": "Filtre artık global olarak devre dışı", "Filter is now globally enabled": "Filtre artık global olarak devrede", "Filters": "Filtreler", "Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Parmak izi sahteciliği tespit edildi: Avatar olarak baş harfler kullanılamıyor. Varsayılan profil resmine dönülüyor.", - "Firecrawl API Base URL": "", - "Firecrawl API Key": "", - "Firecrawl Timeout (s)": "", - "Floating Quick Actions": "", + "Firecrawl API Base URL": "Firecrawl API Temel URL'si", + "Firecrawl API Key": "Firecrawl API Anahtarı", + "Firecrawl Timeout (s)": "Firecrawl Zaman Aşımı (s)", + "Floating Quick Actions": "Yüzen Hızlı Eylemler", "Focus Chat Input": "", "Folder": "Klasör", "Folder Background Image": "Klasör Arka Plan Resmi", @@ -910,7 +910,7 @@ "Follow Up Generation": "", "Follow Up Generation Prompt": "", "Follow up: {{question}}": "", - "Follow-Up Auto-Generation": "", + "Follow-Up Auto-Generation": "Devam İstemlerini Otomatik Oluşturma", "Followed instructions perfectly": "Talimatları mükemmel şekilde takip etti", "for placeholders": "", "Force OCR": "", @@ -992,7 +992,7 @@ "Hide from Sidebar": "", "Hide Model": "Modeli Gizle", "High": "", - "High Contrast Mode": "", + "High Contrast Mode": "Yüksek Kontrast Modu", "History": "", "Home": "", "Host": "Ana bilgisayar", @@ -1012,8 +1012,8 @@ "Ignite curiosity": "Merak uyandırın", "Image": "Görsel", "Image Compression": "Görüntü Sıkıştırma", - "Image Compression Height": "", - "Image Compression Width": "", + "Image Compression Height": "Görüntü Sıkıştırma Yüksekliği", + "Image Compression Width": "Görüntü Sıkıştırma Genişliği", "Image Edit": "", "Image Edit Engine": "", "Image Generation": "Görüntü Oluşturma", @@ -1039,7 +1039,7 @@ "Include `--api-auth` flag when running stable-diffusion-webui": "stable-diffusion-webui çalıştırılırken `--api-auth` bayrağını dahil edin", "Include `--api` flag when running stable-diffusion-webui": "stable-diffusion-webui çalıştırılırken `--api` bayrağını dahil edin", "Includes SharePoint": "SharePoint içerir", - "Increase UI Scale": "", + "Increase UI Scale": "Arayüz Ölçeğini Büyüt", "Influences how quickly the algorithm responds to feedback from the generated text. A lower learning rate will result in slower adjustments, while a higher learning rate will make the algorithm more responsive.": "", "Info": "Bilgi", "Initials": "", @@ -1049,9 +1049,9 @@ "Input Key (e.g. text, unet_name, steps)": "", "Input Variables": "", "Insert": "", - "Insert Follow-Up Prompt to Input": "", - "Insert Prompt as Rich Text": "", - "Insert Suggestion Prompt to Input": "", + "Insert Follow-Up Prompt to Input": "Devam İstemini Girdiye Ekle", + "Insert Prompt as Rich Text": "İstemi Zengin Metin Olarak Ekle", + "Insert Suggestion Prompt to Input": "Öneri İstemini Girdiye Ekle", "Install from Github URL": "Github URL'sinden yükleyin", "Instant Auto-Send After Voice Transcription": "Ses Transkripsiyonundan Sonra Anında Otomatik Gönder", "Integration": "", @@ -1083,7 +1083,7 @@ "JWT Expiration": "JWT Bitişi", "JWT Token": "JWT Token", "Kagi Search API Key": "Kagi Arama API Anahtarı", - "Keep Follow-Up Prompts in Chat": "", + "Keep Follow-Up Prompts in Chat": "Devam İstemlerini Sohbette Tut", "Keep in Sidebar": "", "Key": "Anahtar", "Key is required": "Anahtar gerekli", @@ -1119,7 +1119,7 @@ "Leaderboard": "Liderlik Tablosu", "Learn more": "", "Learn More": "", - "Learn more about Open Terminal": "", + "Learn more about Open Terminal": "Open Terminal hakkında daha fazla bilgi edinin", "Learn more about OpenAPI tool servers.": "OpenAPI araç sunucuları hakkında daha fazla bilgi edinin.", "Learn more about Voxtral transcription.": "", "Leave a public review for {{modelName}}": "", @@ -1130,8 +1130,8 @@ "Leave empty to include all models from \"{{url}}/models\" endpoint": "", "Leave empty to include all models or select specific models": "Tüm modelleri dahil etmek için boş bırakın veya belirli modelleri seçin", "Leave empty to use first admin user": "", - "Leave empty to use the default config, or enter a valid json (see https://yandex.cloud/en/docs/search-api/api-ref/WebSearch/search#yandex.cloud.searchapi.v2.WebSearchRequest)": "", - "Leave empty to use the default model (voxtral-mini-latest).": "", + "Leave empty to use the default config, or enter a valid json (see https://yandex.cloud/en/docs/search-api/api-ref/WebSearch/search#yandex.cloud.searchapi.v2.WebSearchRequest)": "Varsayılan yapılandırmayı kullanmak için boş bırakın veya geçerli bir JSON girin (bkz. https://yandex.cloud/en/docs/search-api/api-ref/WebSearch/search#yandex.cloud.searchapi.v2.WebSearchRequest)", + "Leave empty to use the default model (voxtral-mini-latest).": "Varsayılan modeli kullanmak için boş bırakın (voxtral-mini-latest).", "Leave empty to use the default prompt, or enter a custom prompt": "Varsayılan promptu kullanmak için boş bırakın veya özel bir prompt girin", "Leave model field empty to use the default model.": "", "Legacy": "", @@ -1139,7 +1139,7 @@ "License": "Lisans", "Lift List": "", "Light": "Açık", - "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "", + "Limit concurrent search queries. 0 = unlimited (default). Set to 1 for sequential execution (recommended for APIs with strict rate limits like Brave free tier).": "Eşzamanlı arama sorgularını sınırla. 0 = sınırsız (varsayılan). Sıralı yürütme için 1 olarak ayarlayın (Brave ücretsiz katman gibi katı oran sınırlarına sahip API'ler için önerilir).", "Limits the number of concurrent embedding requests. Set to 0 for unlimited.": "", "List": "", "Listening...": "Dinleniyor...", @@ -1221,12 +1221,12 @@ "Model {{name}} is now {{status}}": "{{name}} modeli artık {{status}}", "Model {{name}} is now hidden": "Model {{name}} artık gizli", "Model {{name}} is now visible": "Model {{name}} artık görünür", - "Model accepts file inputs": "", + "Model accepts file inputs": "Model dosya girdilerini kabul eder", "Model accepts image inputs": "Model görüntü girdilerini kabul eder", - "Model can execute code and perform calculations": "", + "Model can execute code and perform calculations": "Model kod çalıştırabilir ve hesaplamalar yapabilir", "Model can generate images based on text prompts": "", - "Model can search the web for information": "", - "Model Capabilities": "", + "Model can search the web for information": "Model bilgileri aramak için web'de arama yapabilir", + "Model Capabilities": "Model Yetenekleri", "Model created successfully!": "Model başarıyla oluşturuldu!", "Model filesystem path detected. Model shortname is required for update, cannot continue.": "Model dosya sistemi yolu algılandı. Güncelleme için model kısa adı gerekli, devam edilemiyor.", "Model Filtering": "Model Filtreleme", @@ -1262,7 +1262,7 @@ "More Options": "", "Move": "", "Moved {{name}}": "", - "My Terminal": "", + "My Terminal": "Terminalim", "Name": "Ad", "Name and ID are required, please fill them out": "", "Name your knowledge base": "Bilgi tabanınıza bir ad verin", @@ -1279,9 +1279,9 @@ "New Note": "", "New Password": "Yeni Parola", "New Prompt": "", - "New Skill": "", + "New Skill": "Yeni Yetenek", "New Temporary Chat": "", - "New Terminal": "", + "New Terminal": "Yeni Terminal", "New Tool": "", "New Webhook": "", "new-channel": "yeni-kanal", @@ -1326,12 +1326,12 @@ "No results found": "Sonuç bulunamadı", "No search query generated": "Hiç arama sorgusu oluşturulmadı", "No servers detected": "", - "No skills found": "", + "No skills found": "Yetenek bulunamadı", "No source available": "Kaynak mevcut değil", "No sources found": "", "No suggestion prompts": "Önerilen istem yok", - "No Terminal connection configured.": "", - "No terminal connections configured.": "", + "No Terminal connection configured.": "Yapılandırılmış Terminal bağlantısı yok.", + "No terminal connections configured.": "Yapılandırılmış terminal bağlantısı yok.", "No tool server connections configured.": "", "No tools found": "", "No users were found.": "Kullanıcı bulunamadı.", @@ -1386,12 +1386,12 @@ "Open in full screen": "Tam ekranda aç", "Open link": "", "Open modal to configure connection": "", - "Open Modal To Manage Floating Quick Actions": "", - "Open Modal To Manage Image Compression": "", + "Open Modal To Manage Floating Quick Actions": "Yüzen hızlı eylemleri yönetmek için pencereyi aç", + "Open Modal To Manage Image Compression": "Görüntü sıkıştırmayı yönetmek için pencereyi aç", "Open Model Selector": "", "Open Settings": "", "Open Sidebar": "", - "Open Terminal": "", + "Open Terminal": "Terminali Aç", "Open User Profile Menu": "", "Open WebUI can use tools provided by any OpenAPI server.": "Open WebUI OpenAPI tarafından sağlanan araçları kullanabilir", "Open WebUI uses faster-whisper internally.": "Open WebUI, dahili olarak daha hızlı-fısıltı kullanır.", @@ -1441,9 +1441,9 @@ "Permission denied when accessing microphone: {{error}}": "Mikrofona erişim izni reddedildi: {{error}}", "Permissions": "İzinler", "Perplexity API Key": "Perplexity API Anahtarı", - "Perplexity Model": "", - "Perplexity Search API URL": "", - "Perplexity Search Context Usage": "", + "Perplexity Model": "Perplexity Modeli", + "Perplexity Search API URL": "Perplexity Search API URL'si", + "Perplexity Search Context Usage": "Perplexity Search Bağlam Kullanımı", "Personalization": "Kişiselleştirme", "Pin": "Sabitle", "Pinned": "Sabitlenmiş", @@ -1513,7 +1513,7 @@ "Pull Model": "", "Query Generation Prompt": "Sorgu Oluşturma Promptu", "Querying": "", - "Quick Actions": "", + "Quick Actions": "Hızlı Eylemler", "RAG Template": "RAG Şablonu", "Rate {{rating}} out of 10": "", "Rating": "Derecelendirme", @@ -1535,7 +1535,7 @@ "Refresh": "", "Refused when it shouldn't have": "Reddedilmemesi gerekirken reddedildi", "Regenerate": "Tekrar Oluştur", - "Regenerate Menu": "", + "Regenerate Menu": "Yeniden Oluşturma Menüsü", "Regenerate Response": "", "Register Again": "", "Register Client": "", @@ -1558,7 +1558,7 @@ "Remove image": "", "Remove Model": "Modeli Kaldır", "Rename": "Yeniden Adlandır", - "Render Markdown in Previews": "", + "Render Markdown in Previews": "Önizlemelerde Markdown'u İşle", "Reorder Models": "Modelleri Yeniden Sırala", "Reply": "", "Reply in Thread": "Konuya Yanıtla", @@ -1602,46 +1602,46 @@ "Save Chat": "", "Saved": "Kaydedildi", "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Sohbet kayıtlarının doğrudan tarayıcınızın depolama alanına kaydedilmesi artık desteklenmemektedir. Lütfen aşağıdaki butona tıklayarak sohbet kayıtlarınızı indirmek ve silmek için bir dakikanızı ayırın. Endişelenmeyin, sohbet günlüklerinizi arkayüze kolayca yeniden aktarabilirsiniz:", - "Scroll On Branch Change": "", + "Scroll On Branch Change": "Dal Değişiminde Kaydır", "Search": "Ara", "Search a model": "Bir model ara", - "Search all emojis": "", - "Search and manage user memories": "", - "Search and view user chat history": "", + "Search all emojis": "Tüm emojileri ara", + "Search and manage user memories": "Kullanıcı anılarını ara ve yönet", + "Search and view user chat history": "Kullanıcı sohbet geçmişini ara ve görüntüle", "Search Base": "Temel Ara", - "Search channels and channel messages": "", + "Search channels and channel messages": "Kanalları ve kanal mesajlarını ara", "Search Chats": "Sohbetleri Ara", "Search Collection": "Koleksiyon Ara", - "Search Files": "", + "Search Files": "Dosyaları Ara", "Search Filters": "Filtreleri Ara", - "search for archived chats": "", - "search for folders": "", - "search for pinned chats": "", - "search for shared chats": "", + "search for archived chats": "arşivlenmiş sohbetleri ara", + "search for folders": "klasörleri ara", + "search for pinned chats": "sabitlenmiş sohbetleri ara", + "search for shared chats": "paylaşılan sohbetleri ara", "search for tags": "etiketler için ara", "Search Functions": "Fonksiyonları Ara", - "Search Groups": "", - "Search In Models": "", + "Search Groups": "Grupları Ara", + "Search In Models": "Modellerde Ara", "Search Knowledge": "Bilgi Ara", "Search Models": "Modelleri Ara", - "Search Notes": "", + "Search Notes": "Notları Ara", "Search options": "Arama seçenekleri", "Search Prompts": "Prompt Ara", "Search Result Count": "Arama Sonucu Sayısı", - "Search Skills": "", + "Search Skills": "Yetenekleri Ara", "Search the internet": "İNternette Ara", - "Search the web and fetch URLs": "", + "Search the web and fetch URLs": "Web'de ara ve URL'leri getir", "Search Tools": "Arama Araçları", - "Search, view, and manage user notes": "", + "Search, view, and manage user notes": "Kullanıcı notlarını ara, görüntüle ve yönet", "SearchApi API Key": "Arama-API API Anahtarı", "SearchApi Engine": "Arama-API Motoru", "Searched {{count}} sites": "{{count}} site arandı", - "Searching": "", + "Searching": "Aranıyor", "Searching \"{{searchQuery}}\"": "\"{{searchQuery}}\" aranıyor", "Searching Knowledge for \"{{searchQuery}}\"": "\"{{searchQuery}}\" için Bilgi aranıyor", "Searching the web": "İnternette aranıyor...", "Searxng Query URL": "Searxng Sorgu URL'si", - "Searxng search language (all, en, es, de, fr, etc.)": "", + "Searxng search language (all, en, es, de, fr, etc.)": "Searxng arama dili (all, en, es, de, fr, vb.)", "See readme.md for instructions": "Yönergeler için readme.md dosyasına bakın", "See what's new": "Yeniliklere göz atın", "Seed": "Seed", @@ -1730,7 +1730,7 @@ "Show All": "", "Show all ({{COUNT}} characters)": "", "Show Files": "", - "Show Formatting Toolbar": "", + "Show Formatting Toolbar": "Biçimlendirme Araç Çubuğunu Göster", "Show image preview": "", "Show Model": "Modeli Göster", "Show Shortcuts": "", @@ -1748,18 +1748,18 @@ "Single": "", "Sink List": "", "sk-1234": "sk-1234", - "Skill created successfully": "", - "Skill deleted successfully": "", - "Skill Description": "", - "Skill ID": "", - "Skill imported successfully": "", - "Skill Instructions": "", - "Skill Name": "", - "Skill updated successfully": "", - "Skills": "", - "Skills Access": "", - "Skills Public Sharing": "", - "Skills Sharing": "", + "Skill created successfully": "Yetenek başarıyla oluşturuldu", + "Skill deleted successfully": "Yetenek başarıyla silindi", + "Skill Description": "Yetenek Açıklaması", + "Skill ID": "Yetenek Kimliği", + "Skill imported successfully": "Yetenek başarıyla içe aktarıldı", + "Skill Instructions": "Yetenek Talimatları", + "Skill Name": "Yetenek Adı", + "Skill updated successfully": "Yetenek başarıyla güncellendi", + "Skills": "Yetenekler", + "Skills Access": "Yeteneklere Erişim", + "Skills Public Sharing": "Yeteneklerin Herkese Açık Paylaşımı", + "Skills Sharing": "Yeteneklerin Paylaşımı", "Skip Cache": "", "Skip the cache and re-run the inference. Defaults to False.": "", "Something went wrong :/": "", @@ -1768,10 +1768,10 @@ "Sonar Pro": "", "Sonar Reasoning": "", "Sonar Reasoning Pro": "", - "Sort": "", - "Sort by": "", - "Sougou Search API sID": "", - "Sougou Search API SK": "", + "Sort": "Sırala", + "Sort by": "Şuna göre sırala", + "Sougou Search API sID": "Sougou Search API sID'si", + "Sougou Search API SK": "Sougou Search API SK'si", "Source": "Kaynak", "Speech Playback Speed": "Konuşma Oynatma Hızı", "Speech recognition error: {{error}}": "Konuşma tanıma hatası: {{error}}", @@ -1801,7 +1801,7 @@ "Strip existing OCR text from the PDF and re-run OCR. Ignored if Force OCR is enabled. Defaults to False.": "", "STT Model": "STT Modeli", "STT Settings": "STT Ayarları", - "Stylized PDF Export": "", + "Stylized PDF Export": "Biçimlendirilmiş PDF Dışa Aktarımı", "Submit question": "", "Submit suggestion": "", "Subtitle": "", @@ -1835,13 +1835,13 @@ "Task Model": "", "Tasks": "Görevler", "Tavily API Key": "Tavily API Anahtarı", - "Tavily Extract Depth": "", + "Tavily Extract Depth": "Tavily Çıkarma Derinliği", "Tell us more:": "Bize daha fazlasını anlat:", "Temperature": "Temperature", "Temporary Chat": "Geçici Sohbet", - "Temporary Chat by Default": "", - "Terminal": "", - "Terminal servers saved": "", + "Temporary Chat by Default": "Varsayılan Olarak Geçici Sohbet", + "Terminal": "Terminal", + "Terminal servers saved": "Terminal sunucuları kaydedildi", "Text Splitter": "Metin Bölücü", "Text-to-Speech": "Metinden Sese", "Text-to-Speech Engine": "Metinden Sese Motoru", @@ -1912,7 +1912,7 @@ "To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "WebUI'ye erişmek için lütfen yöneticiyle iletişime geçin. Yöneticiler kullanıcı durumlarını Yönetici Panelinden yönetebilir.", "To attach knowledge base here, add them to the \"Knowledge\" workspace first.": "Bilgi tabanını buraya eklemek için önce bunları \"Bilgi\" çalışma alanına ekleyin.", "To learn more about available endpoints, visit our documentation.": "Mevcut uç noktalar hakkında daha fazla bilgi edinmek için belgelerimize göz atın.", - "To select skills here, add them to the \"Skills\" workspace first.": "", + "To select skills here, add them to the \"Skills\" workspace first.": "Burada yetenek seçmek için önce bunları \"Yetenekler\" çalışma alanına ekleyin.", "To select toolkits here, add them to the \"Tools\" workspace first.": "Araçları burada seçmek için öncelikle bunları \"Araçlar\" çalışma alanına ekleyin.", "Toast notifications for new updates": "", "Today": "Bugün", @@ -1948,9 +1948,9 @@ "Top K Reranker": "", "Transformers": "Dönüştürücüler", "Trouble accessing Ollama?": "Ollama'ya erişmede sorun mu yaşıyorsunuz?", - "Trust Proxy Environment": "", - "Try adjusting your search or filter to find what you are looking for.": "", - "Try Again": "", + "Trust Proxy Environment": "Proxy Ortamına Güven", + "Try adjusting your search or filter to find what you are looking for.": "Aradığınızı bulmak için aramanızı veya filtrenizi ayarlamayı deneyin.", + "Try Again": "Tekrar Dene", "TTS Model": "TTS Modeli", "TTS Settings": "TTS Ayarları", "TTS Voice": "TTS Sesi", @@ -1959,7 +1959,7 @@ "Type Hugging Face Resolve (Download) URL": "HuggingFace Çözümleme (İndirme) URL'sini Yazın", "Uh-oh! There was an issue with the response.": "Opps! Yanıtla ilgili bir sorun oluştu", "UI": "Arayüz", - "UI Scale": "", + "UI Scale": "Arayüz Ölçeği", "Unarchive All": "Tümünü Arşivden Çıkar", "Unarchive All Archived Chats": "Arşivlenmiş Tüm Sohbetleri Arşivden Çıkar", "Unarchive Chat": "Sohbeti Arşivden Çıkar", @@ -2060,7 +2060,7 @@ "Web Loader Engine": "", "Web Search": "Web Araması", "Web Search Engine": "Web Arama Motoru", - "Web Search in Chat": "", + "Web Search in Chat": "Sohbette Web Araması", "Web Search Query Generation": "Web Arama Sorgusu Oluşturma", "Webhook Name": "", "Webhook URL": "Webhook URL", @@ -2097,11 +2097,11 @@ "Yacy Instance URL": "", "Yacy Password": "Yacy Parolası", "Yacy Username": "Yacy Kullanıcı Adı", - "Yahoo": "", - "Yandex": "", - "Yandex Web Search API Key": "", - "Yandex Web Search config": "", - "Yandex Web Search URL": "", + "Yahoo": "Yahoo", + "Yandex": "Yandex", + "Yandex Web Search API Key": "Yandex Web Arama API Anahtarı", + "Yandex Web Search config": "Yandex Web Arama Yapılandırması", + "Yandex Web Search URL": "Yandex Web Arama URL'si", "Yesterday": "Dün", "Yesterday at {{LOCALIZED_TIME}}": "", "You": "Sen", @@ -2111,7 +2111,7 @@ "You cannot upload an empty file.": "Boş bir dosya yükleyemezsiniz.", "You do not have permission to edit this model": "", "You do not have permission to edit this prompt.": "", - "You do not have permission to edit this skill.": "", + "You do not have permission to edit this skill.": "Bu yeteneği düzenleme izniniz yok.", "You do not have permission to edit this tool": "", "You do not have permission to make this public": "", "You do not have permission to send messages in this channel.": "", From 2d0b94794f63f9b1a8c9db0e212e5d32b8f020bb Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sat, 7 Mar 2026 23:35:25 +0100 Subject: [PATCH 064/114] Update translation.json (#22353) --- src/lib/i18n/locales/de-DE/translation.json | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/lib/i18n/locales/de-DE/translation.json b/src/lib/i18n/locales/de-DE/translation.json index 21e871c778..94d544d1bf 100644 --- a/src/lib/i18n/locales/de-DE/translation.json +++ b/src/lib/i18n/locales/de-DE/translation.json @@ -282,7 +282,7 @@ "Character limit for autocomplete generation input": "Zeichenlimit für Eingabe der Autovervollständigung", "Chart new frontiers": "Neue Grenzen erkunden", "Chat": "Chat", - "Chat archived.": "", + "Chat archived.": "Chat archiviert.", "Chat Background Image": "Hintergrundbild des Chats", "Chat Bubble UI": "Sprechblasen-Ansicht", "Chat Completions": "Chat Completions", @@ -823,7 +823,7 @@ "Fade Effect for Streaming Text": "Fade-Effekt für Text-Streaming", "Failed to add file.": "Hinzufügen der Datei fehlgeschlagen.", "Failed to add members": "Mitglieder konnten nicht hinzugefügt werden", - "Failed to archive chat.": "", + "Failed to archive chat.": "Chat konnte nicht archiviert werden.", "Failed to attach file": "Datei konnte nicht hinzugefügt werden", "Failed to clear status": "Status konnte nicht geleert werden", "Failed to connect to {{URL}} OpenAPI tool server": "Verbindung zum OpenAPI-Toolserver {{URL}} fehlgeschlagen", @@ -838,11 +838,11 @@ "Failed to generate title": "Titel konnte nicht generiert werden", "Failed to import models": "Modelle konnten nicht importiert werden", "Failed to load chat preview": "Chat-Vorschau konnte nicht geladen werden", - "Failed to load DOCX file. Please try downloading it instead.": "", + "Failed to load DOCX file. Please try downloading it instead.": "DOCX Datei konnte nicht geladen werden. Versuche die Datei stattdessen herunterzuladen.", "Failed to load Excel/CSV file. Please try downloading it instead.": "Excel/CSV-Datei konnte nicht geladen werden. Bitte versuchen Sie stattdessen, sie herunterzuladen.", "Failed to load file content.": "Dateiinhalt konnte nicht geladen werden.", "Failed to load Interface settings": "Interface Einstellungen konnten nicht geladen werden", - "Failed to load PPTX file. Please try downloading it instead.": "", + "Failed to load PPTX file. Please try downloading it instead.": "PPTX Datei konnte nicht geladen werden. Versuche die Datei stattdessen herunterzuladen.", "Failed to move chat": "Chat konnte nicht verschoben werden", "Failed to process URL: {{url}}": "{{url}} konnte nicht verarbeitet werden", "Failed to read clipboard contents": "Zwischenablage konnte nicht gelesen werden", @@ -1261,7 +1261,7 @@ "More options": "Mehr Optionen", "More Options": "Mehr Optionen", "Move": "Verschieben", - "Moved {{name}}": "", + "Moved {{name}}": "{{name}} verschoben", "My Terminal": "Meine Terminals", "Name": "Name", "Name and ID are required, please fill them out": "Name und ID sind erforderlich, bitte füllen Sie diese aus", @@ -1309,7 +1309,7 @@ "No history available": "Keine History verfügbar", "No HTML, CSS, or JavaScript content found.": "Keine HTML-, CSS- oder JavaScript-Inhalte gefunden.", "No inference engine with management support found": "Keine Inferenz-Engine mit Verwaltungsunterstützung gefunden", - "No kernel": "", + "No kernel": "Kein Kernel", "No knowledge bases found.": "Keine Wissensspeicher gefunden.", "No knowledge found": "Kein Wissen gefunden", "No memories to clear": "Keine Erinnerungen zum Löschen", @@ -1325,7 +1325,7 @@ "No results": "Keine Ergebnisse", "No results found": "Keine Ergebnisse gefunden", "No search query generated": "Keine Suchanfrage generiert", - "No servers detected": "", + "No servers detected": "Keine Server erkannt", "No skills found": "Keine Skills gefunden", "No source available": "Keine Quelle verfügbar", "No sources found": "Keine Quellen gefunden", @@ -1481,7 +1481,7 @@ "Please select at least one user for Direct Message channel.": "Bitte wählen Sie mindestens einen Benutzer für den Direktnachrichten-Kanal aus.", "Please wait until all files are uploaded.": "Bitte warten Sie, bis alle Dateien hochgeladen sind.", "Port": "Port", - "Ports": "", + "Ports": "Ports", "Positive attitude": "Positive Einstellung", "Prefer not to say": "Keine Angabe", "Prefix ID": "Präfix-ID", @@ -1578,7 +1578,7 @@ "Response splitting": "Antwortaufteilung", "Response Watermark": "Antwort-Wasserzeichen", "Responses": "Responses", - "Restart": "", + "Restart": "Neustarten", "Result": "Ergebnis", "RESULT": "ERGEBNIS", "Retrieval": "Abruf", @@ -1591,7 +1591,7 @@ "Role": "Rolle", "RTL": "RTL", "Run": "Ausführen", - "Run All": "", + "Run All": "Alle starten", "Running": "Läuft", "Running...": "Läuft...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "Führt Embedding-Aufgaben parallel aus, um die Verarbeitung zu beschleunigen. Deaktivieren Sie dies, falls Rate-Limits oder Ressourcenprobleme auftreten.", @@ -1782,7 +1782,7 @@ "Start a new conversation": "Neue Unterhaltung beginnen", "Start of the channel": "Beginn des Kanals", "Start Tag": "Start-Tag", - "Starting kernel...": "", + "Starting kernel...": "Kernel starten...", "Status": "Status", "Status cleared successfully": "Status erfolgreich gelöscht", "Status updated successfully": "Status erfolgreich aktualisiert", @@ -2127,8 +2127,8 @@ "You're now logged in.": "Sie sind jetzt angemeldet.", "Your Account": "Ihr Konto", "Your account status is currently pending activation.": "Ihr Kontostatus wartet derzeit auf Aktivierung.", - "Your browser does not support the audio tag.": "", - "Your browser does not support the video tag.": "", + "Your browser does not support the audio tag.": "Dein Browser unterstützt den Audio tag nicht.", + "Your browser does not support the video tag.": "Dein Browser unterstützt den Video tag nicht.", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "Ihr gesamter Beitrag geht direkt an den Plugin-Entwickler; Open WebUI behält keinen Anteil ein. Die gewählte Plattform kann jedoch eigene Gebühren erheben.", "Your message text or inputs": "Ihre Nachrichtentexte oder Eingaben", "Your usage stats have been successfully synced.": "Ihre Nutzungsstatistiken wurden erfolgreich synchronisiert.", From c7d1d1e390a79c6c86d4bfe439fd7de6f5fb060f Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 16:36:20 -0600 Subject: [PATCH 065/114] refac --- src/lib/components/chat/Chat.svelte | 18 ++++++++++++------ .../workspace/Models/ModelEditor.svelte | 6 +++++- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 8ea3edb882..7d5e131d26 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -2009,6 +2009,17 @@ return features; }; + const getStopTokens = () => { + const stop = params?.stop ?? $settings?.params?.stop; + if (!stop) return undefined; + + const tokens = Array.isArray(stop) ? stop : stop.split(',').map((s) => s.trim()); + + return tokens + .filter(Boolean) + .map((token) => decodeURIComponent(JSON.parse(`"${token.replace(/"/g, '\\"')}"`))); + }; + const sendMessageSocket = async (model, _messages, _history, responseMessageId, _chatId) => { const responseMessage = _history.messages[responseMessageId]; const userMessage = _history.messages[responseMessage.parentId]; @@ -2170,12 +2181,7 @@ params: { ...$settings?.params, ...params, - stop: - (params?.stop ?? $settings?.params?.stop ?? undefined) - ? (params?.stop.split(',').map((token) => token.trim()) ?? $settings.params.stop).map( - (str) => decodeURIComponent(JSON.parse('"' + str.replace(/\"/g, '\\"') + '"')) - ) - : undefined + stop: getStopTokens() }, files: (files?.length ?? 0) > 0 ? files : undefined, diff --git a/src/lib/components/workspace/Models/ModelEditor.svelte b/src/lib/components/workspace/Models/ModelEditor.svelte index 4d86113f50..8978c0c00a 100644 --- a/src/lib/components/workspace/Models/ModelEditor.svelte +++ b/src/lib/components/workspace/Models/ModelEditor.svelte @@ -218,7 +218,11 @@ } info.params.system = system.trim() === '' ? null : system; - info.params.stop = params.stop ? params.stop.split(',').filter((s) => s.trim()) : null; + info.params.stop = params.stop + ? (typeof params.stop === 'string' ? params.stop.split(',') : params.stop).filter( + (s) => s.trim() + ) + : null; Object.keys(info.params).forEach((key) => { if (info.params[key] === '' || info.params[key] === null) { delete info.params[key]; From 70a31a9a57bdd0690ac270f31ebd1b46e8fdfa98 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 16:40:14 -0600 Subject: [PATCH 066/114] fix: terminals button ui --- src/lib/components/chat/MessageInput.svelte | 92 +++++++++++---------- 1 file changed, 47 insertions(+), 45 deletions(-) diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index f3108abf25..5d5344592b 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -1803,59 +1803,61 @@ {/if} - {#if (!history?.currentId || history.messages[history.currentId]?.done == true) && ($_user?.role === 'admin' || ($_user?.permissions?.chat?.stt ?? true))} + {#if !history?.currentId || history.messages[history.currentId]?.done == true} {#if ($terminalServers ?? []).length > 0 || ($settings?.terminalServers ?? []).some((s) => s.url)} {/if} - - - - + + + + + + + {/if} {/if} {#if prompt === '' && files.length === 0 && ($_user?.role === 'admin' || ($_user?.permissions?.chat?.call ?? true))} From 044fd1bd15cae06a5c56a321ca79d8362942f66a Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 16:49:26 -0600 Subject: [PATCH 067/114] refac --- src/lib/components/chat/FileNav.svelte | 36 ++++++++++++++++---------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/src/lib/components/chat/FileNav.svelte b/src/lib/components/chat/FileNav.svelte index 707be186ef..81ee750a22 100644 --- a/src/lib/components/chat/FileNav.svelte +++ b/src/lib/components/chat/FileNav.svelte @@ -177,7 +177,8 @@ const config = await getTerminalConfig(terminal.url, terminal.key); terminalEnabled = config?.features?.terminal !== false; - const cwd = await getCwd(terminal.url, terminal.key); + const rawCwd = await getCwd(terminal.url, terminal.key); + const cwd = rawCwd ? normalizePath(rawCwd) : null; const dir = cwd ? (cwd.endsWith('/') ? cwd : cwd + '/') : '/'; savedPath = dir; loadDir(dir); @@ -197,18 +198,22 @@ const isPdf = (path: string) => path.split('.').pop()?.toLowerCase() === 'pdf'; const isOffice = (path: string) => OFFICE_EXTS.has(path.split('.').pop()?.toLowerCase() ?? ''); - const buildBreadcrumbs = (path: string) => - path - .split('/') - .filter(Boolean) - .reduce( - (acc, part) => { - const prev = acc[acc.length - 1]; - acc.push({ label: part, path: `${prev.path}${part}/` }); - return acc; - }, - [{ label: '/', path: '/' }] - ); + /** Normalize Windows backslashes to forward slashes. */ + const normalizePath = (p: string) => p.replace(/\\/g, '/'); + + const buildBreadcrumbs = (path: string) => { + const parts = path.split('/').filter(Boolean); + const isDrive = /^[A-Za-z]:$/.test(parts[0] ?? ''); + const root = isDrive ? { label: parts[0], path: `${parts[0]}/` } : { label: '/', path: '/' }; + return (isDrive ? parts.slice(1) : parts).reduce( + (acc, part) => { + const prev = acc[acc.length - 1]; + acc.push({ label: part, path: `${prev.path}${part}/` }); + return acc; + }, + [root] + ); + }; // ── File preview management ────────────────────────────────────────── const clearFilePreview = () => { @@ -486,6 +491,7 @@ if (!filePath || !selectedTerminal) return; handledDisplayFile = true; showFileNavPath.set(null); + filePath = normalizePath(filePath); const lastSlash = filePath.lastIndexOf('/'); const dir = lastSlash > 0 ? filePath.substring(0, lastSlash + 1) : '/'; @@ -507,6 +513,7 @@ const unsubFileNavDir = showFileNavDir.subscribe(async (filePath) => { if (!filePath || !selectedTerminal) return; showFileNavDir.set(null); + filePath = normalizePath(filePath); const lastSlash = filePath.lastIndexOf('/'); const dir = lastSlash > 0 ? filePath.substring(0, lastSlash + 1) : '/'; @@ -525,7 +532,8 @@ if (!handledDisplayFile) { if (savedPath === '/') { - const cwd = await getCwd(terminal.url, terminal.key); + const rawCwd = await getCwd(terminal.url, terminal.key); + const cwd = rawCwd ? normalizePath(rawCwd) : null; if (cwd) savedPath = cwd.endsWith('/') ? cwd : cwd + '/'; } loadDir(savedPath); From 51a2d2b7011040bb0550ace12aa4d33a66984bbe Mon Sep 17 00:00:00 2001 From: Shirasawa <764798966@qq.com> Date: Sun, 8 Mar 2026 06:51:04 +0800 Subject: [PATCH 068/114] i18n: improve Chinese translation (#22351) --- src/lib/i18n/locales/zh-CN/translation.json | 26 +++++++++---------- src/lib/i18n/locales/zh-TW/translation.json | 28 ++++++++++----------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json index 9fac1d692e..744785c78a 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -282,7 +282,7 @@ "Character limit for autocomplete generation input": "输入框内容自动补全输入的字符限制", "Chart new frontiers": "开辟前沿", "Chat": "对话", - "Chat archived.": "", + "Chat archived.": "对话已归档。", "Chat Background Image": "对话背景图片", "Chat Bubble UI": "以聊天气泡的形式显示对话内容", "Chat Completions": "Chat Completions", @@ -823,7 +823,7 @@ "Fade Effect for Streaming Text": "流式输出内容时启用动态渐显效果", "Failed to add file.": "添加文件失败", "Failed to add members": "添加成员失败", - "Failed to archive chat.": "", + "Failed to archive chat.": "对话归档失败。", "Failed to attach file": "文件上传失败", "Failed to clear status": "清除状态失败", "Failed to connect to {{URL}} OpenAPI tool server": "连接到 {{URL}} OpenAPI 工具服务器失败", @@ -838,11 +838,11 @@ "Failed to generate title": "生成标题失败", "Failed to import models": "导入模型配置失败", "Failed to load chat preview": "对话预览加载失败", - "Failed to load DOCX file. Please try downloading it instead.": "", + "Failed to load DOCX file. Please try downloading it instead.": "无法加载 DOCX 文件,请尝试下载后查看。", "Failed to load Excel/CSV file. Please try downloading it instead.": "加载 Excel/CSV 文件失败,请尝试直接下载文件。", "Failed to load file content.": "文件内容加载失败", "Failed to load Interface settings": "“界面设置”数据加载失败", - "Failed to load PPTX file. Please try downloading it instead.": "", + "Failed to load PPTX file. Please try downloading it instead.": "无法加载 PPTX 文件,请尝试下载后查看。", "Failed to move chat": "移动对话失败", "Failed to process URL: {{url}}": "处理链接失败: {{url}}", "Failed to read clipboard contents": "读取剪贴板内容失败", @@ -1261,7 +1261,7 @@ "More options": "更多选项", "More Options": "更多选项", "Move": "移动", - "Moved {{name}}": "", + "Moved {{name}}": "移动“{{name}}”成功", "My Terminal": "我的终端", "Name": "名称", "Name and ID are required, please fill them out": "名称和 ID 是必填项,请填写。", @@ -1309,7 +1309,7 @@ "No history available": "暂无历史记录", "No HTML, CSS, or JavaScript content found.": "未找到 HTML、CSS 或 JavaScript 内容。", "No inference engine with management support found": "未找到支持管理的推理引擎", - "No kernel": "", + "No kernel": "未找到内核", "No knowledge bases found.": "未找到知识库", "No knowledge found": "未找到知识", "No memories to clear": "记忆为空,无须清理", @@ -1325,7 +1325,7 @@ "No results": "未找到结果", "No results found": "未找到结果", "No search query generated": "未生成搜索查询", - "No servers detected": "", + "No servers detected": "未检测到任何服务器", "No skills found": "没有找到技能", "No source available": "没有可用引用来源", "No sources found": "未找到任何引用来源", @@ -1481,7 +1481,7 @@ "Please select at least one user for Direct Message channel.": "请至少选择一个用户以创建私聊频道。", "Please wait until all files are uploaded.": "请等待所有文件上传完毕。", "Port": "端口", - "Ports": "", + "Ports": "端口", "Positive attitude": "态度积极", "Prefer not to say": "暂不透露", "Prefix ID": "模型 ID 前缀", @@ -1578,7 +1578,7 @@ "Response splitting": "拆分回答", "Response Watermark": "复制时添加水印", "Responses": "Responses", - "Restart": "", + "Restart": "重启", "Result": "结果", "RESULT": "结果", "Retrieval": "检索", @@ -1590,7 +1590,7 @@ "Role": "角色", "RTL": "从右至左", "Run": "运行", - "Run All": "", + "Run All": "运行全部", "Running": "运行中", "Running...": "运行中...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "并行运行嵌入任务以加快处理速度。如果遇到限速问题,请关闭此选项。", @@ -1781,7 +1781,7 @@ "Start a new conversation": "开始新对话", "Start of the channel": "频道起点", "Start Tag": "起始标签", - "Starting kernel...": "", + "Starting kernel...": "正在启动内核...", "Status": "状态", "Status cleared successfully": "状态已清除", "Status updated successfully": "状态已更新", @@ -2126,8 +2126,8 @@ "You're now logged in.": "已登录。", "Your Account": "您的账号", "Your account status is currently pending activation.": "您的账号当前状态为待激活", - "Your browser does not support the audio tag.": "", - "Your browser does not support the video tag.": "", + "Your browser does not support the audio tag.": "您的浏览器不支持播放音频。", + "Your browser does not support the video tag.": "您的浏览器不支持播放视频。", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "您的全部捐款将直接给到插件开发者,Open WebUI 不会收取任何分成。但众筹平台可能会有服务费。", "Your message text or inputs": "您的消息文本或输入", "Your usage stats have been successfully synced.": "已成功同步您的使用统计数据。", diff --git a/src/lib/i18n/locales/zh-TW/translation.json b/src/lib/i18n/locales/zh-TW/translation.json index 996b4d48da..eba4340e1b 100644 --- a/src/lib/i18n/locales/zh-TW/translation.json +++ b/src/lib/i18n/locales/zh-TW/translation.json @@ -282,7 +282,7 @@ "Character limit for autocomplete generation input": "自動完成產生輸入的字元限制", "Chart new frontiers": "探索新領域", "Chat": "對話", - "Chat archived.": "", + "Chat archived.": "對話已封存。", "Chat Background Image": "對話背景圖片", "Chat Bubble UI": "對話氣泡介面", "Chat Completions": "對話續寫", @@ -823,7 +823,7 @@ "Fade Effect for Streaming Text": "串流文字淡入效果", "Failed to add file.": "新增檔案失敗。", "Failed to add members": "新增成員失敗", - "Failed to archive chat.": "", + "Failed to archive chat.": "封存對話失敗。", "Failed to attach file": "檔案上傳失敗", "Failed to clear status": "清除狀態失敗", "Failed to connect to {{URL}} OpenAPI tool server": "無法連線至 {{URL}} OpenAPI 工具伺服器", @@ -838,11 +838,11 @@ "Failed to generate title": "產生標題失敗", "Failed to import models": "匯入模型失敗", "Failed to load chat preview": "對話預覽載入失敗", - "Failed to load DOCX file. Please try downloading it instead.": "", + "Failed to load DOCX file. Please try downloading it instead.": "無法載入 DOCX 檔案,請改為下載後再開啟。", "Failed to load Excel/CSV file. Please try downloading it instead.": "無法載入 Excel/CSV 檔案。請嘗試直接下載檔案。", "Failed to load file content.": "載入檔案內容失敗。", "Failed to load Interface settings": "「介面設定」資料載入失敗", - "Failed to load PPTX file. Please try downloading it instead.": "", + "Failed to load PPTX file. Please try downloading it instead.": "無法載入 PPTX 檔案,請改為下載後再開啟。", "Failed to move chat": "移動對話失敗", "Failed to process URL: {{url}}": "處理連結失敗:{{url}}", "Failed to read clipboard contents": "讀取剪貼簿內容失敗", @@ -1261,7 +1261,7 @@ "More options": "更多選項", "More Options": "更多選項", "Move": "移動", - "Moved {{name}}": "", + "Moved {{name}}": "已移動 {{name}}", "My Terminal": "我的終端", "Name": "名稱", "Name and ID are required, please fill them out": "名稱和 ID 為必填項目,請填寫", @@ -1309,7 +1309,7 @@ "No history available": "暫無歷史紀錄", "No HTML, CSS, or JavaScript content found.": "未找到 HTML、CSS 或 JavaScript 內容。", "No inference engine with management support found": "未找到支援管理功能的推理引擎", - "No kernel": "", + "No kernel": "無核心", "No knowledge bases found.": "未找到知識庫", "No knowledge found": "未找到知識", "No memories to clear": "沒有記憶可清除", @@ -1325,7 +1325,7 @@ "No results": "沒有結果", "No results found": "未找到任何結果", "No search query generated": "未產生搜尋查詢", - "No servers detected": "", + "No servers detected": "未偵測到伺服器", "No skills found": "找不到任何技能", "No source available": "無可用來源", "No sources found": "未找到任何來源", @@ -1481,7 +1481,7 @@ "Please select at least one user for Direct Message channel.": "請至少選擇一位使用者以建立直接訊息頻道。", "Please wait until all files are uploaded.": "請等待所有檔案上傳完畢。", "Port": "連接埠", - "Ports": "", + "Ports": "連接埠", "Positive attitude": "積極的態度", "Prefer not to say": "不想透露", "Prefix ID": "前置 ID", @@ -1577,8 +1577,8 @@ "Response notifications cannot be activated as the website permissions have been denied. Please visit your browser settings to grant the necessary access.": "無法啟用回應通知,因為網站權限已遭拒。請前往瀏覽器設定以授予必要存取權限。", "Response splitting": "回應分割", "Response Watermark": "回應浮水印", - "Responses": "回答", - "Restart": "", + "Responses": "Responses", + "Restart": "重新啟動", "Result": "結果", "RESULT": "結果", "Retrieval": "檢索", @@ -1590,7 +1590,7 @@ "Role": "角色", "RTL": "從右到左", "Run": "執行", - "Run All": "", + "Run All": "全部執行", "Running": "正在執行", "Running...": "正在執行...", "Runs embedding tasks concurrently to speed up processing. Turn off if rate limits become an issue.": "同時執行嵌入任務以加快處理速度。如果遇到速率限制問題,請關閉此功能。", @@ -1781,7 +1781,7 @@ "Start a new conversation": "開始新對話", "Start of the channel": "頻道起點", "Start Tag": "起始標籤", - "Starting kernel...": "", + "Starting kernel...": "正在啟動核心…", "Status": "狀態", "Status cleared successfully": "狀態已清除", "Status updated successfully": "狀態已更新", @@ -2126,8 +2126,8 @@ "You're now logged in.": "您已登入。", "Your Account": "您的帳號", "Your account status is currently pending activation.": "您的帳號目前正在等待啟用。", - "Your browser does not support the audio tag.": "", - "Your browser does not support the video tag.": "", + "Your browser does not support the audio tag.": "您的瀏覽器不支援音訊播放。", + "Your browser does not support the video tag.": "您的瀏覽器不支援影片播放。", "Your entire contribution will go directly to the plugin developer; Open WebUI does not take any percentage. However, the chosen funding platform might have its own fees.": "您的所有貢獻將會直接交給外掛開發者;Open WebUI 不會收取任何抽成。然而,所選擇的贊助平臺可能有其自身的費用。", "Your message text or inputs": "您的訊息文字或輸入", "Your usage stats have been successfully synced.": "已成功同步您的使用統計資料。", From 5eb9b58488b42ab8dcfdcc003ecdc964b7f2e866 Mon Sep 17 00:00:00 2001 From: Shirasawa <764798966@qq.com> Date: Sun, 8 Mar 2026 06:51:56 +0800 Subject: [PATCH 069/114] feat: Avoid overview profile image squashed (#22261) --- src/lib/components/chat/Overview/Node.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/components/chat/Overview/Node.svelte b/src/lib/components/chat/Overview/Node.svelte index 0bf36bb918..17c5e51e0c 100644 --- a/src/lib/components/chat/Overview/Node.svelte +++ b/src/lib/components/chat/Overview/Node.svelte @@ -25,7 +25,7 @@
@@ -45,7 +45,7 @@
From 7820a311baee785abe2aaf6aef1304c6305ab3fe Mon Sep 17 00:00:00 2001 From: Shirasawa <764798966@qq.com> Date: Sun, 8 Mar 2026 06:53:28 +0800 Subject: [PATCH 070/114] fix: prevent message queue from overflowing screen (#22176) --- src/lib/components/chat/MessageInput.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index 5d5344592b..2cbd0d9557 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -1175,7 +1175,7 @@ {#if messageQueue.length > 0}
{#each messageQueue as queuedMessage (queuedMessage.id)} Date: Sat, 7 Mar 2026 16:59:06 -0600 Subject: [PATCH 071/114] refac --- backend/open_webui/utils/models.py | 97 ++++++++++++++---------------- 1 file changed, 46 insertions(+), 51 deletions(-) diff --git a/backend/open_webui/utils/models.py b/backend/open_webui/utils/models.py index 564100b14f..e67fa62295 100644 --- a/backend/open_webui/utils/models.py +++ b/backend/open_webui/utils/models.py @@ -149,63 +149,58 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) ] custom_models = Models.get_all_models() + + # Single O(1) lookup: Ollama base names first, then exact IDs (exact wins). + model_lookup = {} + for model in models: + if model.get("owned_by") == "ollama": + model_lookup.setdefault(model["id"].split(":")[0], model) + model_lookup[model["id"]] = model + + existing_ids = {m["id"] for m in models} + for custom_model in custom_models: if custom_model.base_model_id is None: - # Applied directly to a base model - for model in models: - if custom_model.id == model["id"] or ( - model.get("owned_by") == "ollama" - and custom_model.id - == model["id"].split(":")[ - 0 - ] # Ollama may return model ids in different formats (e.g., 'llama3' vs. 'llama3:7b') - ): - if custom_model.is_active: - model["name"] = custom_model.name - model["info"] = custom_model.model_dump() - - # Set action_ids and filter_ids - action_ids = [] - filter_ids = [] - - if "info" in model: - if "meta" in model["info"]: - action_ids.extend( - model["info"]["meta"].get("actionIds", []) - ) - filter_ids.extend( - model["info"]["meta"].get("filterIds", []) - ) - - if "params" in model["info"]: - # Remove params to avoid exposing sensitive info - del model["info"]["params"] - - model["action_ids"] = action_ids - model["filter_ids"] = filter_ids - else: - models.remove(model) - - elif custom_model.is_active and ( - custom_model.id not in [model["id"] for model in models] - ): - # Custom model based on a base model + model = model_lookup.get(custom_model.id) + + if model: + if custom_model.is_active: + model["name"] = custom_model.name + model["info"] = custom_model.model_dump() + + action_ids = [] + filter_ids = [] + + if "info" in model: + if "meta" in model["info"]: + action_ids.extend( + model["info"]["meta"].get("actionIds", []) + ) + filter_ids.extend( + model["info"]["meta"].get("filterIds", []) + ) + + if "params" in model["info"]: + del model["info"]["params"] + + model["action_ids"] = action_ids + model["filter_ids"] = filter_ids + else: + models.remove(model) + + elif custom_model.is_active and custom_model.id not in existing_ids: owned_by = "openai" connection_type = None - pipe = None - for m in models: - if ( - custom_model.base_model_id == m["id"] - or custom_model.base_model_id == m["id"].split(":")[0] - ): - owned_by = m.get("owned_by", "unknown") - if "pipe" in m: - pipe = m["pipe"] - - connection_type = m.get("connection_type", None) - break + base_model = model_lookup.get(custom_model.base_model_id) + if base_model is None: + base_model = model_lookup.get(custom_model.base_model_id.split(":")[0]) + if base_model: + owned_by = base_model.get("owned_by", "unknown") + if "pipe" in base_model: + pipe = base_model["pipe"] + connection_type = base_model.get("connection_type", None) model = { "id": f"{custom_model.id}", From 03c6caac1fc8625f85cf1164f5a977be8005c1bc Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 17:02:02 -0600 Subject: [PATCH 072/114] refac --- backend/open_webui/utils/models.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/backend/open_webui/utils/models.py b/backend/open_webui/utils/models.py index e67fa62295..96d1e363f1 100644 --- a/backend/open_webui/utils/models.py +++ b/backend/open_webui/utils/models.py @@ -151,17 +151,17 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) custom_models = Models.get_all_models() # Single O(1) lookup: Ollama base names first, then exact IDs (exact wins). - model_lookup = {} + base_model_lookup = {} for model in models: if model.get("owned_by") == "ollama": - model_lookup.setdefault(model["id"].split(":")[0], model) - model_lookup[model["id"]] = model + base_model_lookup.setdefault(model["id"].split(":")[0], model) + base_model_lookup[model["id"]] = model existing_ids = {m["id"] for m in models} for custom_model in custom_models: if custom_model.base_model_id is None: - model = model_lookup.get(custom_model.id) + model = base_model_lookup.get(custom_model.id) if model: if custom_model.is_active: @@ -188,14 +188,17 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) else: models.remove(model) - elif custom_model.is_active and custom_model.id not in existing_ids: + elif custom_model.is_active: + if custom_model.id in existing_ids: + continue + owned_by = "openai" connection_type = None pipe = None - base_model = model_lookup.get(custom_model.base_model_id) + base_model = base_model_lookup.get(custom_model.base_model_id) if base_model is None: - base_model = model_lookup.get(custom_model.base_model_id.split(":")[0]) + base_model = base_model_lookup.get(custom_model.base_model_id.split(":")[0]) if base_model: owned_by = base_model.get("owned_by", "unknown") if "pipe" in base_model: From e6b00a8905f0f855a1745b7a94d264ae6f80ff7f Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 17:03:23 -0600 Subject: [PATCH 073/114] refac --- backend/open_webui/utils/models.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/open_webui/utils/models.py b/backend/open_webui/utils/models.py index 96d1e363f1..cb5865d88c 100644 --- a/backend/open_webui/utils/models.py +++ b/backend/open_webui/utils/models.py @@ -161,6 +161,7 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) for custom_model in custom_models: if custom_model.base_model_id is None: + # Override applied directly to a base model (shares the same ID) model = base_model_lookup.get(custom_model.id) if model: From 626fcff417afba642f4f71e0498267a21435c524 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 17:06:30 -0600 Subject: [PATCH 074/114] refac --- src/lib/components/chat/Chat.svelte | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 7d5e131d26..b510dd0b65 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -934,15 +934,19 @@ } }; - $: if (history) { - cancelAnimationFrame(contentsRAF); - contentsRAF = requestAnimationFrame(() => { - getContents(); - contentsRAF = null; - }); - } else { - artifactContents.set([]); - } + const onHistoryChange = (history) => { + if (history) { + cancelAnimationFrame(contentsRAF); + contentsRAF = requestAnimationFrame(() => { + getContents(); + contentsRAF = null; + }); + } else { + artifactContents.set([]); + } + }; + + $: onHistoryChange(history); const getContents = () => { const messages = history ? createMessagesList(history, history.currentId) : []; From 42ecdb5407bec6d0718bc749b3e84e51f3815c21 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 17:11:44 -0600 Subject: [PATCH 075/114] refac --- src/lib/components/chat/Artifacts.svelte | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/lib/components/chat/Artifacts.svelte b/src/lib/components/chat/Artifacts.svelte index 4d2c8af816..7e0bdf2060 100644 --- a/src/lib/components/chat/Artifacts.svelte +++ b/src/lib/components/chat/Artifacts.svelte @@ -98,15 +98,18 @@ }); const unsubscribeArtifactContents = artifactContents.subscribe((value) => { - contents = value; - console.log('Artifact contents updated:', contents); + const newContents = value ?? []; + console.log('Artifact contents updated:', newContents); - if (contents.length === 0) { + if (newContents.length === 0) { showControls.set(false); showArtifacts.set(false); + selectedContentIdx = 0; + } else if (newContents.length > contents.length) { + selectedContentIdx = newContents.length - 1; } - selectedContentIdx = contents ? contents.length - 1 : 0; + contents = newContents; }); return () => { From 2108f420eaafe936742e97731e8647c105ea4900 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sun, 8 Mar 2026 00:12:22 +0100 Subject: [PATCH 076/114] chore: dep bump (#22305) * chore: dep bump * revert: Brotli dependency bump (1.2.0 -> 1.1.0) --- backend/requirements-min.txt | 18 ++++---- backend/requirements.txt | 79 ++++++++++++++++++------------------ pyproject.toml | 56 ++++++++++++------------- 3 files changed, 76 insertions(+), 77 deletions(-) diff --git a/backend/requirements-min.txt b/backend/requirements-min.txt index 6d28dc16d9..13bd199f08 100644 --- a/backend/requirements-min.txt +++ b/backend/requirements-min.txt @@ -1,8 +1,8 @@ # Minimal requirements for backend to run # WIP: use this as a reference to build a minimal docker image -fastapi==0.128.5 -uvicorn[standard]==0.40.0 +fastapi==0.135.1 +uvicorn[standard]==0.41.0 pydantic==2.12.5 python-multipart==0.0.22 itsdangerous==2.2.0 @@ -13,7 +13,7 @@ cryptography bcrypt==5.0.0 argon2-cffi==25.1.0 PyJWT[crypto]==2.11.0 -authlib==1.6.7 +authlib==1.6.9 requests==2.32.5 aiohttp==3.13.2 # do not update to 3.13.3 - broken @@ -25,12 +25,12 @@ Brotli==1.1.0 httpx[socks,http2,zstd,cli,brotli]==0.28.1 starsessions[redis]==2.2.1 -sqlalchemy==2.0.46 -alembic==1.18.3 +sqlalchemy==2.0.48 +alembic==1.18.4 peewee==3.19.0 peewee-migrate==1.14.3 -pycrdt==0.12.46 +pycrdt==0.12.47 redis APScheduler==3.11.2 @@ -42,14 +42,14 @@ asgiref==3.11.1 mcp==1.26.0 openai -langchain==1.2.9 +langchain==1.2.10 langchain-community==0.4.1 langchain-classic==1.0.1 -langchain-text-splitters==1.1.0 +langchain-text-splitters==1.1.1 fake-useragent==2.2.0 -chromadb==1.4.1 +chromadb==1.5.2 black==26.1.0 pydub chardet==5.2.0 diff --git a/backend/requirements.txt b/backend/requirements.txt index 06fb3b8194..3d3a54965d 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -1,5 +1,5 @@ -fastapi==0.128.5 -uvicorn[standard]==0.40.0 +fastapi==0.135.1 +uvicorn[standard]==0.41.0 pydantic==2.12.5 python-multipart==0.0.22 itsdangerous==2.2.0 @@ -10,7 +10,7 @@ cryptography bcrypt==5.0.0 argon2-cffi==25.1.0 PyJWT[crypto]==2.11.0 -authlib==1.6.7 +authlib==1.6.9 requests==2.32.5 aiohttp==3.13.2 # do not update to 3.13.3 - broken @@ -23,17 +23,17 @@ httpx[socks,http2,zstd,cli,brotli]==0.28.1 starsessions[redis]==2.2.1 python-mimeparse==2.0.0 -sqlalchemy==2.0.46 -alembic==1.18.3 +sqlalchemy==2.0.48 +alembic==1.18.4 peewee==3.19.0 peewee-migrate==1.14.3 -pycrdt==0.12.46 +pycrdt==0.12.47 redis APScheduler==3.11.2 RestrictedPython==8.1 -pytz==2025.2 +pytz==2026.1.post1 loguru==0.7.3 asgiref==3.11.1 @@ -44,38 +44,38 @@ mcp==1.26.0 openai anthropic -google-genai==1.62.0 +google-genai==1.66.0 -langchain==1.2.9 +langchain==1.2.10 langchain-community==0.4.1 langchain-classic==1.0.1 -langchain-text-splitters==1.1.0 +langchain-text-splitters==1.1.1 fake-useragent==2.2.0 -chromadb==1.4.1 -weaviate-client==4.19.2 +chromadb==1.5.2 +weaviate-client==4.20.3 opensearch-py==3.1.0 -transformers==5.1.0 -sentence-transformers==5.2.2 +transformers==5.3.0 +sentence-transformers==5.2.3 accelerate pyarrow==20.0.0 # fix: pin pyarrow version to 20 for rpi compatibility #15897 einops==0.8.2 ftfy==6.3.1 chardet==5.2.0 -pypdf==6.7.0 -fpdf2==2.8.5 -pymdown-extensions==10.20.1 +pypdf==6.7.5 +fpdf2==2.8.7 +pymdown-extensions==10.21 docx2txt==0.9 python-pptx==1.0.2 unstructured==0.18.31 msoffcrypto-tool==6.0.0 -nltk==3.9.2 -Markdown==3.10.1 +nltk==3.9.3 +Markdown==3.10.2 beautifulsoup4 pypandoc==1.16.2 -pandas==3.0.0 +pandas==3.0.1 openpyxl==3.1.5 pyxlsb==1.0.10 xlrd==2.0.2 @@ -84,12 +84,12 @@ psutil sentencepiece soundfile==0.13.1 -pillow==12.1.0 +pillow==12.1.1 opencv-python-headless==4.13.0.92 rapidocr-onnxruntime==1.4.4 rank-bm25==0.2.2 -onnxruntime==1.24.1 +onnxruntime==1.24.3 faster-whisper==1.2.1 black==26.1.0 @@ -97,10 +97,10 @@ youtube-transcript-api==1.2.4 pytube==15.0.0 pydub -ddgs==9.10.0 +ddgs==9.11.2 azure-ai-documentintelligence==1.0.2 -azure-identity==1.25.1 +azure-identity==1.25.2 azure-storage-blob==12.28.0 azure-search-documents==11.6.0 @@ -118,10 +118,10 @@ psycopg2-binary==2.9.11 pgvector==0.4.2 PyMySQL==1.1.2 -boto3==1.42.44 +boto3==1.42.62 -pymilvus==2.6.8 -qdrant-client==1.16.2 +pymilvus==2.6.9 +qdrant-client==1.17.0 playwright==1.58.0 # Caution: version must match docker-compose.playwright.yaml - Update the docker-compose.yaml if necessary elasticsearch==9.3.0 pinecone==6.0.2 @@ -141,18 +141,17 @@ pytest-docker~=3.2.5 ldap3==2.9.1 ## Firecrawl -firecrawl-py==4.14.0 +firecrawl-py==4.18.0 ## Trace -opentelemetry-api==1.39.1 -opentelemetry-sdk==1.39.1 -opentelemetry-exporter-otlp==1.39.1 -opentelemetry-instrumentation==0.60b1 -opentelemetry-instrumentation-fastapi==0.60b1 -opentelemetry-instrumentation-sqlalchemy==0.60b1 -opentelemetry-instrumentation-redis==0.60b1 -opentelemetry-instrumentation-requests==0.60b1 -opentelemetry-instrumentation-logging==0.60b1 -opentelemetry-instrumentation-httpx==0.60b1 -opentelemetry-instrumentation-aiohttp-client==0.60b1 -opentelemetry-instrumentation-system-metrics==0.60b1 +opentelemetry-api==1.40.0 +opentelemetry-sdk==1.40.0 +opentelemetry-exporter-otlp==1.40.0 +opentelemetry-instrumentation==0.61b0 +opentelemetry-instrumentation-fastapi==0.61b0 +opentelemetry-instrumentation-sqlalchemy==0.61b0 +opentelemetry-instrumentation-redis==0.61b0 +opentelemetry-instrumentation-requests==0.61b0 +opentelemetry-instrumentation-logging==0.61b0 +opentelemetry-instrumentation-httpx==0.61b0 +opentelemetry-instrumentation-aiohttp-client==0.61b0 diff --git a/pyproject.toml b/pyproject.toml index d240449dff..251240ac48 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,8 +6,8 @@ authors = [ ] license = { file = "LICENSE" } dependencies = [ - "fastapi==0.128.5", - "uvicorn[standard]==0.40.0", + "fastapi==0.135.1", + "uvicorn[standard]==0.41.0", "pydantic==2.12.5", "python-multipart==0.0.22", "itsdangerous==2.2.0", @@ -18,7 +18,7 @@ dependencies = [ "bcrypt==5.0.0", "argon2-cffi==25.1.0", "PyJWT[crypto]==2.11.0", - "authlib==1.6.7", + "authlib==1.6.9", "requests==2.32.5", "aiohttp==3.13.2", # do not update to 3.13.3 - broken @@ -31,15 +31,15 @@ dependencies = [ "starsessions[redis]==2.2.1", "python-mimeparse==2.0.0", - "sqlalchemy==2.0.46", - "alembic==1.18.3", + "sqlalchemy==2.0.48", + "alembic==1.18.4", "peewee==3.19.0", "peewee-migrate==1.14.3", - "pycrdt==0.12.46", + "pycrdt==0.12.47", "redis", - "pytz==2025.2", + "pytz==2026.1.post1", "APScheduler==3.11.2", "RestrictedPython==8.1", @@ -51,38 +51,38 @@ dependencies = [ "openai", "anthropic", - "google-genai==1.62.0", + "google-genai==1.66.0", - "langchain==1.2.9", + "langchain==1.2.10", "langchain-community==0.4.1", "langchain-classic==1.0.1", - "langchain-text-splitters==1.1.0", + "langchain-text-splitters==1.1.1", "fake-useragent==2.2.0", - "chromadb==1.4.1", + "chromadb==1.5.2", "opensearch-py==3.1.0", "PyMySQL==1.1.2", - "boto3==1.42.44", + "boto3==1.42.62", - "transformers==5.1.0", - "sentence-transformers==5.2.2", + "transformers==5.3.0", + "sentence-transformers==5.2.3", "accelerate", "pyarrow==20.0.0", # fix: pin pyarrow version to 20 for rpi compatibility #15897 "einops==0.8.2", "ftfy==6.3.1", "chardet==5.2.0", - "pypdf==6.7.0", - "fpdf2==2.8.5", - "pymdown-extensions==10.20.1", + "pypdf==6.7.5", + "fpdf2==2.8.7", + "pymdown-extensions==10.21", "docx2txt==0.9", "python-pptx==1.0.2", "unstructured==0.18.31", "msoffcrypto-tool==6.0.0", - "nltk==3.9.2", - "Markdown==3.10.1", + "nltk==3.9.3", + "Markdown==3.10.2", "pypandoc==1.16.2", - "pandas==3.0.0", + "pandas==3.0.1", "openpyxl==3.1.5", "pyxlsb==1.0.10", "xlrd==2.0.2", @@ -92,12 +92,12 @@ dependencies = [ "soundfile==0.13.1", "azure-ai-documentintelligence==1.0.2", - "pillow==12.1.0", + "pillow==12.1.1", "opencv-python-headless==4.13.0.92", "rapidocr-onnxruntime==1.4.4", "rank-bm25==0.2.2", - "onnxruntime==1.24.1", + "onnxruntime==1.24.3", "faster-whisper==1.2.1", "black==26.1.0", @@ -105,7 +105,7 @@ dependencies = [ "pytube==15.0.0", "pydub", - "ddgs==9.10.0", + "ddgs==9.11.2", "google-api-python-client", "google-auth-httplib2", @@ -114,7 +114,7 @@ dependencies = [ "googleapis-common-protos==1.72.0", "google-cloud-storage==3.9.0", - "azure-identity==1.25.1", + "azure-identity==1.25.2", "azure-storage-blob==12.28.0", "ldap3==2.9.1", @@ -150,15 +150,15 @@ all = [ "playwright==1.58.0", # Caution: version must match docker-compose.playwright.yaml - Update the docker-compose.yaml if necessary "elasticsearch==9.3.0", - "qdrant-client==1.16.2", + "qdrant-client==1.17.0", - "weaviate-client==4.19.2", - "pymilvus==2.6.8", + "weaviate-client==4.20.3", + "pymilvus==2.6.9", "pinecone==6.0.2", "oracledb==3.4.2", "colbert-ai==0.2.22", - "firecrawl-py==4.14.0", + "firecrawl-py==4.18.0", "azure-search-documents==11.6.0", ] From d4faa5a5eafe4159dc46aa1d19a7477401e5e7e9 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 17:13:19 -0600 Subject: [PATCH 077/114] refac --- backend/open_webui/tools/builtin.py | 8 ++++++-- backend/open_webui/utils/middleware.py | 11 +++++++---- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/backend/open_webui/tools/builtin.py b/backend/open_webui/tools/builtin.py index 7427592380..fe20555f9d 100644 --- a/backend/open_webui/tools/builtin.py +++ b/backend/open_webui/tools/builtin.py @@ -249,11 +249,13 @@ async def generate_image( # Persist files to DB if chat context is available if __chat_id__ and __message_id__ and images: - image_files = Chats.add_message_files_by_id_and_message_id( + db_files = Chats.add_message_files_by_id_and_message_id( __chat_id__, __message_id__, image_files, ) + if db_files is not None: + image_files = db_files # Emit the images to the UI if event emitter is available if __event_emitter__ and image_files: @@ -314,11 +316,13 @@ async def edit_image( # Persist files to DB if chat context is available if __chat_id__ and __message_id__ and images: - image_files = Chats.add_message_files_by_id_and_message_id( + db_files = Chats.add_message_files_by_id_and_message_id( __chat_id__, __message_id__, image_files, ) + if db_files is not None: + image_files = db_files # Emit the images to the UI if event emitter is available if __event_emitter__ and image_files: diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 27323742a4..f3d5d6821c 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -3777,14 +3777,17 @@ async def flush_pending_delta_data(threshold: int = 0): delta.get("images", []), request, metadata, user ) if image_urls: + image_file_list = [ + {"type": "image", "url": url} + for url in image_urls + ] message_files = Chats.add_message_files_by_id_and_message_id( metadata["chat_id"], metadata["message_id"], - [ - {"type": "image", "url": url} - for url in image_urls - ], + image_file_list, ) + if message_files is None: + message_files = image_file_list await event_emitter( { From dfa25111993c9e26e8ec7ed40214d13eb3887c1e Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sun, 8 Mar 2026 00:17:36 +0100 Subject: [PATCH 078/114] fix: persist token usage data for non-streaming chat responses (#22166) The non-streaming response handler was saving assistant messages without their usage/token data. While the streaming handler correctly extracted and saved usage information, the non-streaming path discarded it entirely. This caused assistant messages from non-streaming completions to have NULL usage in the chat_message table, making them invisible to the analytics token aggregation queries and contributing to the '0 tokens' display in Admin Panel Analytics. Extract and normalize the usage data from the API response and include it in the database upsert, matching the pattern already used by the streaming handler. --- backend/open_webui/utils/middleware.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index f3d5d6821c..e5e75652a8 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -3093,6 +3093,9 @@ async def non_streaming_chat_response_handler(response, ctx): ) # Save message in the database + raw_usage = response_data.get("usage", {}) or {} + usage = normalize_usage(raw_usage) if raw_usage else None + Chats.upsert_message_to_chat_by_id_and_message_id( metadata["chat_id"], metadata["message_id"], @@ -3100,6 +3103,7 @@ async def non_streaming_chat_response_handler(response, ctx): "role": "assistant", "content": content, "output": response_output, + **({"usage": usage} if usage else {}), }, ) From b04de83c20ac7dab4bf9c689e1ffc3fe22238b30 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 17:18:46 -0600 Subject: [PATCH 079/114] refac --- backend/open_webui/utils/middleware.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index e5e75652a8..b5cf97d713 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -3093,8 +3093,7 @@ async def non_streaming_chat_response_handler(response, ctx): ) # Save message in the database - raw_usage = response_data.get("usage", {}) or {} - usage = normalize_usage(raw_usage) if raw_usage else None + usage = normalize_usage(response_data.get("usage", {}) or {}) Chats.upsert_message_to_chat_by_id_and_message_id( metadata["chat_id"], @@ -4468,7 +4467,8 @@ async def flush_pending_delta_data(threshold: int = 0): code = sanitize_code(code) if CODE_INTERPRETER_BLOCKED_MODULES: - blocking_code = textwrap.dedent(f""" + blocking_code = textwrap.dedent( + f""" import builtins BLOCKED_MODULES = {CODE_INTERPRETER_BLOCKED_MODULES} @@ -4484,7 +4484,8 @@ def restricted_import(name, globals=None, locals=None, fromlist=(), level=0): return _real_import(name, globals, locals, fromlist, level) builtins.__import__ = restricted_import - """) + """ + ) code = blocking_code + "\n" + code if ( From 7cdff6b1e25692a27cc1c2a1896cb64f3b6071aa Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 17:24:17 -0600 Subject: [PATCH 080/114] refac --- backend/open_webui/utils/middleware.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index b5cf97d713..1f2718ae7f 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -173,6 +173,9 @@ def get_citation_source_from_tool_result( Returns a list of sources (usually one, but query_knowledge_files may return multiple). """ + _EXPECTS_LIST = {"search_web", "query_knowledge_files"} + _EXPECTS_DICT = {"view_knowledge_file"} + try: try: tool_result = json.loads(tool_result) @@ -181,6 +184,12 @@ def get_citation_source_from_tool_result( if isinstance(tool_result, dict) and "error" in tool_result: return [] + # Validate tool_result type based on what the branch expects + if tool_name in _EXPECTS_LIST and not isinstance(tool_result, list): + return [] + elif tool_name in _EXPECTS_DICT and not isinstance(tool_result, dict): + return [] + if tool_name == "search_web": # Parse JSON array: [{"title": "...", "link": "...", "snippet": "..."}] results = tool_result From bc5d519c4f7265dac195d14047de8d08f9ece370 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 17:29:24 -0600 Subject: [PATCH 081/114] refac --- backend/open_webui/utils/tools.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/backend/open_webui/utils/tools.py b/backend/open_webui/utils/tools.py index 2c4b983bd8..7c55429072 100644 --- a/backend/open_webui/utils/tools.py +++ b/backend/open_webui/utils/tools.py @@ -1186,7 +1186,7 @@ async def get_tool_servers_data(servers: List[Dict[str, Any]]) -> List[Dict[str, { "id": str(id), "idx": idx, - "url": server.get("url"), + "url": (server.get("url") or "").rstrip("/"), "openapi": openapi_data, "info": response.get("info"), "specs": response.get("specs"), @@ -1250,7 +1250,7 @@ async def execute_tool_server( if params[param_name] is not None: query_params[param_name] = params[param_name] - final_url = f"{url}{route_path}" + final_url = f"{url.rstrip('/')}{route_path}" for key, value in path_params.items(): final_url = final_url.replace(f"{{{key}}}", str(value)) @@ -1320,6 +1320,8 @@ def get_tool_server_url(url: Optional[str], path: str) -> str: if "://" in path: # If it contains "://", it's a full URL return path + if url: + url = url.rstrip("/") if not path.startswith("/"): # Ensure the path starts with a slash path = f"/{path}" From e303c3da3b174da9e92a79b174f85ba574ca06ef Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 17:45:00 -0600 Subject: [PATCH 082/114] refac: inline codespan rich text input Co-Authored-By: Abdul Moiz <86627657+abdulmoizjawed@users.noreply.github.com> --- package-lock.json | 29 ++++++++++--------- package.json | 3 +- .../components/common/RichTextInput.svelte | 22 +++++++++++++- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/package-lock.json b/package-lock.json index 45f1f53721..8f5599767c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "@sveltejs/svelte-virtual-list": "^3.0.1", "@tiptap/core": "^3.0.7", "@tiptap/extension-bubble-menu": "^2.26.1", + "@tiptap/extension-code": "^3.0.7", "@tiptap/extension-code-block-lowlight": "^3.0.7", "@tiptap/extension-drag-handle": "^3.4.5", "@tiptap/extension-file-handler": "^3.0.7", @@ -3369,9 +3370,9 @@ } }, "node_modules/@tiptap/extension-collaboration": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-collaboration/-/extension-collaboration-3.20.0.tgz", - "integrity": "sha512-JItmI4U0i4kqorO114u24hM9k945IdaQ6Uc2DEtPBFFuS8cepJf2zw+ulAT1kAx6ZRiNvNpT9M7w+J0mWRn+Sg==", + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-collaboration/-/extension-collaboration-3.20.1.tgz", + "integrity": "sha512-JnwLvyzrutBffHp6YPnf0XyTnhAgqZ9D8JSUKFp0edvai+dxsb+UMlawesBrgAuoQXw3B8YZUo2VFDVdKas1xQ==", "license": "MIT", "peer": true, "funding": { @@ -3379,8 +3380,8 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^3.20.0", - "@tiptap/pm": "^3.20.0", + "@tiptap/core": "^3.20.1", + "@tiptap/pm": "^3.20.1", "@tiptap/y-tiptap": "^3.0.2", "yjs": "^13" } @@ -3628,9 +3629,9 @@ } }, "node_modules/@tiptap/extension-node-range": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-node-range/-/extension-node-range-3.20.0.tgz", - "integrity": "sha512-XeKKTV88VuJ4Mh0Rxvc/PPzG76cb44sE+rB4u0J/ms63R/WFTm6yJQlCgUVGnGeHleSlrWuZY8gGSuoljmQzqg==", + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-node-range/-/extension-node-range-3.20.1.tgz", + "integrity": "sha512-+W/mQJxlkXMcwldWUqwdoR0eniJ1S9cVJoAy2Lkis0NhILZDWVNGKl9J4WFoCOXn8Myr17IllIxRYvAXJJ4FHQ==", "license": "MIT", "peer": true, "funding": { @@ -3638,8 +3639,8 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^3.20.0", - "@tiptap/pm": "^3.20.0" + "@tiptap/core": "^3.20.1", + "@tiptap/pm": "^3.20.1" } }, "node_modules/@tiptap/extension-ordered-list": { @@ -3709,9 +3710,9 @@ } }, "node_modules/@tiptap/extension-text-style": { - "version": "3.20.0", - "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-3.20.0.tgz", - "integrity": "sha512-zyWW1a6W+kaXAn3wv2svJ1XuVMapujftvH7Xn2Q3QmKKiDkO+NiFkrGe8BhMopu8Im51nO3NylIgVA0X1mS1rQ==", + "version": "3.20.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-3.20.1.tgz", + "integrity": "sha512-3LQU92zX6tzl47EBskkAKeJXd6EWwYmBDE7jbd7InJqnt9NMAcj4DtXtXpI+e6Un5+8yzNjVA+fI5+5cFS3dSg==", "license": "MIT", "peer": true, "funding": { @@ -3719,7 +3720,7 @@ "url": "https://github.com/sponsors/ueberdosis" }, "peerDependencies": { - "@tiptap/core": "^3.20.0" + "@tiptap/core": "^3.20.1" } }, "node_modules/@tiptap/extension-typography": { diff --git a/package.json b/package.json index 74a2e04992..0e30237aee 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "@sveltejs/svelte-virtual-list": "^3.0.1", "@tiptap/core": "^3.0.7", "@tiptap/extension-bubble-menu": "^2.26.1", + "@tiptap/extension-code": "^3.0.7", "@tiptap/extension-code-block-lowlight": "^3.0.7", "@tiptap/extension-drag-handle": "^3.4.5", "@tiptap/extension-file-handler": "^3.0.7", @@ -157,4 +158,4 @@ "node": ">=18.13.0 <=22.x.x", "npm": ">=6.0.0" } -} +} \ No newline at end of file diff --git a/src/lib/components/common/RichTextInput.svelte b/src/lib/components/common/RichTextInput.svelte index aea8ca7191..07bc4680ea 100644 --- a/src/lib/components/common/RichTextInput.svelte +++ b/src/lib/components/common/RichTextInput.svelte @@ -114,7 +114,7 @@ import { Fragment, DOMParser } from 'prosemirror-model'; import { EditorState, Plugin, PluginKey, TextSelection, Selection } from 'prosemirror-state'; import { Decoration, DecorationSet } from 'prosemirror-view'; - import { Editor, Extension, mergeAttributes } from '@tiptap/core'; + import { Editor, Extension, markInputRule, mergeAttributes } from '@tiptap/core'; import { AIAutocompletion } from './RichTextInput/AutoCompletion.js'; @@ -135,8 +135,26 @@ import FileHandler from '@tiptap/extension-file-handler'; import Typography from '@tiptap/extension-typography'; import Highlight from '@tiptap/extension-highlight'; + import Code from '@tiptap/extension-code'; import CodeBlockLowlight from '@tiptap/extension-code-block-lowlight'; + // WORKAROUND: TipTap's default Code mark input rule regex captures the + // character before the opening backtick, causing it to be deleted. + // This uses a lookbehind assertion instead so the preceding character is + // matched for position but not captured/deleted. + // Upstream fix: https://github.com/ueberdosis/tiptap/pull/7124 + const backtickInputRegex = /(?<=\s|^)`([^`]+)`(?!`)$/; + const FixedCode = Code.extend({ + addInputRules() { + return [ + markInputRule({ + find: backtickInputRegex, + type: this.type + }) + ]; + } + }); + import Mention from '@tiptap/extension-mention'; import FormattingButtons from './RichTextInput/FormattingButtons.svelte'; @@ -692,12 +710,14 @@ extensions: [ StarterKit.configure({ link: link, + code: false, // Disabled in favor of FixedCode (see workaround above) // When rich text is off, disable Strike from StarterKit so we can // re-add it below without its Mod-Shift-s shortcut (which conflicts // with the Toggle Sidebar shortcut). When rich text is on, the user // can undo strikethrough via the toolbar, so the shortcut is fine. ...(richText ? {} : { strike: false }) }), + FixedCode, ...(dragHandle ? [ListItemDragHandle] : []), Placeholder.configure({ placeholder: () => _placeholder, showOnlyWhenEditable: false }), SelectionDecoration, From 7b2f597b30c77ef300d1966e1c6a3edfdb0c465d Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 17:52:58 -0600 Subject: [PATCH 083/114] refac --- .../chat/MessageInput/InputVariablesModal.svelte | 6 ++++++ src/lib/components/common/RichTextInput.svelte | 13 ++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/lib/components/chat/MessageInput/InputVariablesModal.svelte b/src/lib/components/chat/MessageInput/InputVariablesModal.svelte index d2410ad80b..b50ed38395 100644 --- a/src/lib/components/chat/MessageInput/InputVariablesModal.svelte +++ b/src/lib/components/chat/MessageInput/InputVariablesModal.svelte @@ -21,6 +21,12 @@ let variableValues = {}; const submitHandler = async () => { + // Normalize Windows CRLF (\r\n) to LF (\n) for all string values + for (const key of Object.keys(variableValues)) { + if (typeof variableValues[key] === 'string') { + variableValues[key] = variableValues[key].replace(/\r\n/g, '\n'); + } + } onSave(variableValues); show = false; }; diff --git a/src/lib/components/common/RichTextInput.svelte b/src/lib/components/common/RichTextInput.svelte index 07bc4680ea..b9dd058553 100644 --- a/src/lib/components/common/RichTextInput.svelte +++ b/src/lib/components/common/RichTextInput.svelte @@ -485,6 +485,17 @@ focus(); }; + // Convert text to ProseMirror nodes, using hardBreak for newlines + const textToNodes = (state, text) => { + if (!text.includes('\n')) return state.schema.text(text); + const nodes = []; + text.split('\n').forEach((line, i) => { + if (i > 0) nodes.push(state.schema.nodes.hardBreak.create()); + if (line) nodes.push(state.schema.text(line)); + }); + return nodes; + }; + export const replaceVariables = (variables) => { if (!editor || !editor.view) return; const { state, view } = editor; @@ -519,7 +530,7 @@ // Apply replacements in reverse order to maintain correct positions replacements.reverse().forEach(({ from, to, text }) => { - tr = tr.replaceWith(from, to, text !== '' ? state.schema.text(text) : []); + tr = tr.replaceWith(from, to, text !== '' ? textToNodes(state, text) : []); }); // Only dispatch if there are changes From b4f340806a4a0157bdd258b5acaa89c8a048be07 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sun, 8 Mar 2026 01:08:11 +0100 Subject: [PATCH 084/114] fix: migration streaming/batching (#21542) * fix: normalize usage tokens + migration streaming/batching - Migration: replace .fetchall() with yield_per streaming, replace per-message INSERT+SAVEPOINT with batched inserts (5k/batch) with fallback to row-by-row on error, add progress logging - Write path: call normalize_usage() in upsert_message() before saving to ensure input_tokens/output_tokens always present - Read path: analytics queries now COALESCE across input_tokens/prompt_tokens and output_tokens/completion_tokens so historical data with OpenAI-format keys is visible * fix: restore defensive timestamp conversion in migration Re-add try/except around int(float(timestamp)) that was accidentally dropped. Without this, a non-numeric timestamp string would cause a TypeError on the subsequent comparison, breaking the entire upgrade. * revert: remove changes to chat_messages.py --- .../8452d01d26d7_add_chat_message_table.py | 116 ++++++++++++------ 1 file changed, 78 insertions(+), 38 deletions(-) diff --git a/backend/open_webui/migrations/versions/8452d01d26d7_add_chat_message_table.py b/backend/open_webui/migrations/versions/8452d01d26d7_add_chat_message_table.py index 567f7d673a..ea95d08f12 100644 --- a/backend/open_webui/migrations/versions/8452d01d26d7_add_chat_message_table.py +++ b/backend/open_webui/migrations/versions/8452d01d26d7_add_chat_message_table.py @@ -21,6 +21,39 @@ branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None +BATCH_SIZE = 5000 + + +def _flush_batch(conn, table, batch): + """ + Insert a batch of messages, falling back to row-by-row on error. + + Tries a single bulk insert first (fast path). If that fails (e.g. due to + a duplicate key), falls back to individual inserts wrapped in savepoints + so the rest of the batch can still succeed. + """ + savepoint = conn.begin_nested() + try: + conn.execute(sa.insert(table), batch) + savepoint.commit() + return len(batch), 0 + except Exception: + savepoint.rollback() + # Batch failed - insert one-by-one to isolate the bad row(s) + inserted = 0 + failed = 0 + for msg in batch: + sp = conn.begin_nested() + try: + conn.execute(sa.insert(table).values(**msg)) + sp.commit() + inserted += 1 + except Exception as e: + sp.rollback() + failed += 1 + log.warning(f"Failed to insert message {msg['id']}: {e}") + return inserted, failed + def upgrade() -> None: # Step 1: Create table @@ -88,18 +121,21 @@ def upgrade() -> None: sa.column("updated_at", sa.BigInteger()), ) - # Fetch all chats (excluding shared chats which have user_id starting with 'shared-') - chats = conn.execute( + # Stream rows instead of loading all into memory: + # - yield_per: fetches rows in chunks via cursor.fetchmany() (all backends) + # - stream_results: enables server-side cursors on PostgreSQL (no-op on SQLite) + result = conn.execute( sa.select(chat_table.c.id, chat_table.c.user_id, chat_table.c.chat).where( ~chat_table.c.user_id.like("shared-%") - ) - ).fetchall() + ).execution_options(yield_per=1000, stream_results=True) + ) now = int(time.time()) - messages_inserted = 0 - messages_failed = 0 + messages_batch = [] + total_inserted = 0 + total_failed = 0 - for chat_row in chats: + for chat_row in result: chat_id = chat_row[0] user_id = chat_row[1] chat_data = chat_row[2] @@ -139,39 +175,43 @@ def upgrade() -> None: if timestamp < 1577836800 or timestamp > now + 86400: timestamp = now - # Use savepoint to allow individual insert failures without aborting transaction - savepoint = conn.begin_nested() - try: - conn.execute( - sa.insert(chat_message_table).values( - id=f"{chat_id}-{message_id}", - chat_id=chat_id, - user_id=user_id, - role=role, - parent_id=message.get("parentId"), - content=message.get("content"), - output=message.get("output"), - model_id=message.get("model"), - files=message.get("files"), - sources=message.get("sources"), - embeds=message.get("embeds"), - done=message.get("done", True), - status_history=message.get("statusHistory"), - error=message.get("error"), - created_at=timestamp, - updated_at=timestamp, - ) - ) - savepoint.commit() - messages_inserted += 1 - except Exception as e: - savepoint.rollback() - messages_failed += 1 - log.warning(f"Failed to insert message {message_id}: {e}") - continue + messages_batch.append({ + "id": f"{chat_id}-{message_id}", + "chat_id": chat_id, + "user_id": user_id, + "role": role, + "parent_id": message.get("parentId"), + "content": message.get("content"), + "output": message.get("output"), + "model_id": message.get("model"), + "files": message.get("files"), + "sources": message.get("sources"), + "embeds": message.get("embeds"), + "done": message.get("done", True), + "status_history": message.get("statusHistory"), + "error": message.get("error"), + "usage": message.get("usage"), + "created_at": timestamp, + "updated_at": timestamp, + }) + + # Flush batch when full + if len(messages_batch) >= BATCH_SIZE: + inserted, failed = _flush_batch(conn, chat_message_table, messages_batch) + total_inserted += inserted + total_failed += failed + if total_inserted % 50000 < BATCH_SIZE: + log.info(f"Migration progress: {total_inserted} messages inserted...") + messages_batch.clear() + + # Flush remaining messages + if messages_batch: + inserted, failed = _flush_batch(conn, chat_message_table, messages_batch) + total_inserted += inserted + total_failed += failed log.info( - f"Backfilled {messages_inserted} messages into chat_message table ({messages_failed} failed)" + f"Backfilled {total_inserted} messages into chat_message table ({total_failed} failed)" ) From 5d4505c68509242b72727e3493a5adb0f52a5530 Mon Sep 17 00:00:00 2001 From: pedro-inf-custodio <113921389+pedro-inf-custodio@users.noreply.github.com> Date: Sun, 8 Mar 2026 00:13:28 +0000 Subject: [PATCH 085/114] fix: add support for scope in OAuth refresh token request (#22359) * fix: add support for scope in OAuth refresh token request * add oauth refresh token include scope * Fix variable import * Fix env variables import * Added debug logs WIP * Remove debug logs --- backend/open_webui/config.py | 6 ++++++ backend/open_webui/utils/oauth.py | 22 ++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index 512bfdf7aa..32dfdb7ca9 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -339,6 +339,12 @@ def __getattr__(self, key): os.environ.get("ENABLE_OAUTH_SIGNUP", "False").lower() == "true", ) +OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE = PersistentConfig( + "OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE", + "oauth.refresh_token_include_scope", + os.environ.get("OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE", "False").lower() == "true", +) + OAUTH_MERGE_ACCOUNTS_BY_EMAIL = PersistentConfig( "OAUTH_MERGE_ACCOUNTS_BY_EMAIL", diff --git a/backend/open_webui/utils/oauth.py b/backend/open_webui/utils/oauth.py index 284917d22c..392ae74f96 100644 --- a/backend/open_webui/utils/oauth.py +++ b/backend/open_webui/utils/oauth.py @@ -36,6 +36,7 @@ from open_webui.config import ( DEFAULT_USER_ROLE, ENABLE_OAUTH_SIGNUP, + OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE, OAUTH_MERGE_ACCOUNTS_BY_EMAIL, OAUTH_PROVIDERS, ENABLE_OAUTH_ROLE_MANAGEMENT, @@ -113,6 +114,9 @@ class OAuthClientInformationFull(OAuthClientMetadata): auth_manager_config = AppConfig() auth_manager_config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE auth_manager_config.ENABLE_OAUTH_SIGNUP = ENABLE_OAUTH_SIGNUP +auth_manager_config.OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE = ( + OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE +) auth_manager_config.OAUTH_MERGE_ACCOUNTS_BY_EMAIL = OAUTH_MERGE_ACCOUNTS_BY_EMAIL auth_manager_config.ENABLE_OAUTH_ROLE_MANAGEMENT = ENABLE_OAUTH_ROLE_MANAGEMENT auth_manager_config.ENABLE_OAUTH_GROUP_MANAGEMENT = ENABLE_OAUTH_GROUP_MANAGEMENT @@ -787,6 +791,16 @@ async def _perform_token_refresh(self, session) -> dict: if hasattr(client, "client_secret") and client.client_secret: refresh_data["client_secret"] = client.client_secret + # Add scope if available in client kwargs (some providers require it on refresh) + if ( + hasattr(client, "client_kwargs") + and client.client_kwargs.get("scope") + and getattr( + self.app.state.config, "OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE", False + ) + ): + refresh_data["scope"] = client.client_kwargs["scope"] + # Make refresh request async with aiohttp.ClientSession(trust_env=True) as session_http: async with session_http.post( @@ -1081,6 +1095,14 @@ async def _perform_token_refresh(self, session) -> dict: if hasattr(client, "client_secret") and client.client_secret: refresh_data["client_secret"] = client.client_secret + # Add scope if available in client kwargs (some providers require it on refresh) + if ( + hasattr(client, "client_kwargs") + and client.client_kwargs.get("scope") + and auth_manager_config.OAUTH_REFRESH_TOKEN_INCLUDE_SCOPE + ): + refresh_data["scope"] = client.client_kwargs["scope"] + # Make refresh request async with aiohttp.ClientSession(trust_env=True) as session_http: async with session_http.post( From 35bc8310772c222fd8a466f7d00113a84e0402d0 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 18:18:02 -0600 Subject: [PATCH 086/114] refac --- backend/open_webui/tools/builtin.py | 3 +++ backend/open_webui/utils/middleware.py | 1 + src/lib/utils/index.ts | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/backend/open_webui/tools/builtin.py b/backend/open_webui/tools/builtin.py index fe20555f9d..b438759e10 100644 --- a/backend/open_webui/tools/builtin.py +++ b/backend/open_webui/tools/builtin.py @@ -429,6 +429,9 @@ def restricted_import(name, globals=None, locals=None, fromlist=(), level=0): "session_id": ( __metadata__.get("session_id") if __metadata__ else None ), + "files": ( + __metadata__.get("files", []) if __metadata__ else [] + ), }, } ) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 1f2718ae7f..a4ca8c3561 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -4510,6 +4510,7 @@ def restricted_import(name, globals=None, locals=None, fromlist=(), level=0): "session_id": metadata.get( "session_id", None ), + "files": metadata.get("files", []), }, } ) diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts index 5a0f899ffc..61ecb75c8b 100644 --- a/src/lib/utils/index.ts +++ b/src/lib/utils/index.ts @@ -1679,6 +1679,10 @@ export const renderVegaVisualization = async (spec: string, i18n?: any) => { }; export const getCodeBlockContents = (content: string): object => { + // Strip thinking/reasoning and other detail blocks before extracting code + // to prevent code inside
from being treated as artifacts + content = removeAllDetails(content); + const codeBlockContents = content.match(/```[\s\S]*?```/g); let codeBlocks = []; From 95b65ff751f91131b633cb128ff2decdd87c4a85 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 18:23:52 -0600 Subject: [PATCH 087/114] refac --- backend/open_webui/routers/ollama.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/open_webui/routers/ollama.py b/backend/open_webui/routers/ollama.py index 580717987c..926e2c02ad 100644 --- a/backend/open_webui/routers/ollama.py +++ b/backend/open_webui/routers/ollama.py @@ -1176,7 +1176,7 @@ async def embeddings( class GenerateCompletionForm(BaseModel): model: str - prompt: str + prompt: Optional[str] = None suffix: Optional[str] = None images: Optional[list[str]] = None format: Optional[Union[dict, str]] = None From 2e1ef805ff0da372a22702009b9dd416c6633a35 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sun, 8 Mar 2026 01:30:26 +0100 Subject: [PATCH 088/114] fix: banner type dropdown requires two selections to register (#22378) --- src/lib/components/admin/Settings/Interface/Banners.svelte | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib/components/admin/Settings/Interface/Banners.svelte b/src/lib/components/admin/Settings/Interface/Banners.svelte index 6b96374d5e..5ebf9c7685 100644 --- a/src/lib/components/admin/Settings/Interface/Banners.svelte +++ b/src/lib/components/admin/Settings/Interface/Banners.svelte @@ -64,9 +64,7 @@ bind:value={banner.type} required > - {#if banner.type == ''} - - {/if} + From 885c94bda888efc490bd9cd13ff9500fbc45d1f7 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 18:51:20 -0600 Subject: [PATCH 089/114] refac --- src/lib/components/layout/Sidebar/ChatItem.svelte | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/components/layout/Sidebar/ChatItem.svelte b/src/lib/components/layout/Sidebar/ChatItem.svelte index 7134b1e94d..36a76a932c 100644 --- a/src/lib/components/layout/Sidebar/ChatItem.svelte +++ b/src/lib/components/layout/Sidebar/ChatItem.svelte @@ -79,6 +79,9 @@ let mouseOver = false; let draggable = false; + $: if (mouseOver) { + loadChat(); + } const loadChat = async () => { if (!chat) { From d7efdcce2b1cdbe1637a469294bf9d52dbacab53 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 19:02:03 -0600 Subject: [PATCH 090/114] refac --- backend/open_webui/utils/middleware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index a4ca8c3561..3e993fdde6 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -3741,7 +3741,7 @@ async def flush_pending_delta_data(threshold: int = 0): if delta_name: current_response_tool_call[ "function" - ]["name"] += delta_name + ]["name"] = delta_name if delta_arguments: current_response_tool_call[ From 9a269ec8abc930ed45ff6a7803664d5f9131c44f Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sun, 8 Mar 2026 02:02:59 +0100 Subject: [PATCH 091/114] fix: use path converter for model ID routes in analytics to support slashes (#22382) --- backend/open_webui/routers/analytics.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/open_webui/routers/analytics.py b/backend/open_webui/routers/analytics.py index 61aec66332..1bd12f7bdb 100644 --- a/backend/open_webui/routers/analytics.py +++ b/backend/open_webui/routers/analytics.py @@ -278,7 +278,7 @@ class ModelChatsResponse(BaseModel): total: int -@router.get("/models/{model_id}/chats", response_model=ModelChatsResponse) +@router.get("/models/{model_id:path}/chats", response_model=ModelChatsResponse) async def get_model_chats( model_id: str, start_date: Optional[int] = Query(None), @@ -367,7 +367,7 @@ class ModelOverviewResponse(BaseModel): tags: list[TagEntry] -@router.get("/models/{model_id}/overview", response_model=ModelOverviewResponse) +@router.get("/models/{model_id:path}/overview", response_model=ModelOverviewResponse) async def get_model_overview( model_id: str, days: int = Query(30, description="Number of days of history (0 for all)"), From 459a60a24240eab33441ed50f4f68cc27e65a037 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 19:17:24 -0600 Subject: [PATCH 092/114] refac --- backend/open_webui/utils/middleware.py | 55 +++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 3e993fdde6..00de970ef4 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -160,6 +160,55 @@ def output_id(prefix: str) -> str: return f"{prefix}_{uuid4().hex[:24]}" +def _split_tool_calls( + tool_calls: list[dict], +) -> list[dict]: + """Expand tool calls whose arguments contain multiple back-to-back JSON objects. + + Some models (e.g. GPT-5.4) send multiple complete JSON argument objects + under the same tool call index, producing concatenated invalid JSON like: + '{"query":"A","count":5}{"query":"B","count":5}' + + Each such tool call is split into separate entries so each gets executed + independently. Single-object arguments pass through unchanged. + """ + + def split_json_objects(raw: str) -> list[str]: + decoder = json.JSONDecoder() + results = [] + position = 0 + + while position < len(raw): + while position < len(raw) and raw[position].isspace(): + position += 1 + if position >= len(raw): + break + try: + _, end = decoder.raw_decode(raw, position) + results.append(raw[position:end].strip()) + position = end + except json.JSONDecodeError: + return [raw] + + return results or [raw] + + expanded = [] + for tool_call in tool_calls: + arguments = tool_call.get("function", {}).get("arguments", "") + split_arguments = split_json_objects(arguments) + + if len(split_arguments) <= 1: + expanded.append(tool_call) + else: + for argument in split_arguments: + cloned = copy.deepcopy(tool_call) + cloned["id"] = f"call_{uuid4().hex[:24]}" + cloned["function"]["arguments"] = argument + expanded.append(cloned) + + return expanded + + def get_citation_source_from_tool_result( tool_name: str, tool_params: dict, tool_result: str, tool_id: str = "" ) -> list[dict]: @@ -4104,7 +4153,11 @@ async def flush_pending_delta_data(threshold: int = 0): reasoning_item["status"] = "completed" if response_tool_calls: - tool_calls.append(response_tool_calls) + tool_calls.append( + _split_tool_calls( + response_tool_calls + ) + ) if response.background: await response.background() From d1975b740b019ba1364eba7fdcf478ec99b19ca7 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sun, 8 Mar 2026 02:19:44 +0100 Subject: [PATCH 093/114] fix: add deterministic ordering to chat_ids pagination query to prevent duplicates (#22383) --- backend/open_webui/models/chat_messages.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/open_webui/models/chat_messages.py b/backend/open_webui/models/chat_messages.py index e6e932be12..4cd868e4d4 100644 --- a/backend/open_webui/models/chat_messages.py +++ b/backend/open_webui/models/chat_messages.py @@ -292,9 +292,13 @@ def get_chat_ids_by_model_id( query = query.filter(ChatMessage.created_at <= end_date) # Group by chat_id and order by most recent message in each chat + # Secondary sort on chat_id ensures deterministic pagination + # (prevents duplicates across pages when timestamps tie) chat_ids = ( query.group_by(ChatMessage.chat_id) - .order_by(func.max(ChatMessage.created_at).desc()) + .order_by( + func.max(ChatMessage.created_at).desc(), ChatMessage.chat_id + ) .offset(skip) .limit(limit) .all() From ce0ca894fea8a2904bc6f832ff186d5fe53dd0b9 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 19:23:18 -0600 Subject: [PATCH 094/114] enh: code interpreter pyodide fs --- backend/open_webui/config.py | 39 +- backend/open_webui/main.py | 1 + backend/open_webui/utils/middleware.py | 32 +- .../admin/Settings/CodeExecution.svelte | 4 +- src/lib/components/chat/Chat.svelte | 3 + src/lib/components/chat/ChatControls.svelte | 10 +- .../chat/FileNav/FileEntryRow.svelte | 4 +- src/lib/components/chat/MessageInput.svelte | 6 + src/lib/components/chat/PyodideFileNav.svelte | 367 ++++++++++++++++++ src/lib/stores/index.ts | 3 + src/lib/workers/pyodide.worker.ts | 262 +++++++++++-- src/routes/+layout.svelte | 79 +++- 12 files changed, 730 insertions(+), 80 deletions(-) create mode 100644 src/lib/components/chat/PyodideFileNav.svelte diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index 32dfdb7ca9..2e3254a08c 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -2296,20 +2296,31 @@ class BannerModel(BaseModel): ] DEFAULT_CODE_INTERPRETER_PROMPT = """ -#### Tools Available - -1. **Code Interpreter**: `` - - You have access to a Python shell that runs directly in the user's browser, enabling fast execution of code for analysis, calculations, or problem-solving. Use it in this response. - - The Python code you write can incorporate a wide array of libraries, handle data manipulation or visualization, perform API calls for web-related tasks, or tackle virtually any computational challenge. Use this flexibility to **think outside the box, craft elegant solutions, and harness Python's full potential**. - - To use it, **you must enclose your code within `` XML tags** and stop right away. If you don't, the code won't execute. - - When writing code in the code_interpreter XML tag, Do NOT use the triple backticks code block for markdown formatting, example: ```py # python code ``` will cause an error because it is markdown formatting, it is not python code. - - When coding, **always aim to print meaningful outputs** (e.g., results, tables, summaries, or visuals) to better interpret and verify the findings. Avoid relying on implicit outputs; prioritize explicit and clear print statements so the results are effectively communicated to the user. - - After obtaining the printed output, **always provide a concise analysis, interpretation, or next steps to help the user understand the findings or refine the outcome further.** - - If the results are unclear, unexpected, or require validation, refine the code and execute it again as needed. Always aim to deliver meaningful insights from the results, iterating if necessary. - - **If a link to an image, audio, or any file is provided in markdown format in the output, ALWAYS regurgitate word for word, explicitly display it as part of the response to ensure the user can access it easily, do NOT change the link.** - - All responses should be communicated in the chat's primary language, ensuring seamless understanding. If the chat is multilingual, default to English for clarity. - -Ensure that the tools are effectively utilized to achieve the highest-quality analysis for the user.""" +#### Code Interpreter + +You have access to a Python code interpreter via: `` + +- The Python shell runs directly in the user's browser for fast execution of analysis, calculations, or problem-solving. Use it in this response. +- You can use a wide array of libraries for data manipulation, visualization, API calls, or any computational task. Think outside the box and harness Python's full potential. +- **You must enclose your code within `` XML tags** and stop right away. If you don't, the code won't execute. +- Do NOT use triple backticks (```py ... ```) inside the XML tags — that is markdown formatting, not executable Python code. +- **Always print meaningful outputs** (results, tables, summaries, visuals). Avoid implicit outputs; use explicit print statements. +- After obtaining output, **provide a concise analysis, interpretation, or next steps** to help the user understand the findings. +- If results are unclear or unexpected, refine the code and re-execute. Iterate until you deliver meaningful insights. +- **If a link to an image, audio, or any file appears in the output, display it exactly as-is** in your response so the user can access it. Do not modify the link. +- Respond in the chat's primary language. Default to English if multilingual. + +Ensure the code interpreter is effectively utilized to achieve the highest-quality analysis for the user.""" + +# Appended to the code interpreter prompt only when engine is pyodide (not jupyter) +CODE_INTERPRETER_PYODIDE_FS_PROMPT = """ + +##### Persistent File System + +- User-uploaded files are available at `/mnt/uploads/`. When the user asks you to work with their files, read from this directory. +- You can also write output files to `/mnt/uploads/` so the user can access and download them from the file browser. +- The file system persists across code executions within the same session. +- Use `import os; os.listdir('/mnt/uploads')` to discover available files.""" #################################### diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index 328c49b6c8..4c27e811cb 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -2193,6 +2193,7 @@ async def get_app_config(request: Request): "user_count": user_count, "code": { "engine": app.state.config.CODE_EXECUTION_ENGINE, + "interpreter_engine": app.state.config.CODE_INTERPRETER_ENGINE, }, "audio": { "tts": { diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 00de970ef4..4aa7c2f41e 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -1,3 +1,4 @@ +import copy import time import logging import sys @@ -119,6 +120,7 @@ DEFAULT_VOICE_MODE_PROMPT_TEMPLATE, DEFAULT_TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE, DEFAULT_CODE_INTERPRETER_PROMPT, + CODE_INTERPRETER_PYODIDE_FS_PROMPT, CODE_INTERPRETER_BLOCKED_MODULES, ) from open_webui.env import ( @@ -2352,18 +2354,36 @@ async def process_chat_payload(request, form_data, user, metadata, model): ) if "code_interpreter" in features and features["code_interpreter"]: + engine = getattr( + request.app.state.config, "CODE_INTERPRETER_ENGINE", "pyodide" + ) + # Skip XML-tag prompt injection when native FC is enabled — # execute_code will be injected as a builtin tool instead if metadata.get("params", {}).get("function_calling") != "native": + prompt = ( + request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE + if request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE + != "" + else DEFAULT_CODE_INTERPRETER_PROMPT + ) + + # Append filesystem awareness only for pyodide engine + if engine != "jupyter": + prompt += CODE_INTERPRETER_PYODIDE_FS_PROMPT + form_data["messages"] = add_or_update_user_message( - ( - request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE - if request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE - != "" - else DEFAULT_CODE_INTERPRETER_PROMPT - ), + prompt, form_data["messages"], ) + else: + # Native FC: tool docstring can't be dynamic, so inject + # filesystem context into messages for pyodide engine + if engine != "jupyter": + form_data["messages"] = add_or_update_user_message( + CODE_INTERPRETER_PYODIDE_FS_PROMPT, + form_data["messages"], + ) tool_ids = form_data.pop("tool_ids", None) terminal_id = form_data.pop("terminal_id", None) diff --git a/src/lib/components/admin/Settings/CodeExecution.svelte b/src/lib/components/admin/Settings/CodeExecution.svelte index 23388c0a45..cad7970de1 100644 --- a/src/lib/components/admin/Settings/CodeExecution.svelte +++ b/src/lib/components/admin/Settings/CodeExecution.svelte @@ -67,7 +67,7 @@ > {#each engines as engine} - + {/each}
@@ -193,7 +193,7 @@ > {#each engines as engine} - + {/each}
diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index b510dd0b65..b391cd1a51 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -148,6 +148,8 @@ let webSearchEnabled = false; let codeInterpreterEnabled = false; + + let showCommands = false; let generating = false; @@ -2924,6 +2926,7 @@ {stopResponse} {showMessage} {eventTarget} + {codeInterpreterEnabled} />
diff --git a/src/lib/components/chat/ChatControls.svelte b/src/lib/components/chat/ChatControls.svelte index 60ec1aa27d..f5957e40e4 100644 --- a/src/lib/components/chat/ChatControls.svelte +++ b/src/lib/components/chat/ChatControls.svelte @@ -10,6 +10,7 @@ import { onDestroy, onMount, tick, getContext } from 'svelte'; import { + config, terminalServers, mobile, showControls, @@ -31,6 +32,7 @@ import Artifacts from './Artifacts.svelte'; import Embeds from './ChatControls/Embeds.svelte'; import FileNav from './FileNav.svelte'; + import PyodideFileNav from './PyodideFileNav.svelte'; import Overview from './Overview.svelte'; const i18n = getContext('i18n'); @@ -50,6 +52,8 @@ export let files; export let modelId; + export let codeInterpreterEnabled = false; + export let pane: Pane | null = null; let largeScreen = false; @@ -67,7 +71,7 @@ $: hasMessages = history?.messages && Object.keys(history.messages).length > 0; $: showControlsTab = $user?.role === 'admin' || ($user?.permissions?.chat?.controls ?? true); - $: showFilesTab = !!$selectedTerminalId; + $: showFilesTab = !!$selectedTerminalId || (codeInterpreterEnabled && $config?.code?.interpreter_engine !== 'jupyter'); $: showOverviewTab = hasMessages; // Tab fallback: if active tab becomes hidden, switch to next available @@ -355,6 +359,8 @@ /> {:else if activeTab === 'files' && $selectedTerminalId} + {:else if activeTab === 'files' && codeInterpreterEnabled} + {:else} {/if} @@ -504,6 +510,8 @@ /> {:else if activeTab === 'files' && $selectedTerminalId} + {:else if activeTab === 'files' && codeInterpreterEnabled} + {:else} {/if} diff --git a/src/lib/components/chat/FileNav/FileEntryRow.svelte b/src/lib/components/chat/FileNav/FileEntryRow.svelte index b572b15255..eb217bcc9b 100644 --- a/src/lib/components/chat/FileNav/FileEntryRow.svelte +++ b/src/lib/components/chat/FileNav/FileEntryRow.svelte @@ -12,8 +12,8 @@ export let entry: FileEntry; export let currentPath: string; - export let terminalUrl: string; - export let terminalKey: string; + export let terminalUrl: string = ''; + export let terminalKey: string = ''; export let onOpen: (entry: FileEntry) => void = () => {}; export let onDownload: (path: string) => void = () => {}; diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index 2cbd0d9557..9bf3a08139 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -508,11 +508,17 @@ let showCodeInterpreterButton = false; $: showCodeInterpreterButton = + !$selectedTerminalId && (atSelectedModel?.id ? [atSelectedModel.id] : selectedModels).length === codeInterpreterCapableModels.length && $config?.features?.enable_code_interpreter && ($_user.role === 'admin' || $_user?.permissions?.features?.code_interpreter); + // Disable code interpreter when terminal is active (mutually exclusive) + $: if ($selectedTerminalId && codeInterpreterEnabled) { + codeInterpreterEnabled = false; + } + const scrollToBottom = () => { const element = document.getElementById('messages-container'); element.scrollTo({ diff --git a/src/lib/components/chat/PyodideFileNav.svelte b/src/lib/components/chat/PyodideFileNav.svelte new file mode 100644 index 0000000000..45e9693207 --- /dev/null +++ b/src/lib/components/chat/PyodideFileNav.svelte @@ -0,0 +1,367 @@ + + + + + + +
(isDragOver = false)} + on:drop={handleDrop} + role="region" + aria-label={$i18n.t('Pyodide file browser')} +> + {#if isDragOver} +
+ + + + {$i18n.t('Drop files here')} +
+ {/if} + + {#if overlay} +
+ {/if} + + + loadDir(path)} + onRefresh={() => { + if (selectedFile) { + const name = selectedFile.split('/').pop() ?? ''; + openEntry({ name, type: 'file', size: 0 }); + } else { + loadDir(currentPath); + } + }} + onNewFolder={createFolder} + onNewFile={() => {}} + onUploadFiles={uploadFiles} + onMove={() => {}} + > + + + + + + +
+ {#if selectedFile} + + {:else if loading} +
+ +
+ {:else if error} +
+
{error}
+
+ {:else if entries.length === 0} +
+ +
+ {$i18n.t('No files yet. Upload files or run Python code to create them.')} +
+
+ {:else} +
    + {#each entries as entry (entry.name)} + + {/each} +
+ {/if} +
+
diff --git a/src/lib/stores/index.ts b/src/lib/stores/index.ts index bdc8fe31ca..6361dcab80 100644 --- a/src/lib/stores/index.ts +++ b/src/lib/stores/index.ts @@ -72,6 +72,9 @@ export const functions = writable(null); export const toolServers = writable([]); export const terminalServers = writable([]); +// Persistent Pyodide worker for code interpreter FS +export const pyodideWorker: Writable = writable(null); + export const banners: Writable = writable([]); export const settings: Writable = writable({}); diff --git a/src/lib/workers/pyodide.worker.ts b/src/lib/workers/pyodide.worker.ts index 221effca5e..a9334b4faf 100644 --- a/src/lib/workers/pyodide.worker.ts +++ b/src/lib/workers/pyodide.worker.ts @@ -13,6 +13,12 @@ declare global { } } +// --------------------------------------------------------------------------- +// Pyodide bootstrap +// --------------------------------------------------------------------------- + +let pyodideReady: Promise | null = null; + async function loadPyodideAndPackages(packages: string[] = []) { self.stdout = null; self.stderr = null; @@ -40,41 +46,148 @@ async function loadPyodideAndPackages(packages: string[] = []) { packages: ['micropip'] }); - const mountDir = '/mnt'; - self.pyodide.FS.mkdirTree(mountDir); - // self.pyodide.FS.mount(self.pyodide.FS.filesystems.IDBFS, {}, mountDir); - - // // Load persisted files from IndexedDB (Initial Sync) - // await new Promise((resolve, reject) => { - // self.pyodide.FS.syncfs(true, (err) => { - // if (err) { - // console.error('Error syncing from IndexedDB:', err); - // reject(err); - // } else { - // console.log('Successfully loaded from IndexedDB.'); - // resolve(); - // } - // }); - // }); + // Create the upload directory and mount IDBFS for persistence + const uploadDir = '/mnt/uploads'; + self.pyodide.FS.mkdirTree(uploadDir); + self.pyodide.FS.mount(self.pyodide.FS.filesystems.IDBFS, {}, '/mnt'); - const micropip = self.pyodide.pyimport('micropip'); + // Load persisted files from IndexedDB + await new Promise((resolve) => { + (self.pyodide.FS as any).syncfs(true, (err: Error | null) => { + if (err) { + console.error('Error syncing from IndexedDB:', err); + } + // Always resolve — missing data is fine on first run + resolve(); + }); + }); - // await micropip.set_index_urls('https://pypi.org/pypi/{package_name}/json'); + // Ensure /mnt/uploads still exists after sync (first-time init) + try { + self.pyodide.FS.stat(uploadDir); + } catch { + self.pyodide.FS.mkdirTree(uploadDir); + } + + const micropip = self.pyodide.pyimport('micropip'); await micropip.install(packages); } -self.onmessage = async (event) => { - const { id, code, ...context } = event.data; +/** + * Ensure Pyodide is loaded. On the first call, loads and installs packages. + * Subsequent calls reuse the already-loaded instance (persistent worker). + */ +async function ensurePyodide(packages: string[] = []) { + if (!pyodideReady) { + pyodideReady = loadPyodideAndPackages(packages); + } + await pyodideReady; + + // Install any additional packages not loaded on init + if (packages.length > 0 && self.pyodide) { + const micropip = self.pyodide.pyimport('micropip'); + await micropip.install(packages); + } +} + +/** + * Persist the in-memory FS to IndexedDB (fire-and-forget with logging). + */ +function persistFS() { + if (!self.pyodide) return; + (self.pyodide.FS as any).syncfs(false, (err: Error | null) => { + if (err) { + console.error('Error syncing to IndexedDB:', err); + } else { + console.log('Successfully synced to IndexedDB.'); + } + }); +} - console.log(event.data); +// --------------------------------------------------------------------------- +// FS operations +// --------------------------------------------------------------------------- - // The worker copies the context in its own "memory" (an object mapping name to values) - for (const key of Object.keys(context)) { - self[key] = context[key]; +function fsUploadFiles(files: { name: string; data: ArrayBuffer }[], dir = '/mnt/uploads') { + try { + self.pyodide.FS.stat(dir); + } catch { + self.pyodide.FS.mkdirTree(dir); } - // make sure loading is done - await loadPyodideAndPackages(self.packages); + for (const file of files) { + self.pyodide.FS.writeFile(`${dir}/${file.name}`, new Uint8Array(file.data)); + } +} + +function fsList(path: string) { + const entries: { name: string; type: 'file' | 'directory'; size: number }[] = []; + try { + const items = self.pyodide.FS.readdir(path).filter( + (n: string) => n !== '.' && n !== '..' + ); + for (const name of items) { + try { + const stat = self.pyodide.FS.stat(`${path}/${name}`); + const isDir = self.pyodide.FS.isDir(stat.mode); + entries.push({ + name, + type: isDir ? 'directory' : 'file', + size: isDir ? 0 : stat.size + }); + } catch { + // skip inaccessible entries + } + } + } catch { + // directory doesn't exist + } + return entries; +} + +function fsRead(path: string): ArrayBuffer { + const data: Uint8Array = (self.pyodide.FS as any).readFile(path) as Uint8Array; + return data.buffer as ArrayBuffer; +} + +function fsDelete(path: string) { + try { + const stat = self.pyodide.FS.stat(path); + if (self.pyodide.FS.isDir(stat.mode)) { + // Recursively delete directory contents + const items = self.pyodide.FS.readdir(path).filter( + (n: string) => n !== '.' && n !== '..' + ); + for (const item of items) { + fsDelete(`${path}/${item}`); + } + self.pyodide.FS.rmdir(path); + } else { + self.pyodide.FS.unlink(path); + } + } catch { + // already gone + } +} + +function fsMkdir(path: string) { + self.pyodide.FS.mkdirTree(path); +} + +// --------------------------------------------------------------------------- +// Code execution +// --------------------------------------------------------------------------- + +async function executeCode(id: string, code: string, files?: { name: string; data: ArrayBuffer }[]) { + self.stdout = null; + self.stderr = null; + self.result = null; + + // Upload any accompanying files before execution + if (files && files.length > 0) { + fsUploadFiles(files); + persistFS(); + } try { // check if matplotlib is imported in the code @@ -113,25 +226,90 @@ matplotlib.pyplot.show = show`); console.log('Python result:', self.result); - // Persist any changes to IndexedDB - // await new Promise((resolve, reject) => { - // self.pyodide.FS.syncfs(false, (err) => { - // if (err) { - // console.error('Error syncing to IndexedDB:', err); - // reject(err); - // } else { - // console.log('Successfully synced to IndexedDB.'); - // resolve(); - // } - // }); - // }); - } catch (error) { - self.stderr = error.toString(); + // Persist any files the code may have written + persistFS(); + } catch (error: unknown) { + self.stderr = error instanceof Error ? error.message : String(error); } self.postMessage({ id, result: self.result, stdout: self.stdout, stderr: self.stderr }); +} + +// --------------------------------------------------------------------------- +// Message handler +// --------------------------------------------------------------------------- + +self.onmessage = async (event) => { + const data = event.data; + const { id, type } = data; + + // Backward compatibility: messages without a `type` field are execute requests + if (!type || type === 'execute') { + const { code, files, ...context } = data; + + // Copy context keys (packages, etc.) into worker scope + for (const key of Object.keys(context)) { + if (key !== 'id' && key !== 'type') { + self[key] = context[key]; + } + } + + await ensurePyodide(self.packages); + await executeCode(id, code, files); + return; + } + + // FS operations require Pyodide to be loaded + await ensurePyodide(); + + switch (type) { + case 'fs:upload': { + const { files, dir } = data; + fsUploadFiles(files, dir); + persistFS(); + self.postMessage({ id, type: 'fs:upload', success: true }); + break; + } + + case 'fs:list': { + const entries = fsList(data.path); + self.postMessage({ id, type: 'fs:list', entries }); + break; + } + + case 'fs:read': { + try { + const buffer = fsRead(data.path); + self.postMessage({ id, type: 'fs:read', data: buffer }, { transfer: [buffer] }); + } catch (err: unknown) { + self.postMessage({ id, type: 'fs:read', error: err instanceof Error ? err.message : String(err) }); + } + break; + } + + case 'fs:delete': { + fsDelete(data.path); + persistFS(); + self.postMessage({ id, type: 'fs:delete', success: true }); + break; + } + + case 'fs:mkdir': { + fsMkdir(data.path); + persistFS(); + self.postMessage({ id, type: 'fs:mkdir', success: true }); + break; + } + + default: + console.warn('Unknown message type:', type); + } }; +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + function processResult(result: any): any { // Catch and always return JSON-safe string representations try { @@ -167,9 +345,9 @@ function processResult(result: any): any { } // Stringify anything that's left (e.g., Proxy objects that cannot be directly processed) return JSON.stringify(result); - } catch (err) { + } catch (err: unknown) { // In case something unexpected happens, we return a stringified fallback - return `[processResult error]: ${err.message || err.toString()}`; + return `[processResult error]: ${err instanceof Error ? err.message : String(err)}`; } } diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 42768ca99d..36fd7b22d5 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -34,8 +34,10 @@ terminalServers, showControls, showFileNavPath, - showFileNavDir + showFileNavDir, + pyodideWorker } from '$lib/stores'; + import { getFileContentById } from '$lib/apis/files'; import { goto } from '$app/navigation'; import { page } from '$app/stores'; import { beforeNavigate } from '$app/navigation'; @@ -184,7 +186,20 @@ }); }; - const executePythonAsWorker = async (id, code, cb) => { + /** + * Get or create the persistent Pyodide worker. + * The worker persists across executions so the virtual FS (IDBFS) is preserved. + */ + const getOrCreateWorker = () => { + let worker = $pyodideWorker; + if (!worker) { + worker = new PyodideWorker(); + pyodideWorker.set(worker); + } + return worker; + }; + + const executePythonAsWorker = async (id, code, cb, files = []) => { let result = null; let stdout = null; let stderr = null; @@ -206,19 +221,44 @@ /\bimport\s+pytz\b|\bfrom\s+pytz\b/.test(code) ? 'pytz' : null ].filter(Boolean); - const pyodideWorker = new PyodideWorker(); + const worker = getOrCreateWorker(); + + // Fetch file content from the server and prepare for the worker + let filePayloads = []; + if (files && files.length > 0) { + for (const file of files) { + try { + const fileId = file?.id; + const fileName = file?.filename || file?.name || 'file'; + if (fileId) { + const content = await getFileContentById(fileId); + if (content) { + filePayloads.push({ name: fileName, data: content }); + } + } + } catch (e) { + console.error('Failed to fetch file for Pyodide:', e); + } + } + } - pyodideWorker.postMessage({ + worker.postMessage({ + type: 'execute', id: id, code: code, - packages: packages + packages: packages, + files: filePayloads.length > 0 ? filePayloads : undefined }); - setTimeout(() => { + // Timeout for this specific execution (not the worker itself) + let timeoutId = setTimeout(() => { if (executing) { executing = false; stderr = 'Execution Time Limit Exceeded'; - pyodideWorker.terminate(); + + // Terminate and recreate the worker on timeout + worker.terminate(); + pyodideWorker.set(null); if (cb) { cb( @@ -237,11 +277,18 @@ } }, 60000); - pyodideWorker.onmessage = (event) => { - console.log('pyodideWorker.onmessage', event); - const { id, ...data } = event.data; + // Use addEventListener so multiple concurrent executions don't clobber each other + const onMessage = (event) => { + const { id: eventId, ...data } = event.data; + // Only handle responses for this execution ID + if (eventId !== id) return; + // Ignore FS responses (they use a type field) + if (data.type && data.type.startsWith('fs:')) return; - console.log(id, data); + console.log('pyodideWorker.onmessage', event); + clearTimeout(timeoutId); + worker.removeEventListener('message', onMessage); + worker.removeEventListener('error', onError); data['stdout'] && (stdout = data['stdout']); data['stderr'] && (stderr = data['stderr']); @@ -265,8 +312,11 @@ executing = false; }; - pyodideWorker.onerror = (event) => { + const onError = (event) => { console.log('pyodideWorker.onerror', event); + clearTimeout(timeoutId); + worker.removeEventListener('message', onMessage); + worker.removeEventListener('error', onError); if (cb) { cb( @@ -284,6 +334,9 @@ } executing = false; }; + + worker.addEventListener('message', onMessage); + worker.addEventListener('error', onError); }; const resolveToolServer = (serverUrl) => { @@ -423,7 +476,7 @@ } else if (data?.session_id === $socket.id) { if (type === 'execute:python') { console.log('execute:python', data); - executePythonAsWorker(data.id, data.code, cb); + executePythonAsWorker(data.id, data.code, cb, data.files || []); } else if (type === 'execute:tool') { console.log('execute:tool', data); executeTool(data, cb); From 8cd3bd7997d25877c2d316d8aa3058b01c7d6660 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 19:28:57 -0600 Subject: [PATCH 095/114] refac --- src/lib/components/chat/PyodideFileNav.svelte | 99 +++++++++++++++++-- 1 file changed, 92 insertions(+), 7 deletions(-) diff --git a/src/lib/components/chat/PyodideFileNav.svelte b/src/lib/components/chat/PyodideFileNav.svelte index 45e9693207..3afbd7bbe4 100644 --- a/src/lib/components/chat/PyodideFileNav.svelte +++ b/src/lib/components/chat/PyodideFileNav.svelte @@ -3,7 +3,7 @@ @@ -47,6 +49,18 @@ {align} transition={flyAndScale} > + { + onCreateSub(); + }} + > + +
{$i18n.t('Create Folder')}
+
+ +
+ { diff --git a/src/lib/components/layout/Sidebar/Folders/FolderModal.svelte b/src/lib/components/layout/Sidebar/Folders/FolderModal.svelte index f1d0975282..73248a59c2 100644 --- a/src/lib/components/layout/Sidebar/Folders/FolderModal.svelte +++ b/src/lib/components/layout/Sidebar/Folders/FolderModal.svelte @@ -19,6 +19,7 @@ export let onSubmit: Function = (e) => {}; export let folderId = null; + export let parentId = null; export let edit = false; let folder = null; @@ -55,7 +56,8 @@ await onSubmit({ name, meta, - data + data, + parent_id: edit ? undefined : parentId }); show = false; loading = false; diff --git a/src/lib/components/layout/Sidebar/RecursiveFolder.svelte b/src/lib/components/layout/Sidebar/RecursiveFolder.svelte index f800cfe9ba..3557a4fd5d 100644 --- a/src/lib/components/layout/Sidebar/RecursiveFolder.svelte +++ b/src/lib/components/layout/Sidebar/RecursiveFolder.svelte @@ -18,7 +18,8 @@ updateFolderIsExpandedById, updateFolderById, updateFolderParentIdById, - getFolderById + getFolderById, + createNewFolder } from '$lib/apis/folders'; import { getChatById, @@ -64,6 +65,9 @@ let showFolderModal = false; let edit = false; + let showCreateSubFolderModal = false; + let createSubFolderParentId = null; + let draggedOver = false; let dragged = false; @@ -414,6 +418,30 @@ saveAs(blob, `folder-${folders[folderId].name}-export-${Date.now()}.json`); }; + + const createSubFolderHandler = async ({ name, meta, data, parent_id }) => { + if (name === '') { + toast.error($i18n.t('Folder name cannot be empty.')); + return; + } + + name = name.trim(); + + const res = await createNewFolder(localStorage.token, { + name, + data, + meta, + parent_id + }).catch((error) => { + toast.error(`${error}`); + return null; + }); + + if (res) { + toast.success($i18n.t('Folder created successfully')); + dispatch('update'); + } + }; + + {#if dragged && x && y}
@@ -593,6 +627,10 @@ onExport={() => { exportHandler(); }} + onCreateSub={() => { + createSubFolderParentId = folderId; + showCreateSubFolderModal = true; + }} >
diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index dced0f6c92..ae23cad549 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -897,6 +897,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -2135,4 +2136,4 @@ "YouTube": "", "Youtube Language": "", "Youtube Proxy URL": "" -} +} \ No newline at end of file From 989938856fdb4b4afa584ae2d18c88d5be614ae2 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:05:18 -0600 Subject: [PATCH 099/114] refac --- backend/open_webui/config.py | 7 ++++++- backend/open_webui/utils/middleware.py | 6 +++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index 2e3254a08c..f029b6ba2b 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -2313,7 +2313,12 @@ class BannerModel(BaseModel): Ensure the code interpreter is effectively utilized to achieve the highest-quality analysis for the user.""" # Appended to the code interpreter prompt only when engine is pyodide (not jupyter) -CODE_INTERPRETER_PYODIDE_FS_PROMPT = """ +CODE_INTERPRETER_PYODIDE_PROMPT = """ + +##### Pyodide Environment + +- This Python environment runs via Pyodide in the browser. **Do not install packages** — `pip install`, `subprocess`, and `micropip.install()` are not available. +- If a required library is unavailable, use an alternative approach with available modules. Do not attempt to install anything. ##### Persistent File System diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 5dd8ed3f5d..389ae9a90b 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -120,7 +120,7 @@ DEFAULT_VOICE_MODE_PROMPT_TEMPLATE, DEFAULT_TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE, DEFAULT_CODE_INTERPRETER_PROMPT, - CODE_INTERPRETER_PYODIDE_FS_PROMPT, + CODE_INTERPRETER_PYODIDE_PROMPT, CODE_INTERPRETER_BLOCKED_MODULES, ) from open_webui.env import ( @@ -2378,7 +2378,7 @@ async def process_chat_payload(request, form_data, user, metadata, model): # Append filesystem awareness only for pyodide engine if engine != "jupyter": - prompt += CODE_INTERPRETER_PYODIDE_FS_PROMPT + prompt += CODE_INTERPRETER_PYODIDE_PROMPT form_data["messages"] = add_or_update_user_message( prompt, @@ -2389,7 +2389,7 @@ async def process_chat_payload(request, form_data, user, metadata, model): # filesystem context into messages for pyodide engine if engine != "jupyter": form_data["messages"] = add_or_update_user_message( - CODE_INTERPRETER_PYODIDE_FS_PROMPT, + CODE_INTERPRETER_PYODIDE_PROMPT, form_data["messages"], ) From 144d8b1bb78df87661d34aa1d985ca9c50980a06 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:12:35 -0600 Subject: [PATCH 100/114] refac --- backend/open_webui/utils/middleware.py | 113 ++++++++++++++++--------- 1 file changed, 72 insertions(+), 41 deletions(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 389ae9a90b..256b21aa5e 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -890,6 +890,27 @@ def handle_responses_streaming_event( return current_output, None +def get_source_context(sources: list, include_content: bool = True) -> str: + """ + Build tag context string from citation sources. + """ + context_string = "" + citation_idx = {} + for source in sources: + for doc, meta in zip(source.get("document", []), source.get("metadata", [])): + src_id = meta.get("source") or source.get("source", {}).get("id") or "N/A" + if src_id not in citation_idx: + citation_idx[src_id] = len(citation_idx) + 1 + src_name = source.get("source", {}).get("name") + body = doc if include_content else "" + context_string += ( + f'{body}\n" + ) + return context_string + + def apply_source_context_to_messages( request: Request, messages: list, @@ -908,21 +929,7 @@ def apply_source_context_to_messages( if not sources or not user_message: return messages - context_string = "" - citation_idx = {} - - for source in sources: - for doc, meta in zip(source.get("document", []), source.get("metadata", [])): - src_id = meta.get("source") or source.get("source", {}).get("id") or "N/A" - if src_id not in citation_idx: - citation_idx[src_id] = len(citation_idx) + 1 - src_name = source.get("source", {}).get("name") - body = doc if include_content else "" - context_string += ( - f'{body}\n" - ) + context_string = get_source_context(sources, include_content) context_string = context_string.strip() if not context_string: @@ -2741,6 +2748,18 @@ async def tool_function(**kwargs): except Exception as e: log.exception(e) + # Save the pre-RAG message state so the native tool call loop can + # restore to the true original (before file-source injection) rather + # than a snapshot that already has the RAG template baked in. + system_message = get_system_message(form_data["messages"]) + metadata["system_prompt"] = ( + get_content_from_message(system_message) if system_message else None + ) + metadata["user_prompt"] = get_last_user_message( + form_data["messages"] + ) + metadata["sources"] = sources[:] if sources else [] + # If context is not empty, insert it into the messages if sources and prompt: form_data["messages"] = apply_source_context_to_messages( @@ -4202,16 +4221,21 @@ async def flush_pending_delta_data(threshold: int = 0): model.get("info", {}).get("meta", {}).get("capabilities") or {} ).get("citations", True) - # Save original system message so we can restore it before - # re-applying source context (prevents duplication when - # RAG_SYSTEM_CONTEXT is enabled and the template is appended - # to the system message on each iteration). - original_system_message = get_system_message(form_data["messages"]) - original_system_content = ( - get_content_from_message(original_system_message) - if original_system_message - else None + # Use the pre-RAG system content captured before the + # initial file-source injection in process_chat_payload. + # This ensures restore truly undoes the RAG template. + original_system_content = metadata.get( + "system_prompt" ) + if original_system_content is None: + original_system_message = get_system_message( + form_data["messages"] + ) + original_system_content = ( + get_content_from_message(original_system_message) + if original_system_message + else None + ) while ( len(tool_calls) > 0 @@ -4459,33 +4483,40 @@ async def flush_pending_delta_data(threshold: int = 0): } ) - # Emit citation sources and apply source context to messages + # Emit citation sources to the frontend for display if citations_enabled: for source in tool_call_sources: await event_emitter({"type": "source", "data": source}) - # Apply source context to messages for model. - # Use include_content=False to avoid duplicating content - # that is already in the tool result message. + # Apply tool source context to messages for the model. + # Restoring to pre-RAG original prevents duplicating + # the RAG template across file and tool sources. all_tool_call_sources.extend(tool_call_sources) if all_tool_call_sources and user_message: - # Restore original messages before re-applying to - # avoid recursive nesting (user message) and - # duplication (system message with RAG_SYSTEM_CONTEXT). + # Restore pre-RAG message state before re-applying + # to prevent RAG template duplication. + original_user_message = metadata.get( + "user_prompt" + ) or user_message set_last_user_message_content( - user_message, form_data["messages"] + original_user_message, + form_data["messages"], ) - if original_system_content is not None: - replace_system_message_content( - original_system_content, + replace_system_message_content( + original_system_content or "", + form_data["messages"], + ) + + # Combine file and tool sources into one RAG + # template application. + form_data["messages"] = ( + apply_source_context_to_messages( + request, form_data["messages"], + metadata.get("sources", []) + + all_tool_call_sources, + user_message, ) - form_data["messages"] = apply_source_context_to_messages( - request, - form_data["messages"], - all_tool_call_sources, - user_message, - include_content=False, ) tool_call_sources.clear() From 3ceaa107ab51b13795ddbcc35feb41f8bdc5be23 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:14:32 -0600 Subject: [PATCH 101/114] chore: format --- .../8452d01d26d7_add_chat_message_table.py | 54 ++++++++------- backend/open_webui/models/chat_messages.py | 4 +- backend/open_webui/routers/folders.py | 8 ++- backend/open_webui/utils/middleware.py | 51 +++++--------- backend/open_webui/utils/models.py | 4 +- package-lock.json | 4 +- package.json | 4 +- .../admin/Settings/CodeExecution.svelte | 7 +- src/lib/components/chat/Chat.svelte | 2 - src/lib/components/chat/ChatControls.svelte | 4 +- src/lib/components/chat/PyodideFileNav.svelte | 69 ++++++++++++------- src/lib/components/layout/Sidebar.svelte | 8 +-- .../workspace/Models/ModelEditor.svelte | 4 +- src/lib/i18n/locales/ar-BH/translation.json | 6 ++ src/lib/i18n/locales/ar/translation.json | 6 ++ src/lib/i18n/locales/bg-BG/translation.json | 6 ++ src/lib/i18n/locales/bn-BD/translation.json | 6 ++ src/lib/i18n/locales/bo-TB/translation.json | 6 ++ src/lib/i18n/locales/bs-BA/translation.json | 6 ++ src/lib/i18n/locales/ca-ES/translation.json | 6 ++ src/lib/i18n/locales/ceb-PH/translation.json | 6 ++ src/lib/i18n/locales/cs-CZ/translation.json | 6 ++ src/lib/i18n/locales/da-DK/translation.json | 6 ++ src/lib/i18n/locales/de-DE/translation.json | 6 ++ src/lib/i18n/locales/dg-DG/translation.json | 6 ++ src/lib/i18n/locales/el-GR/translation.json | 6 ++ src/lib/i18n/locales/en-GB/translation.json | 6 ++ src/lib/i18n/locales/en-US/translation.json | 7 +- src/lib/i18n/locales/es-ES/translation.json | 6 ++ src/lib/i18n/locales/et-EE/translation.json | 6 ++ src/lib/i18n/locales/eu-ES/translation.json | 6 ++ src/lib/i18n/locales/fa-IR/translation.json | 6 ++ src/lib/i18n/locales/fi-FI/translation.json | 6 ++ src/lib/i18n/locales/fr-CA/translation.json | 6 ++ src/lib/i18n/locales/fr-FR/translation.json | 6 ++ src/lib/i18n/locales/gl-ES/translation.json | 6 ++ src/lib/i18n/locales/he-IL/translation.json | 6 ++ src/lib/i18n/locales/hi-IN/translation.json | 6 ++ src/lib/i18n/locales/hr-HR/translation.json | 6 ++ src/lib/i18n/locales/hu-HU/translation.json | 6 ++ src/lib/i18n/locales/id-ID/translation.json | 6 ++ src/lib/i18n/locales/ie-GA/translation.json | 6 ++ src/lib/i18n/locales/it-IT/translation.json | 6 ++ src/lib/i18n/locales/ja-JP/translation.json | 6 ++ src/lib/i18n/locales/ka-GE/translation.json | 6 ++ src/lib/i18n/locales/kab-DZ/translation.json | 6 ++ src/lib/i18n/locales/ko-KR/translation.json | 6 ++ src/lib/i18n/locales/lt-LT/translation.json | 6 ++ src/lib/i18n/locales/lv-LV/translation.json | 6 ++ src/lib/i18n/locales/ms-MY/translation.json | 6 ++ src/lib/i18n/locales/nb-NO/translation.json | 6 ++ src/lib/i18n/locales/nl-NL/translation.json | 6 ++ src/lib/i18n/locales/pa-IN/translation.json | 6 ++ src/lib/i18n/locales/pl-PL/translation.json | 6 ++ src/lib/i18n/locales/pt-BR/translation.json | 6 ++ src/lib/i18n/locales/pt-PT/translation.json | 6 ++ src/lib/i18n/locales/ro-RO/translation.json | 6 ++ src/lib/i18n/locales/ru-RU/translation.json | 6 ++ src/lib/i18n/locales/sk-SK/translation.json | 6 ++ src/lib/i18n/locales/sr-RS/translation.json | 6 ++ src/lib/i18n/locales/sv-SE/translation.json | 6 ++ src/lib/i18n/locales/th-TH/translation.json | 6 ++ src/lib/i18n/locales/tk-TM/translation.json | 6 ++ src/lib/i18n/locales/tr-TR/translation.json | 6 ++ src/lib/i18n/locales/ug-CN/translation.json | 6 ++ src/lib/i18n/locales/uk-UA/translation.json | 6 ++ src/lib/i18n/locales/ur-PK/translation.json | 6 ++ .../i18n/locales/uz-Cyrl-UZ/translation.json | 6 ++ .../i18n/locales/uz-Latn-Uz/translation.json | 6 ++ src/lib/i18n/locales/vi-VN/translation.json | 6 ++ src/lib/i18n/locales/zh-CN/translation.json | 6 ++ src/lib/i18n/locales/zh-TW/translation.json | 6 ++ src/lib/workers/pyodide.worker.ts | 20 +++--- 73 files changed, 482 insertions(+), 116 deletions(-) diff --git a/backend/open_webui/migrations/versions/8452d01d26d7_add_chat_message_table.py b/backend/open_webui/migrations/versions/8452d01d26d7_add_chat_message_table.py index ea95d08f12..aa9b0a4c26 100644 --- a/backend/open_webui/migrations/versions/8452d01d26d7_add_chat_message_table.py +++ b/backend/open_webui/migrations/versions/8452d01d26d7_add_chat_message_table.py @@ -125,9 +125,9 @@ def upgrade() -> None: # - yield_per: fetches rows in chunks via cursor.fetchmany() (all backends) # - stream_results: enables server-side cursors on PostgreSQL (no-op on SQLite) result = conn.execute( - sa.select(chat_table.c.id, chat_table.c.user_id, chat_table.c.chat).where( - ~chat_table.c.user_id.like("shared-%") - ).execution_options(yield_per=1000, stream_results=True) + sa.select(chat_table.c.id, chat_table.c.user_id, chat_table.c.chat) + .where(~chat_table.c.user_id.like("shared-%")) + .execution_options(yield_per=1000, stream_results=True) ) now = int(time.time()) @@ -175,33 +175,39 @@ def upgrade() -> None: if timestamp < 1577836800 or timestamp > now + 86400: timestamp = now - messages_batch.append({ - "id": f"{chat_id}-{message_id}", - "chat_id": chat_id, - "user_id": user_id, - "role": role, - "parent_id": message.get("parentId"), - "content": message.get("content"), - "output": message.get("output"), - "model_id": message.get("model"), - "files": message.get("files"), - "sources": message.get("sources"), - "embeds": message.get("embeds"), - "done": message.get("done", True), - "status_history": message.get("statusHistory"), - "error": message.get("error"), - "usage": message.get("usage"), - "created_at": timestamp, - "updated_at": timestamp, - }) + messages_batch.append( + { + "id": f"{chat_id}-{message_id}", + "chat_id": chat_id, + "user_id": user_id, + "role": role, + "parent_id": message.get("parentId"), + "content": message.get("content"), + "output": message.get("output"), + "model_id": message.get("model"), + "files": message.get("files"), + "sources": message.get("sources"), + "embeds": message.get("embeds"), + "done": message.get("done", True), + "status_history": message.get("statusHistory"), + "error": message.get("error"), + "usage": message.get("usage"), + "created_at": timestamp, + "updated_at": timestamp, + } + ) # Flush batch when full if len(messages_batch) >= BATCH_SIZE: - inserted, failed = _flush_batch(conn, chat_message_table, messages_batch) + inserted, failed = _flush_batch( + conn, chat_message_table, messages_batch + ) total_inserted += inserted total_failed += failed if total_inserted % 50000 < BATCH_SIZE: - log.info(f"Migration progress: {total_inserted} messages inserted...") + log.info( + f"Migration progress: {total_inserted} messages inserted..." + ) messages_batch.clear() # Flush remaining messages diff --git a/backend/open_webui/models/chat_messages.py b/backend/open_webui/models/chat_messages.py index 4cd868e4d4..b707ab358b 100644 --- a/backend/open_webui/models/chat_messages.py +++ b/backend/open_webui/models/chat_messages.py @@ -296,9 +296,7 @@ def get_chat_ids_by_model_id( # (prevents duplicates across pages when timestamps tie) chat_ids = ( query.group_by(ChatMessage.chat_id) - .order_by( - func.max(ChatMessage.created_at).desc(), ChatMessage.chat_id - ) + .order_by(func.max(ChatMessage.created_at).desc(), ChatMessage.chat_id) .offset(skip) .limit(limit) .all() diff --git a/backend/open_webui/routers/folders.py b/backend/open_webui/routers/folders.py index 602173e4c1..f6269e7b72 100644 --- a/backend/open_webui/routers/folders.py +++ b/backend/open_webui/routers/folders.py @@ -129,7 +129,9 @@ def create_folder( ) try: - folder = Folders.insert_new_folder(user.id, form_data, form_data.parent_id, db=db) + folder = Folders.insert_new_folder( + user.id, form_data, form_data.parent_id, db=db + ) return folder except Exception as e: log.exception(e) @@ -317,7 +319,9 @@ async def delete_folder_by_id( folder = folders.pop() if folder: try: - folder_ids = Folders.delete_folder_by_id_and_user_id(folder.id, user.id, db=db) + folder_ids = Folders.delete_folder_by_id_and_user_id( + folder.id, user.id, db=db + ) for folder_id in folder_ids: if delete_contents: diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 256b21aa5e..40b8dc78a3 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -2248,10 +2248,7 @@ async def process_chat_payload(request, form_data, user, metadata, model): folder.data["system_prompt"], form_data, metadata, user ) if "files" in folder.data: - if ( - metadata.get("params", {}).get("function_calling") - != "native" - ): + if metadata.get("params", {}).get("function_calling") != "native": form_data["files"] = [ *folder.data["files"], *form_data.get("files", []), @@ -2378,8 +2375,7 @@ async def process_chat_payload(request, form_data, user, metadata, model): if metadata.get("params", {}).get("function_calling") != "native": prompt = ( request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE - if request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE - != "" + if request.app.state.config.CODE_INTERPRETER_PROMPT_TEMPLATE != "" else DEFAULT_CODE_INTERPRETER_PROMPT ) @@ -2755,9 +2751,7 @@ async def tool_function(**kwargs): metadata["system_prompt"] = ( get_content_from_message(system_message) if system_message else None ) - metadata["user_prompt"] = get_last_user_message( - form_data["messages"] - ) + metadata["user_prompt"] = get_last_user_message(form_data["messages"]) metadata["sources"] = sources[:] if sources else [] # If context is not empty, insert it into the messages @@ -4200,11 +4194,7 @@ async def flush_pending_delta_data(threshold: int = 0): reasoning_item["status"] = "completed" if response_tool_calls: - tool_calls.append( - _split_tool_calls( - response_tool_calls - ) - ) + tool_calls.append(_split_tool_calls(response_tool_calls)) if response.background: await response.background() @@ -4224,13 +4214,9 @@ async def flush_pending_delta_data(threshold: int = 0): # Use the pre-RAG system content captured before the # initial file-source injection in process_chat_payload. # This ensures restore truly undoes the RAG template. - original_system_content = metadata.get( - "system_prompt" - ) + original_system_content = metadata.get("system_prompt") if original_system_content is None: - original_system_message = get_system_message( - form_data["messages"] - ) + original_system_message = get_system_message(form_data["messages"]) original_system_content = ( get_content_from_message(original_system_message) if original_system_message @@ -4495,9 +4481,9 @@ async def flush_pending_delta_data(threshold: int = 0): if all_tool_call_sources and user_message: # Restore pre-RAG message state before re-applying # to prevent RAG template duplication. - original_user_message = metadata.get( - "user_prompt" - ) or user_message + original_user_message = ( + metadata.get("user_prompt") or user_message + ) set_last_user_message_content( original_user_message, form_data["messages"], @@ -4509,14 +4495,11 @@ async def flush_pending_delta_data(threshold: int = 0): # Combine file and tool sources into one RAG # template application. - form_data["messages"] = ( - apply_source_context_to_messages( - request, - form_data["messages"], - metadata.get("sources", []) - + all_tool_call_sources, - user_message, - ) + form_data["messages"] = apply_source_context_to_messages( + request, + form_data["messages"], + metadata.get("sources", []) + all_tool_call_sources, + user_message, ) tool_call_sources.clear() @@ -4588,8 +4571,7 @@ async def flush_pending_delta_data(threshold: int = 0): code = sanitize_code(code) if CODE_INTERPRETER_BLOCKED_MODULES: - blocking_code = textwrap.dedent( - f""" + blocking_code = textwrap.dedent(f""" import builtins BLOCKED_MODULES = {CODE_INTERPRETER_BLOCKED_MODULES} @@ -4605,8 +4587,7 @@ def restricted_import(name, globals=None, locals=None, fromlist=(), level=0): return _real_import(name, globals, locals, fromlist, level) builtins.__import__ = restricted_import - """ - ) + """) code = blocking_code + "\n" + code if ( diff --git a/backend/open_webui/utils/models.py b/backend/open_webui/utils/models.py index cb5865d88c..108cd0b4b0 100644 --- a/backend/open_webui/utils/models.py +++ b/backend/open_webui/utils/models.py @@ -199,7 +199,9 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) base_model = base_model_lookup.get(custom_model.base_model_id) if base_model is None: - base_model = base_model_lookup.get(custom_model.base_model_id.split(":")[0]) + base_model = base_model_lookup.get( + custom_model.base_model_id.split(":")[0] + ) if base_model: owned_by = base_model.get("owned_by", "unknown") if "pipe" in base_model: diff --git a/package-lock.json b/package-lock.json index 8f5599767c..5a359dd054 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "open-webui", - "version": "0.8.8", + "version": "0.8.9", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "open-webui", - "version": "0.8.8", + "version": "0.8.9", "dependencies": { "@azure/msal-browser": "^4.5.0", "@codemirror/lang-javascript": "^6.2.2", diff --git a/package.json b/package.json index 0e30237aee..49a72efa37 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-webui", - "version": "0.8.8", + "version": "0.8.9", "private": true, "scripts": { "dev": "npm run pyodide:fetch && vite dev --host", @@ -158,4 +158,4 @@ "node": ">=18.13.0 <=22.x.x", "npm": ">=6.0.0" } -} \ No newline at end of file +} diff --git a/src/lib/components/admin/Settings/CodeExecution.svelte b/src/lib/components/admin/Settings/CodeExecution.svelte index cad7970de1..6195672869 100644 --- a/src/lib/components/admin/Settings/CodeExecution.svelte +++ b/src/lib/components/admin/Settings/CodeExecution.svelte @@ -67,7 +67,8 @@ > {#each engines as engine} - + {/each}
@@ -193,7 +194,9 @@ > {#each engines as engine} - + {/each}
diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index b391cd1a51..8ea8641f39 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -148,8 +148,6 @@ let webSearchEnabled = false; let codeInterpreterEnabled = false; - - let showCommands = false; let generating = false; diff --git a/src/lib/components/chat/ChatControls.svelte b/src/lib/components/chat/ChatControls.svelte index f5957e40e4..aea9fa83cf 100644 --- a/src/lib/components/chat/ChatControls.svelte +++ b/src/lib/components/chat/ChatControls.svelte @@ -71,7 +71,9 @@ $: hasMessages = history?.messages && Object.keys(history.messages).length > 0; $: showControlsTab = $user?.role === 'admin' || ($user?.permissions?.chat?.controls ?? true); - $: showFilesTab = !!$selectedTerminalId || (codeInterpreterEnabled && $config?.code?.interpreter_engine !== 'jupyter'); + $: showFilesTab = + !!$selectedTerminalId || + (codeInterpreterEnabled && $config?.code?.interpreter_engine !== 'jupyter'); $: showOverviewTab = hasMessages; // Tab fallback: if active tab becomes hidden, switch to next available diff --git a/src/lib/components/chat/PyodideFileNav.svelte b/src/lib/components/chat/PyodideFileNav.svelte index 3afbd7bbe4..73a10325d0 100644 --- a/src/lib/components/chat/PyodideFileNav.svelte +++ b/src/lib/components/chat/PyodideFileNav.svelte @@ -108,7 +108,10 @@ savedPyodidePath = currentPath; try { - const res = await sendWorkerMessage({ type: 'fs:list', path: currentPath.replace(/\/$/, '') || '/' }); + const res = await sendWorkerMessage({ + type: 'fs:list', + path: currentPath.replace(/\/$/, '') || '/' + }); entries = (res.entries || []).sort((a: FileEntry, b: FileEntry) => { if (a.type !== b.type) return a.type === 'directory' ? -1 : 1; return a.name.localeCompare(b.name); @@ -247,7 +250,11 @@ payloads.push({ name: file.name, data: await file.arrayBuffer() }); } try { - await sendWorkerMessage({ type: 'fs:upload', files: payloads, dir: currentPath.replace(/\/$/, '') || '/' }); + await sendWorkerMessage({ + type: 'fs:upload', + files: payloads, + dir: currentPath.replace(/\/$/, '') || '/' + }); } catch (e) { console.error('Upload failed:', e); } @@ -347,9 +354,18 @@ on:click={() => selectedFile && downloadFile(selectedFile)} aria-label={$i18n.t('Download')} > - - - + + + @@ -370,13 +395,7 @@
{#if selectedFile} - + {:else if loading}
@@ -435,17 +454,17 @@ {/if} {#if entries.length > 0 || creatingFolder || creatingFile} -
    - {#each entries as entry (entry.name)} - - {/each} -
+
    + {#each entries as entry (entry.name)} + + {/each} +
{/if} {/if}
diff --git a/src/lib/components/layout/Sidebar.svelte b/src/lib/components/layout/Sidebar.svelte index 27e03a7869..253ba18ded 100644 --- a/src/lib/components/layout/Sidebar.svelte +++ b/src/lib/components/layout/Sidebar.svelte @@ -150,16 +150,12 @@ } // Check for duplicate names in the same parent - const siblings = Object.values(folders).filter( - (folder) => folder.parent_id === parent_id - ); + const siblings = Object.values(folders).filter((folder) => folder.parent_id === parent_id); if (siblings.find((folder) => folder.name.toLowerCase() === name.toLowerCase())) { // If a folder with the same name already exists, append a number to the name let i = 1; while ( - siblings.find( - (folder) => folder.name.toLowerCase() === `${name} ${i}`.toLowerCase() - ) + siblings.find((folder) => folder.name.toLowerCase() === `${name} ${i}`.toLowerCase()) ) { i++; } diff --git a/src/lib/components/workspace/Models/ModelEditor.svelte b/src/lib/components/workspace/Models/ModelEditor.svelte index 8978c0c00a..9deeff1027 100644 --- a/src/lib/components/workspace/Models/ModelEditor.svelte +++ b/src/lib/components/workspace/Models/ModelEditor.svelte @@ -219,8 +219,8 @@ info.params.system = system.trim() === '' ? null : system; info.params.stop = params.stop - ? (typeof params.stop === 'string' ? params.stop.split(',') : params.stop).filter( - (s) => s.trim() + ? (typeof params.stop === 'string' ? params.stop.split(',') : params.stop).filter((s) => + s.trim() ) : null; Object.keys(info.params).forEach((key) => { diff --git a/src/lib/i18n/locales/ar-BH/translation.json b/src/lib/i18n/locales/ar-BH/translation.json index 3adfdfc6d5..dff6be6fe7 100644 --- a/src/lib/i18n/locales/ar-BH/translation.json +++ b/src/lib/i18n/locales/ar-BH/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "الإفتراضي صلاحيات المستخدم", "Defaults": "", "Delete": "حذف", + "Delete {{name}}": "", "Delete a model": "حذف الموديل", "Delete All": "", "Delete All Chats": "حذف جميع الدردشات", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "e.g. '30s','10m'. الوحدات الزمنية الصالحة هي 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com \"{{searchValue}}\" أسحب من ", "Pull a model from Ollama.com": "Ollama.com سحب الموديل من ", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/ar/translation.json b/src/lib/i18n/locales/ar/translation.json index 4d6927b51c..c98f286a19 100644 --- a/src/lib/i18n/locales/ar/translation.json +++ b/src/lib/i18n/locales/ar/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "هل أنت متأكد من رغبتك في حذف هذه القناة؟", "Are you sure you want to delete this message?": "هل أنت متأكد من رغبتك في حذف هذه الرسالة؟", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "هل أنت متأكد من رغبتك في إلغاء أرشفة جميع المحادثات المؤرشفة؟", "Arena Models": "نماذج الساحة", "Artifacts": "القطع الأثرية", @@ -486,6 +487,7 @@ "Default User Role": "الإفتراضي صلاحيات المستخدم", "Defaults": "", "Delete": "حذف", + "Delete {{name}}": "", "Delete a model": "حذف الموديل", "Delete All": "", "Delete All Chats": "حذف جميع الدردشات", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "ارسم", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "e.g. '30s','10m'. الوحدات الزمنية الصالحة هي 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "تم حذف المجلد بنجاح", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "لم يتم تحديد ملف", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com \"{{searchValue}}\" أسحب من ", "Pull a model from Ollama.com": "Ollama.com سحب الموديل من ", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "توجيه إنشاء الاستعلام", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/bg-BG/translation.json b/src/lib/i18n/locales/bg-BG/translation.json index f6792cb8fd..9d1d0ec7a1 100644 --- a/src/lib/i18n/locales/bg-BG/translation.json +++ b/src/lib/i18n/locales/bg-BG/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Сигурни ли сте, че искате да изтриете този канал?", "Are you sure you want to delete this message?": "Сигурни ли сте, че искате да изтриете това съобщение?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Сигурни ли сте, че искате да разархивирате всички архивирани чатове?", "Arena Models": "Арена Модели", "Artifacts": "Артефакти", @@ -486,6 +487,7 @@ "Default User Role": "Ролята на потребителя по подразбиране", "Defaults": "", "Delete": "Изтриване", + "Delete {{name}}": "", "Delete a model": "Изтриване на модела", "Delete All": "", "Delete All Chats": "Изтриване на всички чатове", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Рисуване", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "напр. '30с','10м'. Валидни единици са 'с', 'м', 'ч'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Папката е изтрита успешно", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Не е избран файл", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Извади \"{{searchValue}}\" от Ollama.com", "Pull a model from Ollama.com": "Издърпайте модела от Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Промпт за генериране на запитвания", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/bn-BD/translation.json b/src/lib/i18n/locales/bn-BD/translation.json index a348795018..df3b6aaea8 100644 --- a/src/lib/i18n/locales/bn-BD/translation.json +++ b/src/lib/i18n/locales/bn-BD/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "ইউজারের ডিফল্ট পদবি", "Defaults": "", "Delete": "মুছে ফেলুন", + "Delete {{name}}": "", "Delete a model": "একটি মডেল মুছে ফেলুন", "Delete All": "", "Delete All Chats": "সব চ্যাট মুছে ফেলুন", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "যেমন '30s','10m'. সময়ের অনুমোদিত অনুমোদিত এককগুলি হচ্ছে 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com থেকে \"{{searchValue}}\" টানুন", "Pull a model from Ollama.com": "Ollama.com থেকে একটি টেনে আনুন আনুন", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/bo-TB/translation.json b/src/lib/i18n/locales/bo-TB/translation.json index 8288ca9fcc..6a4fe45090 100644 --- a/src/lib/i18n/locales/bo-TB/translation.json +++ b/src/lib/i18n/locales/bo-TB/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "ཁྱེད་ཀྱིས་བགྲོ་གླེང་འདི་བསུབ་འདོད་ངེས་ཡིན་ནམ།", "Are you sure you want to delete this message?": "འཕྲིན་འདི་བསུབ་འདོད་ངེས་ཡིན་ནམ།", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "ཁྱེད་ཀྱིས་ཡིག་མཛོད་དུ་བཞག་པའི་ཁ་བརྡ་ཡོངས་རྫོགས་ཕྱིར་འདོན་འདོད་ངེས་ཡིན་ནམ།", "Arena Models": "Arena དཔེ་དབྱིབས།", "Artifacts": "རྫས་རྟེན།", @@ -486,6 +487,7 @@ "Default User Role": "སྔོན་སྒྲིག་བེད་སྤྱོད་མཁན་གྱི་གནས་ཚད།", "Defaults": "", "Delete": "བསུབ་པ།", + "Delete {{name}}": "", "Delete a model": "དཔེ་དབྱིབས་ཤིག་བསུབ་པ།", "Delete All": "", "Delete All Chats": "ཁ་བརྡ་ཡོངས་རྫོགས་བསུབ་པ།", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "རི་མོ་འབྲི་བ།", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "དཔེར་ན། '30s','10m'. ནུས་ལྡན་དུས་ཚོད་ཀྱི་ཚན་པ་ནི། 's', 'm', 'h' ཡིན།", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "ཡིག་སྣོད་ལེགས་པར་བསུབས་ཟིན།", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "ཡིག་ཆ་གདམ་ག་མ་བྱས།", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com ནས་ \"{{searchValue}}\" འཐེན་པ།", "Pull a model from Ollama.com": "Ollama.com ནས་དཔེ་དབྱིབས་ཤིག་འཐེན་པ།", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "འདྲི་བ་བཟོ་སྐྲུན་གྱི་འགུལ་སློང་།", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/bs-BA/translation.json b/src/lib/i18n/locales/bs-BA/translation.json index bc8773f0d1..a62d7e5d24 100644 --- a/src/lib/i18n/locales/bs-BA/translation.json +++ b/src/lib/i18n/locales/bs-BA/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "Zadana korisnička uloga", "Defaults": "", "Delete": "Izbriši", + "Delete {{name}}": "", "Delete a model": "Izbriši model", "Delete All": "", "Delete All Chats": "Izbriši sve razgovore", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "npr. '30s','10m'. Važeće vremenske jedinice su 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Povucite \"{{searchValue}}\" s Ollama.com", "Pull a model from Ollama.com": "Povucite model s Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/ca-ES/translation.json b/src/lib/i18n/locales/ca-ES/translation.json index b1b621ebfe..89228d5a78 100644 --- a/src/lib/i18n/locales/ca-ES/translation.json +++ b/src/lib/i18n/locales/ca-ES/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Estàs segur que vols eliminar aquest canal?", "Are you sure you want to delete this message?": "Estàs segur que vols eliminar aquest missatge?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Estàs segur que vols suprimir aquesta versió? Les versions filles es tornaran a enllaçar amb la versió principal d'aquesta versió.", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Estàs segur que vols desarxivar tots els xats arxivats?", "Arena Models": "Models de l'Arena", "Artifacts": "Artefactes", @@ -486,6 +487,7 @@ "Default User Role": "Rol d'usuari per defecte", "Defaults": "Valors per defecte", "Delete": "Eliminar", + "Delete {{name}}": "", "Delete a model": "Eliminar un model", "Delete All": "Eliminar tot", "Delete All Chats": "Eliminar tots els xats", @@ -578,6 +580,7 @@ "Downloading stats...": "Descarregant estadístiques...", "Draw": "Dibuixar", "Drop any files here to upload": "Arrossega aquí qualsevol fitxer per pujar-lo", + "Drop files here": "", "Drop files here to upload": "Deixa anar els arxius aquí per pujar-los", "DuckDuckGo": "DuckDuckGo", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "p. ex. '30s','10m'. Les unitats de temps vàlides són 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "Posa el focus en l'entrada del xat", "Folder": "Carpeta", "Folder Background Image": "Imatge del fons de la carpeta", + "Folder created successfully": "", "Folder deleted successfully": "Carpeta eliminada correctament", "Folder Max File Count": "Nombre màxim d'arxius per carpeta", "Folder name": "Nom de carpeta", @@ -1304,6 +1308,7 @@ "No file selected": "No s'ha escollit cap fitxer", "No files found": "No s'han trobat arxius", "No files in this knowledge base.": "No hi ha arxius a la base de coneixement.", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "No s'han trobat funcions", "No groups found": "No s'han trobat grups", "No history available": "No hi ha historial disponible", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Obtenir \"{{searchValue}}\" de Ollama.com", "Pull a model from Ollama.com": "Obtenir un model d'Ollama.com", "Pull Model": "Obtenir un model", + "Pyodide file browser": "", "Query Generation Prompt": "Indicació per a generació de consulta", "Querying": "Consultes", "Quick Actions": "Accions ràpides", diff --git a/src/lib/i18n/locales/ceb-PH/translation.json b/src/lib/i18n/locales/ceb-PH/translation.json index 098776cc6d..b0ff5202f2 100644 --- a/src/lib/i18n/locales/ceb-PH/translation.json +++ b/src/lib/i18n/locales/ceb-PH/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "Default nga Papel sa Gumagamit", "Defaults": "", "Delete": "", + "Delete {{name}}": "", "Delete a model": "Pagtangtang sa usa ka template", "Delete All": "", "Delete All Chats": "", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "p. ", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "", "Pull a model from Ollama.com": "Pagkuha ug template gikan sa Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/cs-CZ/translation.json b/src/lib/i18n/locales/cs-CZ/translation.json index e3d2f4ba85..8941640667 100644 --- a/src/lib/i18n/locales/cs-CZ/translation.json +++ b/src/lib/i18n/locales/cs-CZ/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Opravdu chcete smazat tento kanál?", "Are you sure you want to delete this message?": "Opravdu chcete smazat tuto zprávu?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Opravdu chcete zrušit archivaci všech archivovaných konverzací?", "Arena Models": "Modely pro arénu", "Artifacts": "Artefakty", @@ -486,6 +487,7 @@ "Default User Role": "Výchozí role uživatele", "Defaults": "", "Delete": "Smazat", + "Delete {{name}}": "", "Delete a model": "Smazat model", "Delete All": "", "Delete All Chats": "Smazat všechny konverzace", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Kreslit", "Drop any files here to upload": "Přetáhněte sem soubory pro nahrání", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "např. '30s','10m'. Platné časové jednotky jsou 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "Složka", "Folder Background Image": "Obrázek na pozadí složky", + "Folder created successfully": "", "Folder deleted successfully": "Složka byla úspěšně smazána", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Nebyl vybrán žádný soubor", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "Žádné funkce nenalezeny", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Stáhnout \"{{searchValue}}\" z Ollama.com", "Pull a model from Ollama.com": "Stáhnout model z Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Instrukce pro generování dotazu", "Querying": "", "Quick Actions": "Rychlé akce", diff --git a/src/lib/i18n/locales/da-DK/translation.json b/src/lib/i18n/locales/da-DK/translation.json index ecb07cafa5..27e62191dc 100644 --- a/src/lib/i18n/locales/da-DK/translation.json +++ b/src/lib/i18n/locales/da-DK/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Er du sikker på du vil slette denne kanal?", "Are you sure you want to delete this message?": "Er du sikker på du vil slette denne besked?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Er du sikker på du vil fjerne alle arkiverede chats?", "Arena Models": "Arena Modeller", "Artifacts": "Artifakter", @@ -486,6 +487,7 @@ "Default User Role": "Brugers rolle som standard", "Defaults": "", "Delete": "Slet", + "Delete {{name}}": "", "Delete a model": "Slet en model", "Delete All": "", "Delete All Chats": "Slet alle chats", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Tegn", "Drop any files here to upload": "Drop nogen filer her for at uploade", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "f.eks. '30s', '10m'. Tilladte værdier er 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "Fokus chat-input", "Folder": "Mappe", "Folder Background Image": "Mappe baggrundsbillede", + "Folder created successfully": "", "Folder deleted successfully": "Mappe fjernet.", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Ingen fil valgt", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "Ingen funktioner fundet", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Hent \"{{searchValue}}\" fra Ollama.com", "Pull a model from Ollama.com": "Hent en model fra Ollama.com", "Pull Model": "Hent model", + "Pyodide file browser": "", "Query Generation Prompt": "Forespørgsel genererings prompt", "Querying": "Undersøger", "Quick Actions": "Hurtig-handlinger", diff --git a/src/lib/i18n/locales/de-DE/translation.json b/src/lib/i18n/locales/de-DE/translation.json index 94d544d1bf..673bcaaba4 100644 --- a/src/lib/i18n/locales/de-DE/translation.json +++ b/src/lib/i18n/locales/de-DE/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Sind Sie sicher, dass Sie diesen Kanal löschen möchten?", "Are you sure you want to delete this message?": "Sind Sie sicher, dass Sie diese Nachricht löschen möchten?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Sind Sie sicher, dass Sie diese Version löschen wollen? Child-Versionen werden zu dem Parent dieser Version verlinkt.", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Sind Sie sicher, dass Sie alle archivierten Chats wiederherstellen möchten?", "Arena Models": "Arena-Modelle", "Artifacts": "Artefakte", @@ -486,6 +487,7 @@ "Default User Role": "Standard-Benutzerrolle", "Defaults": "Standardwerte", "Delete": "Löschen", + "Delete {{name}}": "", "Delete a model": "Ein Modell löschen", "Delete All": "Alle löschen", "Delete All Chats": "Alle Chats löschen", @@ -578,6 +580,7 @@ "Downloading stats...": "Statistik wird heruntergeladen...", "Draw": "Zeichnen", "Drop any files here to upload": "Dateien zum Hochladen hier ablegen", + "Drop files here": "", "Drop files here to upload": "Dateien zum Hochladen hier fallen lassen", "DuckDuckGo": "DuckDuckGo", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "z. B. '30s', '10m'. Gültig: 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "Chat-Eingabe fokussieren", "Folder": "Ordner", "Folder Background Image": "Ordner-Hintergrundbild", + "Folder created successfully": "", "Folder deleted successfully": "Ordner erfolgreich gelöscht", "Folder Max File Count": "Maximale Dateianzahl pro Ordner", "Folder name": "Ordnername", @@ -1304,6 +1308,7 @@ "No file selected": "Keine Datei ausgewählt", "No files found": "Keine Dateien gefunden", "No files in this knowledge base.": "Keine Dateien in diesem Wissensspeicher", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "Keine Funktionen gefunden", "No groups found": "Keine Gruppen gefunden", "No history available": "Keine History verfügbar", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "\"{{searchValue}}\" von Ollama.com laden", "Pull a model from Ollama.com": "Ein Modell von Ollama.com laden", "Pull Model": "Modell laden", + "Pyodide file browser": "", "Query Generation Prompt": "Abfrage-Generierungs-Prompt", "Querying": "Frage ab...", "Quick Actions": "Schnellaktionen", diff --git a/src/lib/i18n/locales/dg-DG/translation.json b/src/lib/i18n/locales/dg-DG/translation.json index f530299954..8774cee65e 100644 --- a/src/lib/i18n/locales/dg-DG/translation.json +++ b/src/lib/i18n/locales/dg-DG/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "Default User Role", "Defaults": "", "Delete": "", + "Delete {{name}}": "", "Delete a model": "Delete a model", "Delete All": "", "Delete All Chats": "", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "e.g. '30s','10m'. Much time units are 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "", "Pull a model from Ollama.com": "Pull a wowdel from Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/el-GR/translation.json b/src/lib/i18n/locales/el-GR/translation.json index 66db5bd86c..21441dc201 100644 --- a/src/lib/i18n/locales/el-GR/translation.json +++ b/src/lib/i18n/locales/el-GR/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό το κανάλι;", "Are you sure you want to delete this message?": "Είστε σίγουροι ότι θέλετε να διαγράψετε αυτό το μήνυμα;", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Είστε σίγουροι ότι θέλετε να απο-αρχειοθετήσετε όλες τις αρχειοθετημένες συνομιλίες;", "Arena Models": "Μοντέλα Arena", "Artifacts": "Αρχεία", @@ -486,6 +487,7 @@ "Default User Role": "Προεπιλεγμένος Ρόλος Χρήστη", "Defaults": "", "Delete": "Διαγραφή", + "Delete {{name}}": "", "Delete a model": "Διαγραφή ενός μοντέλου", "Delete All": "", "Delete All Chats": "Διαγραφή Όλων των Συνομιλιών", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Σχεδίαση", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "π.χ. '30s','10m'. Οι έγκυρες μονάδες χρόνου είναι 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "Φάκελος", "Folder Background Image": "Εικόνα Φόντου Φακέλου", + "Folder created successfully": "", "Folder deleted successfully": "Ο φάκελος διαγράφηκε με επιτυχία", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Δεν έχει επιλεγεί αρχείο", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "Δεν βρέθηκαν λειτουργίες", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Τραβήξτε \"{{searchValue}}\" από το Ollama.com", "Pull a model from Ollama.com": "Τραβήξτε ένα μοντέλο από το Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Προτροπή Δημιουργίας Ερωτήσεων", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/en-GB/translation.json b/src/lib/i18n/locales/en-GB/translation.json index 4cc97d93cd..06b8ac6a1c 100644 --- a/src/lib/i18n/locales/en-GB/translation.json +++ b/src/lib/i18n/locales/en-GB/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "", "Defaults": "", "Delete": "", + "Delete {{name}}": "", "Delete a model": "", "Delete All": "", "Delete All Chats": "", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "", "Pull a model from Ollama.com": "", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index ae23cad549..77d52c6446 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "", "Defaults": "", "Delete": "", + "Delete {{name}}": "", "Delete a model": "", "Delete All": "", "Delete All Chats": "", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "", @@ -1305,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1512,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "", "Pull a model from Ollama.com": "", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", @@ -2136,4 +2141,4 @@ "YouTube": "", "Youtube Language": "", "Youtube Proxy URL": "" -} \ No newline at end of file +} diff --git a/src/lib/i18n/locales/es-ES/translation.json b/src/lib/i18n/locales/es-ES/translation.json index d9877b5d3b..76765f0047 100644 --- a/src/lib/i18n/locales/es-ES/translation.json +++ b/src/lib/i18n/locales/es-ES/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "¿Seguro de que quieres eliminar este canal?", "Are you sure you want to delete this message?": "¿Seguro de que quieres eliminar este mensaje? ", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "¿Seguro que desea eliminar esta versión? Las versiones secundarias se vincularán a la versión principal de esta.", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "¿Seguro de que quieres desarchivar todos los chats archivados?", "Arena Models": "Arena de Modelos", "Artifacts": "Artefactos", @@ -486,6 +487,7 @@ "Default User Role": "Rol predeterminado de los nuevos usuarios", "Defaults": "Predeterminados", "Delete": "Borrar", + "Delete {{name}}": "", "Delete a model": "Borrar un modelo", "Delete All": "Borrar Todo", "Delete All Chats": "Borrar todos los chats", @@ -578,6 +580,7 @@ "Downloading stats...": "Descargando estadísticas...", "Draw": "Dibujar", "Drop any files here to upload": "Arrastra aquí los archivos a subir.", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "DuckDuckGo", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "p.ej. '30s','10m'. Unidades de tiempo válidas son 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "Enfocar a la Entrada del Chat", "Folder": "Carpeta", "Folder Background Image": "Imagen de Fondo de la Carpeta", + "Folder created successfully": "", "Folder deleted successfully": "Carpeta eliminada correctamente", "Folder Max File Count": "Máximo Número de Ficheros en Carpeta", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "No se seleccionó archivo", "No files found": "No se encontraron archivos", "No files in this knowledge base.": "Ningún archivo en esta base de conocimiento.", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "No se encontraron funciones", "No groups found": "No se encontraron grupos", "No history available": "No hay historial disponible", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Extraer \"{{searchValue}}\" desde Ollama.com", "Pull a model from Ollama.com": "Extraer un modelo desde Ollama.com", "Pull Model": "Extraer Modelo", + "Pyodide file browser": "", "Query Generation Prompt": "Indicador para la Consulta de Generación", "Querying": "Consultando", "Quick Actions": "Acciones Rápida", diff --git a/src/lib/i18n/locales/et-EE/translation.json b/src/lib/i18n/locales/et-EE/translation.json index b133d638e7..535e195b29 100644 --- a/src/lib/i18n/locales/et-EE/translation.json +++ b/src/lib/i18n/locales/et-EE/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Kas olete kindel, et soovite selle kanali kustutada?", "Are you sure you want to delete this message?": "Kas olete kindel, et soovite selle sõnumi kustutada?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Kas olete kindel, et soovite kõik arhiveeritud vestlused arhiivist eemaldada?", "Arena Models": "Areena mudelid", "Artifacts": "Tekkinud objektid", @@ -486,6 +487,7 @@ "Default User Role": "Vaikimisi kasutaja roll", "Defaults": "", "Delete": "Kustuta", + "Delete {{name}}": "", "Delete a model": "Kustuta mudel", "Delete All": "", "Delete All Chats": "Kustuta kõik vestlused", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Joonista", "Drop any files here to upload": "Lohistage siia failid üleslaadimiseks", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "nt '30s', '10m'. Kehtivad ajaühikud on 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "Kaust", "Folder Background Image": "Kausta taustpilt", + "Folder created successfully": "", "Folder deleted successfully": "Kaust edukalt kustutatud", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Faili pole valitud", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "No functions found", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Tõmba \"{{searchValue}}\" Ollama.com-ist", "Pull a model from Ollama.com": "Tõmba mudel Ollama.com-ist", "Pull Model": "Pull Mudel", + "Pyodide file browser": "", "Query Generation Prompt": "Päringu genereerimise vihje", "Querying": "Querying", "Quick Actions": "Quick Actions", diff --git a/src/lib/i18n/locales/eu-ES/translation.json b/src/lib/i18n/locales/eu-ES/translation.json index 117a260c60..d46fe503b7 100644 --- a/src/lib/i18n/locales/eu-ES/translation.json +++ b/src/lib/i18n/locales/eu-ES/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Ziur zaude artxibatutako txat guztiak desartxibatu nahi dituzula?", "Arena Models": "Arena Ereduak", "Artifacts": "Artefaktuak", @@ -486,6 +487,7 @@ "Default User Role": "Erabiltzaile Rol Lehenetsia", "Defaults": "", "Delete": "Ezabatu", + "Delete {{name}}": "", "Delete a model": "Ezabatu eredu bat", "Delete All": "", "Delete All Chats": "Ezabatu Txat Guztiak", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Marraztu", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "adib. '30s','10m'. Denbora unitate baliodunak dira 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Karpeta ongi ezabatu da", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Ez da fitxategirik hautatu", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ekarri \"{{searchValue}}\" Ollama.com-etik", "Pull a model from Ollama.com": "Ekarri modelo bat Ollama.com-etik", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Kontsulta sortzeko prompt-a", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/fa-IR/translation.json b/src/lib/i18n/locales/fa-IR/translation.json index 1bc4077445..f01fb5f7a5 100644 --- a/src/lib/i18n/locales/fa-IR/translation.json +++ b/src/lib/i18n/locales/fa-IR/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "آیا مطمئن هستید که می\u200cخواهید این کانال را حذف کنید؟", "Are you sure you want to delete this message?": "آیا مطمئن هستید که می\u200cخواهید این پیام را حذف کنید؟", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "آیا مطمئن هستید که می\u200cخواهید همه گفتگوهای بایگانی شده را از بایگانی خارج کنید؟", "Arena Models": "مدل\u200cهای آرنا", "Artifacts": "مصنوعات", @@ -486,6 +487,7 @@ "Default User Role": "نقش کاربر پیش فرض", "Defaults": "", "Delete": "حذف", + "Delete {{name}}": "", "Delete a model": "حذف یک مدل", "Delete All": "", "Delete All Chats": "حذف همه گفتگوها", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "رسم کردن", "Drop any files here to upload": "فایل\u200cها را برای آپلود به اینجا بکشید و رها کنید", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "به طور مثال '30s','10m'. واحد\u200cهای زمانی معتبر 's', 'm', 'h' هستند.", @@ -897,6 +900,7 @@ "Focus Chat Input": "فوکوس روی ورودی چت", "Folder": "پوشه", "Folder Background Image": "تصویر پس\u200cزمینه پوشه", + "Folder created successfully": "", "Folder deleted successfully": "پوشه با موفقیت حذف شد", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "فایلی انتخاب نشده است", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "هیچ تابعی یافت نشد", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "بازگرداندن \"{{searchValue}}\" از Ollama.com", "Pull a model from Ollama.com": "دریافت یک مدل از Ollama.com", "Pull Model": "کشیدن مدل", + "Pyodide file browser": "", "Query Generation Prompt": "پرامپت تولید کوئری", "Querying": "در حال پرس\u200cوجو", "Quick Actions": "اقدامات سریع", diff --git a/src/lib/i18n/locales/fi-FI/translation.json b/src/lib/i18n/locales/fi-FI/translation.json index 78d02d0aa2..a3a549fba2 100644 --- a/src/lib/i18n/locales/fi-FI/translation.json +++ b/src/lib/i18n/locales/fi-FI/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Haluatko varmasti poistaa tämän kanavan?", "Are you sure you want to delete this message?": "Haluatko varmasti poistaa tämän viestin?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Haluatko varamsti poistaa tämän version? Alaversiot linkitetään uudelleen tämän version ylätason versioon.", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Haluatko varmasti purkaa kaikkien arkistoitujen keskustelujen arkistoinnin?", "Arena Models": "Arena-mallit", "Artifacts": "Artefaktit", @@ -486,6 +487,7 @@ "Default User Role": "Oletuskäyttäjärooli", "Defaults": "Oletukset", "Delete": "Poista", + "Delete {{name}}": "", "Delete a model": "Poista malli", "Delete All": "Poista kaikki", "Delete All Chats": "Poista kaikki keskustelut", @@ -578,6 +580,7 @@ "Downloading stats...": "Ladataa tilastoja...", "Draw": "Piirros", "Drop any files here to upload": "Pudota tähän ladattavat tiedostot", + "Drop files here": "", "Drop files here to upload": "Pudota tiedostot tähän ladataksesi", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "esim. '30s', '10m'. Kelpoiset aikayksiköt ovat 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "Kohdista keskustelu tekstikenttään", "Folder": "Kansio", "Folder Background Image": "Kansion taustakuva", + "Folder created successfully": "", "Folder deleted successfully": "Kansio poistettu onnistuneesti", "Folder Max File Count": "Kansion tiedostojen enimmäismäärä", "Folder name": "Kansion nimi", @@ -1304,6 +1308,7 @@ "No file selected": "Tiedostoa ei ole valittu", "No files found": "Tiedostoja ei löytynyt", "No files in this knowledge base.": "Tässä tietokannassa ei ole tiedostoja.", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "Funktioita ei löytynyt", "No groups found": "Ryhmiä ei löytynyt", "No history available": "Historiaa ei saatavilla", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Lataa \"{{searchValue}}\" Ollama.comista", "Pull a model from Ollama.com": "Lataa malli Ollama.comista", "Pull Model": "Lataa malli", + "Pyodide file browser": "", "Query Generation Prompt": "Kyselytulosten luontikehote", "Querying": "Kysely", "Quick Actions": "Pikatoiminnot", diff --git a/src/lib/i18n/locales/fr-CA/translation.json b/src/lib/i18n/locales/fr-CA/translation.json index d7a80ee90b..903522f047 100644 --- a/src/lib/i18n/locales/fr-CA/translation.json +++ b/src/lib/i18n/locales/fr-CA/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Êtes-vous sûr de vouloir supprimer ce canal ?", "Are you sure you want to delete this message?": "Êtes-vous sûr de vouloir supprimer ce message ?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Êtes-vous sûr de vouloir désarchiver toutes les conversations archivées?", "Arena Models": "Modèles d'arène", "Artifacts": "Artéfacts", @@ -486,6 +487,7 @@ "Default User Role": "Rôle utilisateur par défaut", "Defaults": "", "Delete": "Supprimer", + "Delete {{name}}": "", "Delete a model": "Supprimer un modèle", "Delete All": "", "Delete All Chats": "Supprimer toutes les conversations", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Match nul", "Drop any files here to upload": "Déposez des fichiers ici pour les téléverser", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "par ex. '30s', '10 min'. Les unités de temps valides sont 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Dossier supprimé avec succès", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Aucun fichier sélectionné", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Récupérer « {{searchValue}} » depuis Ollama.com", "Pull a model from Ollama.com": "Télécharger un modèle depuis Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Prompt de génération de requête", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/fr-FR/translation.json b/src/lib/i18n/locales/fr-FR/translation.json index c123b3d967..a226b43bc5 100644 --- a/src/lib/i18n/locales/fr-FR/translation.json +++ b/src/lib/i18n/locales/fr-FR/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Êtes-vous sûr de vouloir supprimer ce canal ?", "Are you sure you want to delete this message?": "Êtes-vous sûr de vouloir supprimer ce message ?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Êtes-vous sûr de vouloir désarchiver toutes les conversations ?", "Arena Models": "Modèles d'arène", "Artifacts": "Artéfacts", @@ -486,6 +487,7 @@ "Default User Role": "Rôle utilisateur par défaut", "Defaults": "", "Delete": "Supprimer", + "Delete {{name}}": "", "Delete a model": "Supprimer un modèle", "Delete All": "Tout supprimer", "Delete All Chats": "Supprimer toutes les conversations", @@ -578,6 +580,7 @@ "Downloading stats...": "Téléchargement des statistiques...", "Draw": "Match nul", "Drop any files here to upload": "Déposez des fichiers ici pour les téléverser", + "Drop files here": "", "Drop files here to upload": "Déposez des fichiers ici pour les téléverser", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "par ex. '30s', '10 min'. Les unités de temps valides sont 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "Activer la zone de saisie", "Folder": "Dossier", "Folder Background Image": "Image d'arrière-plan du dossier", + "Folder created successfully": "", "Folder deleted successfully": "Dossier supprimé avec succès", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Aucun fichier sélectionné", "No files found": "", "No files in this knowledge base.": "Aucun fichier dans cette base de connaissances.", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "Aucun historique disponible", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Récupérer « {{searchValue}} » depuis Ollama.com", "Pull a model from Ollama.com": "Télécharger un modèle depuis Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Prompt de génération de requête", "Querying": "Requête en cours", "Quick Actions": "Actions rapide", diff --git a/src/lib/i18n/locales/gl-ES/translation.json b/src/lib/i18n/locales/gl-ES/translation.json index 27c9b3d58b..63b37f9391 100644 --- a/src/lib/i18n/locales/gl-ES/translation.json +++ b/src/lib/i18n/locales/gl-ES/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "¿Seguro que queres eliminar este canal?", "Are you sure you want to delete this message?": "¿Seguro que queres eliminar este mensaxe? ", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "¿Estás seguro de que quieres desArquivar todos os chats arquivados?", "Arena Models": "Area de Modelos", "Artifacts": "Artefactos", @@ -486,6 +487,7 @@ "Default User Role": "Rol por defecto para os usuarios", "Defaults": "", "Delete": "Borrar", + "Delete {{name}}": "", "Delete a model": "Borra un modelo", "Delete All": "", "Delete All Chats": "Eliminar todos os chats", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Dibujar", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "p.ej. '30s','10m'. Unidades válidas detempo son 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Carpeta eliminada correctamente", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Ningún arquivo fué seleccionado", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Extraer \"{{searchValue}}\" de Ollama.com", "Pull a model from Ollama.com": "Obter un modelo de Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Prompt de xeneración de consulta", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/he-IL/translation.json b/src/lib/i18n/locales/he-IL/translation.json index a6b061d054..ab44c359e8 100644 --- a/src/lib/i18n/locales/he-IL/translation.json +++ b/src/lib/i18n/locales/he-IL/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "תפקיד משתמש ברירת מחדל", "Defaults": "", "Delete": "מחק", + "Delete {{name}}": "", "Delete a model": "מחק מודל", "Delete All": "", "Delete All Chats": "מחק את כל הצ'אטים", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "למשל '30s', '10m'. יחידות זמן חוקיות הן 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "משוך \"{{searchValue}}\" מ-Ollama.com", "Pull a model from Ollama.com": "משוך מודל מ-Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/hi-IN/translation.json b/src/lib/i18n/locales/hi-IN/translation.json index d1576fca2d..54938dabca 100644 --- a/src/lib/i18n/locales/hi-IN/translation.json +++ b/src/lib/i18n/locales/hi-IN/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "डिफ़ॉल्ट उपयोगकर्ता भूमिका", "Defaults": "", "Delete": "डिलीट", + "Delete {{name}}": "", "Delete a model": "एक मॉडल हटाएँ", "Delete All": "", "Delete All Chats": "सभी चैट हटाएं", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "जैसे '30s', '10m', मान्य समय इकाइयाँ 's', 'm', 'h' हैं।", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "\"{{searchValue}}\" को Ollama.com से खींचें", "Pull a model from Ollama.com": "Ollama.com से एक मॉडल खींचें", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/hr-HR/translation.json b/src/lib/i18n/locales/hr-HR/translation.json index e6dadaba52..5bacffb41f 100644 --- a/src/lib/i18n/locales/hr-HR/translation.json +++ b/src/lib/i18n/locales/hr-HR/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "Zadana korisnička uloga", "Defaults": "", "Delete": "Izbriši", + "Delete {{name}}": "", "Delete a model": "Izbriši model", "Delete All": "", "Delete All Chats": "Izbriši sve razgovore", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "npr. '30s','10m'. Važeće vremenske jedinice su 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Povucite \"{{searchValue}}\" s Ollama.com", "Pull a model from Ollama.com": "Povucite model s Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/hu-HU/translation.json b/src/lib/i18n/locales/hu-HU/translation.json index 0a210ed323..da7cdd4481 100644 --- a/src/lib/i18n/locales/hu-HU/translation.json +++ b/src/lib/i18n/locales/hu-HU/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Biztosan törölni szeretnéd ezt a csatornát?", "Are you sure you want to delete this message?": "Biztosan törölni szeretnéd ezt az üzenetet?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Biztosan vissza szeretnéd állítani az összes archivált csevegést?", "Arena Models": "Arena modellek", "Artifacts": "Műtermékek", @@ -486,6 +487,7 @@ "Default User Role": "Alapértelmezett felhasználói szerep", "Defaults": "", "Delete": "Törlés", + "Delete {{name}}": "", "Delete a model": "Modell törlése", "Delete All": "", "Delete All Chats": "Minden beszélgetés törlése", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Rajzolás", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "pl. '30s','10m'. Érvényes időegységek: 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Mappa sikeresen törölve", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Nincs kiválasztva fájl", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "\"{{searchValue}}\" letöltése az Ollama.com-ról", "Pull a model from Ollama.com": "Modell letöltése az Ollama.com-ról", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Lekérdezés generálási prompt", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/id-ID/translation.json b/src/lib/i18n/locales/id-ID/translation.json index 6e78717c3f..2ce4e232bb 100644 --- a/src/lib/i18n/locales/id-ID/translation.json +++ b/src/lib/i18n/locales/id-ID/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "Peran Pengguna Default", "Defaults": "", "Delete": "Menghapus", + "Delete {{name}}": "", "Delete a model": "Menghapus model", "Delete All": "", "Delete All Chats": "Menghapus Semua Obrolan", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "misalnya '30-an', '10m'. Satuan waktu yang valid adalah 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Tidak ada file yang dipilih", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Tarik \"{{searchValue}}\" dari Ollama.com", "Pull a model from Ollama.com": "Tarik model dari Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/ie-GA/translation.json b/src/lib/i18n/locales/ie-GA/translation.json index d711c5fbe1..e12c645495 100644 --- a/src/lib/i18n/locales/ie-GA/translation.json +++ b/src/lib/i18n/locales/ie-GA/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "An bhfuil tú cinnte gur mhaith leat an cainéal seo a scriosadh?", "Are you sure you want to delete this message?": "An bhfuil tú cinnte gur mhaith leat an teachtaireacht seo a scriosadh?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "An bhfuil tú cinnte gur mian leat an leagan seo a scriosadh? Déanfar leaganacha linbh a athnascadh le tuismitheoir an leagain seo.", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "An bhfuil tú cinnte gur mhaith leat gach comhrá cartlainne a dhíchartlannú?", "Arena Models": "Samhlacha Réimse", "Artifacts": "Déantáin", @@ -486,6 +487,7 @@ "Default User Role": "Ról Úsáideora Réamhshocraithe", "Defaults": "Réamhshocruithe", "Delete": "Scrios", + "Delete {{name}}": "", "Delete a model": "Scrios samhail", "Delete All": "Scrios Gach Rud", "Delete All Chats": "Scrios Gach Comhrá", @@ -578,6 +580,7 @@ "Downloading stats...": "Ag íoslódáil staitisticí...", "Draw": "Tarraing", "Drop any files here to upload": "Scaoil aon chomhaid anseo le huaslódáil", + "Drop files here": "", "Drop files here to upload": "Scaoil comhaid anseo le huaslódáil", "DuckDuckGo": "DuckDuckGo", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "m.sh. '30s', '10m'. Is iad aonaid ama bailí ná 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "Dírigh ar Ionchur Comhrá", "Folder": "Fillteán", "Folder Background Image": "Íomhá Chúlra Fillteáin", + "Folder created successfully": "", "Folder deleted successfully": "Scriosadh an fillteán go rathúil", "Folder Max File Count": "Uasmhéid Líon Comhad Fillteán", "Folder name": "Ainm fillteáin", @@ -1304,6 +1308,7 @@ "No file selected": "Níl aon chomhad roghnaithe", "No files found": "Níor aimsíodh aon chomhaid", "No files in this knowledge base.": "Níl aon chomhaid sa bhunachar eolais seo.", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "Níor aimsíodh aon fheidhmeanna", "No groups found": "Níor aimsíodh aon ghrúpaí", "No history available": "Níl aon stair ar fáil", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Tarraing \"{{searchValue}}\" ó Ollama.com", "Pull a model from Ollama.com": "Tarraing samhail ó Ollama.com", "Pull Model": "Samhail Tarraingthe", + "Pyodide file browser": "", "Query Generation Prompt": "Cuirí Ginearáil Ceisteanna", "Querying": "Ag fiosrú", "Quick Actions": "Gníomhartha Tapa", diff --git a/src/lib/i18n/locales/it-IT/translation.json b/src/lib/i18n/locales/it-IT/translation.json index 56cd7836b3..135cca43b6 100644 --- a/src/lib/i18n/locales/it-IT/translation.json +++ b/src/lib/i18n/locales/it-IT/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Sei sicuro di voler eliminare questo canale?", "Are you sure you want to delete this message?": "Sei sicuro di voler eliminare questo messaggio?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Sei sicuro di voler disarchiviare tutte le chat archiviate?", "Arena Models": "Modelli Arena", "Artifacts": "Artefatti", @@ -486,6 +487,7 @@ "Default User Role": "Ruolo utente predefinito", "Defaults": "", "Delete": "Elimina", + "Delete {{name}}": "", "Delete a model": "Elimina un modello", "Delete All": "", "Delete All Chats": "Elimina tutte le chat", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Disegna", "Drop any files here to upload": "Rilascia qui i file per caricarli", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "ad esempio '30s','10m'. Le unità di tempo valide sono 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Cartella rimossa con successo", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Nessun file selezionato", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Estrai \"{{searchValue}}\" da Ollama.com", "Pull a model from Ollama.com": "Estrai un modello da Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Prompt di Generazione Query", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/ja-JP/translation.json b/src/lib/i18n/locales/ja-JP/translation.json index 0532d958b8..71a84cbf04 100644 --- a/src/lib/i18n/locales/ja-JP/translation.json +++ b/src/lib/i18n/locales/ja-JP/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "このチャンネルを削除しますか?", "Are you sure you want to delete this message?": "このメッセージを削除しますか?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "すべてのアーカイブされたチャットをアンアーカイブしますか?", "Arena Models": "Arenaモデル", "Artifacts": "アーティファクト", @@ -486,6 +487,7 @@ "Default User Role": "デフォルトのユーザー役割", "Defaults": "", "Delete": "削除", + "Delete {{name}}": "", "Delete a model": "モデルを削除", "Delete All": "", "Delete All Chats": "すべてのチャットを削除", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "引き分け", "Drop any files here to upload": "ここにファイルをドロップしてアップロード", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "例: '30s'、'10m'。有効な時間単位は 's'、'm'、'h' です。", @@ -897,6 +900,7 @@ "Focus Chat Input": "チャット入力欄にフォーカス", "Folder": "フォルダー", "Folder Background Image": "フォルダーの背景画像", + "Folder created successfully": "", "Folder deleted successfully": "フォルダー削除が成功しました。", "Folder Max File Count": "フォルダー内の最大ファイル数", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "ファイルが選択されていません", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "functionsが見つかりません", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com から \"{{searchValue}}\" をプル", "Pull a model from Ollama.com": "Ollama.com からモデルをプル", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "クエリ生成プロンプト", "Querying": "照会中", "Quick Actions": "クイックアクション", diff --git a/src/lib/i18n/locales/ka-GE/translation.json b/src/lib/i18n/locales/ka-GE/translation.json index 78cf199339..5775c767e4 100644 --- a/src/lib/i18n/locales/ka-GE/translation.json +++ b/src/lib/i18n/locales/ka-GE/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "მართლა გნებავთ ამ არხის წაშლა?", "Are you sure you want to delete this message?": "მართლა გნებავთ ამ შეტყობინების წასლა?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "არენის მოდელები", "Artifacts": "არტეფაქტები", @@ -486,6 +487,7 @@ "Default User Role": "მომხმარებლის ნაგულისხმევი როლი", "Defaults": "", "Delete": "წაშლა", + "Delete {{name}}": "", "Delete a model": "მოდელის წაშლა", "Delete All": "", "Delete All Chats": "ყველა ჩატის წაშლა", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "ხატვა", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "მაგ: '30წ', '10მ'. მოქმედი დროის ერთეულები: 'წ', 'წთ', 'სთ'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "საქაღალდე", "Folder Background Image": "საქაღალდის ფონის სურათი", + "Folder created successfully": "", "Folder deleted successfully": "საქაღალდე წარმატებით წაიშალა", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "ფაილი არჩეული არაა", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "ფუნქციები აღმოჩენილი არაა", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "\"{{searchValue}}\"-ის გადმოწერა Ollama.com-იდან", "Pull a model from Ollama.com": "მოდელის გადმოწერა Ollama.com-დან", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "მოთხოვნა", "Quick Actions": "სწრაფი მოქმედებები", diff --git a/src/lib/i18n/locales/kab-DZ/translation.json b/src/lib/i18n/locales/kab-DZ/translation.json index ee36320599..7132052c02 100644 --- a/src/lib/i18n/locales/kab-DZ/translation.json +++ b/src/lib/i18n/locales/kab-DZ/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Tetḥeqqeḍ tebɣiḍ ad tekkseḍ targa-a?", "Are you sure you want to delete this message?": "Tetḥeqqeḍ tebɣiḍ ad tekkseḍ izen-a?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Tetḥeqqemt tebɣamt ad d-tekksemt akk iqecwalen iarkasen?", "Arena Models": "Timudmiwin n Arena", "Artifacts": "Tarkisant", @@ -486,6 +487,7 @@ "Default User Role": "Tamlilt n useqdac amezwar", "Defaults": "", "Delete": "Kkes", + "Delete {{name}}": "", "Delete a model": "Kkes tamudemt", "Delete All": "", "Delete All Chats": "Kkes akk idiwenniyen", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Suneɣ", "Drop any files here to upload": "Ssers-d ifuyla da akken ad ten-tessaliḍ", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "e.g. '30s','10m'. Tiyunin n wakud ameɣtu d 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "Akaram", "Folder Background Image": "Tugna n ugilal n ukaram", + "Folder created successfully": "", "Folder deleted successfully": "Akaram-nni yettwakkes akken iwata", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Ulac afaylu i yettwafernen", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Awway n \"{{searchValue}}\" seg Ollama.com", "Pull a model from Ollama.com": "Zdem-d tamudemt seg Ollama.com", "Pull Model": "Zdem-d tamudemt", + "Pyodide file browser": "", "Query Generation Prompt": "Aneftaɣ n usirew n tuttra", "Querying": "", "Quick Actions": "Tigawin tiruradin", diff --git a/src/lib/i18n/locales/ko-KR/translation.json b/src/lib/i18n/locales/ko-KR/translation.json index 234638867c..cd847b89ce 100644 --- a/src/lib/i18n/locales/ko-KR/translation.json +++ b/src/lib/i18n/locales/ko-KR/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "정말 이 채널을 삭제하시겠습니까?", "Are you sure you want to delete this message?": "정말 이 메시지를 삭제하시겠습니까?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "정말 보관된 모든 채팅을 보관 해제하시겠습니까?", "Arena Models": "Arena 모델", "Artifacts": "아티팩트", @@ -486,6 +487,7 @@ "Default User Role": "기본 사용자 역할", "Defaults": "", "Delete": "삭제", + "Delete {{name}}": "", "Delete a model": "모델 삭제", "Delete All": "", "Delete All Chats": "모든 채팅 삭제", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "그리기", "Drop any files here to upload": "여기에 파일을 끌어다 놓아 업로드하세요", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "예: '30초','10분'. 올바른 시간 단위는 '초', '분', '시'입니다.", @@ -897,6 +900,7 @@ "Focus Chat Input": "채팅 입력창에 포커스", "Folder": "폴더", "Folder Background Image": "폴더 배경 이미지", + "Folder created successfully": "", "Folder deleted successfully": "성공적으로 폴더가 삭제되었습니다", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "파일이 선택되지 않았습니다", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "함수를 찾을 수 없습니다", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com에서 \"{{searchValue}}\" 가져오기", "Pull a model from Ollama.com": "Ollama.com에서 모델 가져오기(pull)", "Pull Model": "모델 pull", + "Pyodide file browser": "", "Query Generation Prompt": "쿼리 생성 프롬프트", "Querying": "쿼리 진행중", "Quick Actions": "빠른 작업", diff --git a/src/lib/i18n/locales/lt-LT/translation.json b/src/lib/i18n/locales/lt-LT/translation.json index b6195ff803..8479aa0f6d 100644 --- a/src/lib/i18n/locales/lt-LT/translation.json +++ b/src/lib/i18n/locales/lt-LT/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "Numatytoji naudotojo rolė", "Defaults": "", "Delete": "ištrinti", + "Delete {{name}}": "", "Delete a model": "Ištrinti modėlį", "Delete All": "", "Delete All Chats": "Ištrinti visus pokalbius", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "pvz. '30s', '10m'. Laiko vienetai yra 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Nėra pasirinktų dokumentų", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Rasti \"{{searchValue}}\" iš Ollama.com", "Pull a model from Ollama.com": "Gauti modelį iš Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/lv-LV/translation.json b/src/lib/i18n/locales/lv-LV/translation.json index 1d1f4724ae..07202c58a6 100644 --- a/src/lib/i18n/locales/lv-LV/translation.json +++ b/src/lib/i18n/locales/lv-LV/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Vai tiešām vēlaties dzēst šo kanālu?", "Are you sure you want to delete this message?": "Vai tiešām vēlaties dzēst šo ziņojumu?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Vai tiešām vēlaties atarhivēt visas arhivētās tērzēšanas?", "Arena Models": "Arēnas modeļi", "Artifacts": "Artefakti", @@ -486,6 +487,7 @@ "Default User Role": "Noklusējuma lietotāja loma", "Defaults": "", "Delete": "Dzēst", + "Delete {{name}}": "", "Delete a model": "Dzēst modeli", "Delete All": "", "Delete All Chats": "Dzēst visas tērzēšanas", @@ -578,6 +580,7 @@ "Downloading stats...": "Lejupielādē statistiku...", "Draw": "Zīmēt", "Drop any files here to upload": "Nometiet jebkurus failus šeit, lai augšupielādētu", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "DuckDuckGo", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "piem., '30s','10m'. Derīgas laika vienības ir 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "Fokusēt tērzēšanas ievadi", "Folder": "Mape", "Folder Background Image": "Mapes fona attēls", + "Folder created successfully": "", "Folder deleted successfully": "Mape veiksmīgi dzēsta", "Folder Max File Count": "Mapes maksimālais failu skaits", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Fails nav izvēlēts", "No files found": "", "No files in this knowledge base.": "Šajā zināšanu bāzē nav failu.", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "Funkcijas nav atrastas", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Lejupielādēt \"{{searchValue}}\" no Ollama.com", "Pull a model from Ollama.com": "Lejupielādēt modeli no Ollama.com", "Pull Model": "Lejupielādēt modeli", + "Pyodide file browser": "", "Query Generation Prompt": "Vaicājuma ģenerēšanas uzvedne", "Querying": "Vaicā", "Quick Actions": "Ātrās darbības", diff --git a/src/lib/i18n/locales/ms-MY/translation.json b/src/lib/i18n/locales/ms-MY/translation.json index b6459c4817..4f05a58d67 100644 --- a/src/lib/i18n/locales/ms-MY/translation.json +++ b/src/lib/i18n/locales/ms-MY/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "Peranan Pengguna Lalai", "Defaults": "", "Delete": "Padam", + "Delete {{name}}": "", "Delete a model": "Padam Model", "Delete All": "", "Delete All Chats": "Padam Semua Perbualan", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "cth '30s','10m'. Unit masa yang sah ialah 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Tiada fail dipilih", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Tarik \"{{ searchValue }}\" daripada Ollama.com", "Pull a model from Ollama.com": "Tarik model dari Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/nb-NO/translation.json b/src/lib/i18n/locales/nb-NO/translation.json index d4ced2a235..b7e521cd93 100644 --- a/src/lib/i18n/locales/nb-NO/translation.json +++ b/src/lib/i18n/locales/nb-NO/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Er du sikker på at du vil slette denne kanalen?", "Are you sure you want to delete this message?": "Er du sikker på at du vil slette denne meldingen?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Er du sikker på at du vil oppheve arkiveringen av alle arkiverte chatter?", "Arena Models": "Arena-modeller", "Artifacts": "Artifakter", @@ -486,6 +487,7 @@ "Default User Role": "Standard brukerrolle", "Defaults": "", "Delete": "Slett", + "Delete {{name}}": "", "Delete a model": "Slett en modell", "Delete All": "", "Delete All Chats": "Slett alle chatter", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Tegne", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "f.eks. '30s','10m'. Gyldige tidsenheter er 's', 'm', 't'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Mappe slettet", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Ingen fil valgt", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Hent {{searchValue}} fra Ollama.com", "Pull a model from Ollama.com": "Hent en modell fra Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Ledetekst for genering av spørringer", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/nl-NL/translation.json b/src/lib/i18n/locales/nl-NL/translation.json index 886395fea4..7013db4a44 100644 --- a/src/lib/i18n/locales/nl-NL/translation.json +++ b/src/lib/i18n/locales/nl-NL/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Weet je zeker dat je dit kanaal wil verwijderen?", "Are you sure you want to delete this message?": "Weet je zeker dat je dit bericht wil verwijderen?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Weet je zeker dat je alle gearchiveerde chats wil onarchiveren?", "Arena Models": "Arenamodellen", "Artifacts": "Artefacten", @@ -486,6 +487,7 @@ "Default User Role": "Standaard gebruikersrol", "Defaults": "", "Delete": "Verwijderen", + "Delete {{name}}": "", "Delete a model": "Verwijder een model", "Delete All": "", "Delete All Chats": "Verwijder alle chats", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Teken", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "bijv. '30s', '10m'. Geldige tijdseenheden zijn 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Map succesvol verwijderd", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Geen bestand geselecteerd", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Haal \"{{searchValue}}\" uit Ollama.com", "Pull a model from Ollama.com": "Haal een model van Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Vraaggeneratieprompt", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/pa-IN/translation.json b/src/lib/i18n/locales/pa-IN/translation.json index 3edbf74bd8..b824faf43d 100644 --- a/src/lib/i18n/locales/pa-IN/translation.json +++ b/src/lib/i18n/locales/pa-IN/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "ਮੂਲ ਉਪਭੋਗਤਾ ਭੂਮਿਕਾ", "Defaults": "", "Delete": "ਮਿਟਾਓ", + "Delete {{name}}": "", "Delete a model": "ਇੱਕ ਮਾਡਲ ਮਿਟਾਓ", "Delete All": "", "Delete All Chats": "ਸਾਰੀਆਂ ਚੈਟਾਂ ਨੂੰ ਮਿਟਾਓ", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "ਉਦਾਹਰਣ ਲਈ '30ਸ','10ਮਿ'. ਸਹੀ ਸਮਾਂ ਇਕਾਈਆਂ ਹਨ 'ਸ', 'ਮ', 'ਘੰ'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "ਓਲਾਮਾ.ਕਾਮ ਤੋਂ \"{{searchValue}}\" ਖਿੱਚੋ", "Pull a model from Ollama.com": "ਓਲਾਮਾ.ਕਾਮ ਤੋਂ ਇੱਕ ਮਾਡਲ ਖਿੱਚੋ", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/pl-PL/translation.json b/src/lib/i18n/locales/pl-PL/translation.json index da19789867..d2420efd8c 100644 --- a/src/lib/i18n/locales/pl-PL/translation.json +++ b/src/lib/i18n/locales/pl-PL/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Czy na pewno chcesz usunąć ten kanał?", "Are you sure you want to delete this message?": "Czy na pewno chcesz usunąć tę wiadomość?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Czy na pewno chcesz przywrócić wszystkie czaty?", "Arena Models": "Modele Arena", "Artifacts": "Artefakty", @@ -486,6 +487,7 @@ "Default User Role": "Domyślna rola użytkownika", "Defaults": "", "Delete": "Usuń", + "Delete {{name}}": "", "Delete a model": "Usuń model", "Delete All": "", "Delete All Chats": "Usuń wszystkie czaty", @@ -578,6 +580,7 @@ "Downloading stats...": "Pobieranie statystyk...", "Draw": "Remis", "Drop any files here to upload": "Upuść pliki tutaj, aby przesłać", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "DuckDuckGo", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "np. '30s','10m'. Jednostki: 's' (sek), 'm' (min), 'h' (godz).", @@ -897,6 +900,7 @@ "Focus Chat Input": "Skupienie na polu czatu", "Folder": "Folder", "Folder Background Image": "Tło folderu", + "Folder created successfully": "", "Folder deleted successfully": "Folder usunięty pomyślnie", "Folder Max File Count": "Maks. liczba plików w folderze", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Nie wybrano pliku", "No files found": "", "No files in this knowledge base.": "Brak plików w tej bazie wiedzy.", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "Nie znaleziono funkcji", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Pobierz \"{{searchValue}}\" z Ollama.com", "Pull a model from Ollama.com": "Pobierz model z Ollama.com", "Pull Model": "Pobierz Model", + "Pyodide file browser": "", "Query Generation Prompt": "Prompt generowania zapytania", "Querying": "Odpytywanie", "Quick Actions": "Szybkie akcje", diff --git a/src/lib/i18n/locales/pt-BR/translation.json b/src/lib/i18n/locales/pt-BR/translation.json index 74d0febaf7..2d69ed5a3a 100644 --- a/src/lib/i18n/locales/pt-BR/translation.json +++ b/src/lib/i18n/locales/pt-BR/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Tem certeza de que deseja excluir este canal?", "Are you sure you want to delete this message?": "Tem certeza de que deseja excluir esta mensagem?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Tem certeza de que deseja excluir esta versão? As versões filhas serão vinculadas novamente à versão pai.", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Você tem certeza que deseja desarquivar todos os chats arquivados?", "Arena Models": "Arena de Modelos", "Artifacts": "Artefatos", @@ -486,6 +487,7 @@ "Default User Role": "Padrão para novos usuários", "Defaults": "Padrões", "Delete": "Excluir", + "Delete {{name}}": "", "Delete a model": "Excluir um modelo", "Delete All": "Excluir tudo", "Delete All Chats": "Excluir Todos os Chats", @@ -578,6 +580,7 @@ "Downloading stats...": "Baixando estatísticas...", "Draw": "Empate", "Drop any files here to upload": "Solte qualquer arquivo aqui para fazer upload", + "Drop files here": "", "Drop files here to upload": "Solte os arquivos aqui para fazer upload", "DuckDuckGo": "DuckDuckGo", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "por exemplo, '30s', '10m'. Unidades de tempo válidas são 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "Foco na janela do Chat", "Folder": "Pasta", "Folder Background Image": "Imagem de fundo da pasta", + "Folder created successfully": "", "Folder deleted successfully": "Pasta excluída com sucesso", "Folder Max File Count": "Contagem máxima de arquivos por pasta", "Folder name": "Nome da pasta", @@ -1304,6 +1308,7 @@ "No file selected": "Nenhum arquivo selecionado", "No files found": "Nenhum arquivo encontrado", "No files in this knowledge base.": "Não existem arquivos nesta base de conhecimento.", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "Nenhuma função encontrada", "No groups found": "Nenhum grupo encontrado", "No history available": "Não há histórico disponível.", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Obter \"{{searchValue}}\" de Ollama.com", "Pull a model from Ollama.com": "Obter um modelo de Ollama.com", "Pull Model": "Obter Modelo", + "Pyodide file browser": "", "Query Generation Prompt": "Prompt de Geração de Consulta", "Querying": "Consultando", "Quick Actions": "Ações rápidas", diff --git a/src/lib/i18n/locales/pt-PT/translation.json b/src/lib/i18n/locales/pt-PT/translation.json index dc7efc5700..b45ec49cc1 100644 --- a/src/lib/i18n/locales/pt-PT/translation.json +++ b/src/lib/i18n/locales/pt-PT/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "Função de Utilizador Padrão", "Defaults": "", "Delete": "Apagar", + "Delete {{name}}": "", "Delete a model": "Apagar um modelo", "Delete All": "", "Delete All Chats": "Apagar todas as conversas", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "por exemplo, '30s', '10m'. Unidades de tempo válidas são 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Puxar \"{{searchValue}}\" do Ollama.com", "Pull a model from Ollama.com": "Puxar um modelo do Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/ro-RO/translation.json b/src/lib/i18n/locales/ro-RO/translation.json index 2b953f16bb..37cc71aa3c 100644 --- a/src/lib/i18n/locales/ro-RO/translation.json +++ b/src/lib/i18n/locales/ro-RO/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Ești sigur că vrei să ștergi acest canal?", "Are you sure you want to delete this message?": "Ești sigur că vrei să ștergi acest mesaj?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Ești sigur că vrei să dezarhivezi toate conversațiile arhivate?", "Arena Models": "Arena Models", "Artifacts": "Artefacte", @@ -486,6 +487,7 @@ "Default User Role": "Rolul Implicit al Utilizatorului", "Defaults": "", "Delete": "Șterge", + "Delete {{name}}": "", "Delete a model": "Șterge un model", "Delete All": "", "Delete All Chats": "Șterge Toate Conversațiile", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Desenează", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "de ex. '30s', '10m'. Unitățile de timp valide sunt 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Folder șters cu succes", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Nu a fost selectat niciun fișier", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Extrage \"{{searchValue}}\" de pe Ollama.com", "Pull a model from Ollama.com": "Extrage un model de pe Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/ru-RU/translation.json b/src/lib/i18n/locales/ru-RU/translation.json index 7e36725824..99a5189ae0 100644 --- a/src/lib/i18n/locales/ru-RU/translation.json +++ b/src/lib/i18n/locales/ru-RU/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Вы уверены, что хотите удалить этот канал?", "Are you sure you want to delete this message?": "Вы уверены, что хотите удалить это сообщение?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Вы уверены, что хотите разархивировать все заархивированные чаты?", "Arena Models": "Арена моделей", "Artifacts": "Артефакты", @@ -486,6 +487,7 @@ "Default User Role": "Роль пользователя по умолчанию", "Defaults": "", "Delete": "Удалить", + "Delete {{name}}": "", "Delete a model": "Удалить модель", "Delete All": "Удалить ВСЕ", "Delete All Chats": "Удалить ВСЕ Чаты", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Рисовать", "Drop any files here to upload": "Переместите сюда любые файлы для загрузки", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "например, '30s','10m'. Допустимые единицы времени: 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "Фоновое изображение папки", + "Folder created successfully": "", "Folder deleted successfully": "Папка успешно удалена", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Файлы не выбраны", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Загрузить \"{{searchValue}}\" с Ollama.com", "Pull a model from Ollama.com": "Загрузить модель с Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Запрос на генерацию промпта", "Querying": "Запрос", "Quick Actions": "Быстрые действия", diff --git a/src/lib/i18n/locales/sk-SK/translation.json b/src/lib/i18n/locales/sk-SK/translation.json index 631818be15..693e6734fb 100644 --- a/src/lib/i18n/locales/sk-SK/translation.json +++ b/src/lib/i18n/locales/sk-SK/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "Arena modely", "Artifacts": "Artefakty", @@ -486,6 +487,7 @@ "Default User Role": "Predvolená rola užívateľa", "Defaults": "", "Delete": "Odstrániť", + "Delete {{name}}": "", "Delete a model": "Odstrániť model.", "Delete All": "", "Delete All Chats": "Odstrániť všetky konverzácie", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Nakresliť", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "napr. '30s','10m'. Platné časové jednotky sú 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "Priečinok", "Folder Background Image": "Obrázok pozadia priečinku", + "Folder created successfully": "", "Folder deleted successfully": "Priečinok bol úspešne vymazaný", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Nebola vybratá žiadna súbor", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Stiahnite \"{{searchValue}}\" z Ollama.com", "Pull a model from Ollama.com": "Stiahnite model z Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/sr-RS/translation.json b/src/lib/i18n/locales/sr-RS/translation.json index 1a0a7bd106..2146eec353 100644 --- a/src/lib/i18n/locales/sr-RS/translation.json +++ b/src/lib/i18n/locales/sr-RS/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Да ли сигурно желите обрисати овај канал?", "Are you sure you want to delete this message?": "Да ли сигурно желите обрисати ову поруку?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Да ли сигурно желите деархивирати све архиве?", "Arena Models": "Модели са Арене", "Artifacts": "Артефакти", @@ -486,6 +487,7 @@ "Default User Role": "Подразумевана улога корисника", "Defaults": "", "Delete": "Обриши", + "Delete {{name}}": "", "Delete a model": "Обриши модел", "Delete All": "", "Delete All Chats": "Обриши сва ћаскања", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Нацртај", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "нпр. '30s', '10m'. Важеће временске јединице су 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Повуците \"{{searchValue}}\" са Ollama.com", "Pull a model from Ollama.com": "Повуците модел са Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/sv-SE/translation.json b/src/lib/i18n/locales/sv-SE/translation.json index 1459d67bf8..2bd95feb58 100644 --- a/src/lib/i18n/locales/sv-SE/translation.json +++ b/src/lib/i18n/locales/sv-SE/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Är du säker på att du vill radera denna kanal?", "Are you sure you want to delete this message?": "Är du säker på att du vill radera detta meddelande?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Är du säker på att du vill avarkivera alla arkiverade chattar?", "Arena Models": "Arenamodeller", "Artifacts": "Artefakter", @@ -486,6 +487,7 @@ "Default User Role": "Standardanvändarroll", "Defaults": "", "Delete": "Radera", + "Delete {{name}}": "", "Delete a model": "Ta bort en modell", "Delete All": "", "Delete All Chats": "Ta bort alla chattar", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Rita", "Drop any files here to upload": "Släpp alla filer här för att ladda upp", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "t.ex. '30s', '10m'. Giltiga tidsenheter är 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "Mapp", "Folder Background Image": "Bakgrundsbild till mappen", + "Folder created successfully": "", "Folder deleted successfully": "Mappen har tagits bort", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Ingen fil vald", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "Inga funktioner hittades", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ladda ner \"{{searchValue}}\" från Ollama.com", "Pull a model from Ollama.com": "Ladda ner en modell från Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Prompt för frågegenerering", "Querying": "Frågar", "Quick Actions": "Snabbåtgärder", diff --git a/src/lib/i18n/locales/th-TH/translation.json b/src/lib/i18n/locales/th-TH/translation.json index 4092f0e7fd..e2b451c7c2 100644 --- a/src/lib/i18n/locales/th-TH/translation.json +++ b/src/lib/i18n/locales/th-TH/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "คุณแน่ใจหรือว่าต้องการลบช่องนี้?", "Are you sure you want to delete this message?": "คุณแน่ใจหรือว่าต้องการลบข้อความนี้?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "คุณแน่ใจหรือว่าต้องการยกเลิกการเก็บถาวรแชททั้งหมด?", "Arena Models": "โมเดลใน Arena", "Artifacts": "Artifacts", @@ -486,6 +487,7 @@ "Default User Role": "บทบาทผู้ใช้เริ่มต้น", "Defaults": "", "Delete": "ลบ", + "Delete {{name}}": "", "Delete a model": "ลบโมเดล", "Delete All": "", "Delete All Chats": "ลบการแชททั้งหมด", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "วาด", "Drop any files here to upload": "วางไฟล์ที่นี่เพื่ออัปโหลด", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "เช่น '30s', '10m' หน่วยเวลาที่ใช้ได้คือ 's', 'm', 'h'", @@ -897,6 +900,7 @@ "Focus Chat Input": "โฟกัสช่องป้อนแชท", "Folder": "โฟลเดอร์", "Folder Background Image": "รูปภาพพื้นหลังโฟลเดอร์", + "Folder created successfully": "", "Folder deleted successfully": "ลบโฟลเดอร์สำเร็จแล้ว", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "ไม่ได้เลือกไฟล์", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "ไม่พบฟังก์ชัน", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "ดึง \"{{searchValue}}\" จาก Ollama.com", "Pull a model from Ollama.com": "ดึงโมเดลจาก Ollama.com", "Pull Model": "ดึงโมเดล", + "Pyodide file browser": "", "Query Generation Prompt": "พรอมต์สร้างคิวรี", "Querying": "กำลังค้นหา", "Quick Actions": "การกระทำด่วน", diff --git a/src/lib/i18n/locales/tk-TM/translation.json b/src/lib/i18n/locales/tk-TM/translation.json index b8d605fa9c..651254fa29 100644 --- a/src/lib/i18n/locales/tk-TM/translation.json +++ b/src/lib/i18n/locales/tk-TM/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "", "Artifacts": "", @@ -486,6 +487,7 @@ "Default User Role": "", "Defaults": "", "Delete": "Öçür", + "Delete {{name}}": "", "Delete a model": "", "Delete All": "", "Delete All Chats": "Ähli Çatlary Öçür", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "", "Pull a model from Ollama.com": "", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/tr-TR/translation.json b/src/lib/i18n/locales/tr-TR/translation.json index 42c2b98fed..9c0d3c9bd6 100644 --- a/src/lib/i18n/locales/tr-TR/translation.json +++ b/src/lib/i18n/locales/tr-TR/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Bu kanalı silmek istediğinizden emin misiniz?", "Are you sure you want to delete this message?": "Bu mesajı silmek istediğinizden emin misiniz?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "Bu sürümü silmek istediğinizden emin misiniz? Alt sürümler bu sürümün üst sürümüne yeniden bağlanacaktır.", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Arşivlenmiş tüm sohbetlerin arşivini kaldırmak istediğinizden emin misiniz?", "Arena Models": "Arena Modelleri", "Artifacts": "Eserler", @@ -486,6 +487,7 @@ "Default User Role": "Varsayılan Kullanıcı Rolü", "Defaults": "Varsayılanlar", "Delete": "Sil", + "Delete {{name}}": "", "Delete a model": "Bir modeli sil", "Delete All": "Tümünü Sil", "Delete All Chats": "Tüm Sohbetleri Sil", @@ -578,6 +580,7 @@ "Downloading stats...": "İstatistikler indiriliyor...", "Draw": "Çiz", "Drop any files here to upload": "Yüklemek için dosyaları buraya bırakın", + "Drop files here": "", "Drop files here to upload": "Yüklemek için dosyaları buraya bırakın", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "örn. '30s', '10m'. Geçerli zaman birimleri 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "Klasör", "Folder Background Image": "Klasör Arka Plan Resmi", + "Folder created successfully": "", "Folder deleted successfully": "Klasör başarıyla silindi", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Hiçbir dosya seçilmedi", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com'dan \"{{searchValue}}\" çekin", "Pull a model from Ollama.com": "Ollama.com'dan bir model çekin", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Sorgu Oluşturma Promptu", "Querying": "", "Quick Actions": "Hızlı Eylemler", diff --git a/src/lib/i18n/locales/ug-CN/translation.json b/src/lib/i18n/locales/ug-CN/translation.json index 56dccac739..3b45c2202c 100644 --- a/src/lib/i18n/locales/ug-CN/translation.json +++ b/src/lib/i18n/locales/ug-CN/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "بۇ قانالنى ئۆچۈرەمسىز؟", "Are you sure you want to delete this message?": "بۇ ئۇچۇرنى ئۆچۈرەمسىز؟", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "بارلىق ئارخىپلانغان سۆھبەتلەرنى قايتا ئەسلىگە كەلتۈرەمسىز؟", "Arena Models": "Arena مودېللىرى", "Artifacts": "ئۇزۇقلار", @@ -486,6 +487,7 @@ "Default User Role": "كۆڭۈلدىكى ئىشلەتكۈچى رولى", "Defaults": "", "Delete": "ئۆچۈرۈش", + "Delete {{name}}": "", "Delete a model": "مودېل ئۆچۈرۈش", "Delete All": "", "Delete All Chats": "بارلىق سۆھبەتلەرنى ئۆچۈرۈش", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "سىزىش", "Drop any files here to upload": "ھەر قانداق ھۆججەتنى بۇ يەرگە قويۇپ يۈكلەڭ", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "مەسىلەن: '30s', '10m'. توغرا ۋاقىت بىرلىكى: 's' (سېكۇنت), 'm' (مىنۇت), 'h' (سائەت).", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "قىسقۇچ مۇۋەپپەقىيەتلىك ئۆچۈرۈلدى", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "ھۆججەت تاللانمىدى", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com دىن \"{{searchValue}}\" نى تارتىش", "Pull a model from Ollama.com": "Ollama.com دىن مودېل تارتىش", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "ئىزدەش سۇئالى تۈرتكەسى", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/uk-UA/translation.json b/src/lib/i18n/locales/uk-UA/translation.json index 4d6f5c2060..6c949f2fee 100644 --- a/src/lib/i18n/locales/uk-UA/translation.json +++ b/src/lib/i18n/locales/uk-UA/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Ви впевнені, що хочете видалити цей канал?", "Are you sure you want to delete this message?": "Ви впевнені, що хочете видалити це повідомлення?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Ви впевнені, що хочете розархівувати усі архівовані чати?", "Arena Models": "Моделі Arena", "Artifacts": "Артефакти", @@ -486,6 +487,7 @@ "Default User Role": "Роль користувача за замовчуванням", "Defaults": "", "Delete": "Видалити", + "Delete {{name}}": "", "Delete a model": "Видалити модель", "Delete All": "", "Delete All Chats": "Видалити усі чати", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Малювати", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "напр., '30s','10m'. Дійсні одиниці часу: 'с', 'хв', 'г'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Папку успішно видалено", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Файл не обрано", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Завантажити \"{{searchValue}}\" з Ollama.com", "Pull a model from Ollama.com": "Завантажити модель з Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Підказка для генерації запиту", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/ur-PK/translation.json b/src/lib/i18n/locales/ur-PK/translation.json index 679bfa601b..b165ac17fe 100644 --- a/src/lib/i18n/locales/ur-PK/translation.json +++ b/src/lib/i18n/locales/ur-PK/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "", "Are you sure you want to delete this message?": "", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "", "Arena Models": "ارینا ماڈلز", "Artifacts": "نوادرات", @@ -486,6 +487,7 @@ "Default User Role": "ڈیفالٹ صارف کا کردار", "Defaults": "", "Delete": "حذف کریں", + "Delete {{name}}": "", "Delete a model": "ایک ماڈل حذف کریں", "Delete All": "", "Delete All Chats": "تمام چیٹس حذف کریں", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "ڈرائنگ کریں", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "مثلاً '30s'، '10m' درست وقت کی اکائیاں ہیں 's'، 'm'، 'h'", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "پوشہ کامیابی سے حذف ہو گیا", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "کوئی فائل منتخب نہیں کی گئی", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com سے \"{{searchValue}}\" کو کھینچیں", "Pull a model from Ollama.com": "Ollama.com سے ماڈل حاصل کریں", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/uz-Cyrl-UZ/translation.json b/src/lib/i18n/locales/uz-Cyrl-UZ/translation.json index f35c516c93..b1168b60df 100644 --- a/src/lib/i18n/locales/uz-Cyrl-UZ/translation.json +++ b/src/lib/i18n/locales/uz-Cyrl-UZ/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Ҳақиқатан ҳам бу канални ўчириб ташламоқчимисиз?", "Are you sure you want to delete this message?": "Ҳақиқатан ҳам бу хабарни ўчириб ташламоқчимисиз?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Ҳақиқатан ҳам барча архивланган чатларни архивдан чиқармоқчимисиз?", "Arena Models": "Арена моделлари", "Artifacts": "Артефактлар", @@ -486,6 +487,7 @@ "Default User Role": "Стандарт фойдаланувчи роли", "Defaults": "", "Delete": "Ўчириш", + "Delete {{name}}": "", "Delete a model": "Моделни ўчириш", "Delete All": "", "Delete All Chats": "Барча суҳбатларни ўчириш", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Чизиш", "Drop any files here to upload": "Юклаш учун исталган файлни шу ерга ташланг", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "масалан. 30s, 10m. Яроқли вақт бирликлари 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Жилд муваффақиятли ўчирилди", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Ҳеч қандай файл танланмаган", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.cом сайтидан “{{сеарчВалуе}}”ни тортинг", "Pull a model from Ollama.com": "Ollama.cом дан моделни тортинг", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Сўровни яратиш таклифи", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/uz-Latn-Uz/translation.json b/src/lib/i18n/locales/uz-Latn-Uz/translation.json index 2af10b56d4..9087fe70e0 100644 --- a/src/lib/i18n/locales/uz-Latn-Uz/translation.json +++ b/src/lib/i18n/locales/uz-Latn-Uz/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Haqiqatan ham bu kanalni oʻchirib tashlamoqchimisiz?", "Are you sure you want to delete this message?": "Haqiqatan ham bu xabarni oʻchirib tashlamoqchimisiz?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Haqiqatan ham barcha arxivlangan chatlarni arxivdan chiqarmoqchimisiz?", "Arena Models": "Arena modellari", "Artifacts": "Artefaktlar", @@ -486,6 +487,7 @@ "Default User Role": "Odatiy foydalanuvchi roli", "Defaults": "", "Delete": "Oʻchirish", + "Delete {{name}}": "", "Delete a model": "Modelni o'chirish", "Delete All": "", "Delete All Chats": "Barcha suhbatlarni o'chirish", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Chizish", "Drop any files here to upload": "Yuklash uchun istalgan faylni shu yerga tashlang", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "masalan. '30s', '10m'. Yaroqli vaqt birliklari 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Jild muvaffaqiyatli oʻchirildi", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Hech qanday fayl tanlanmagan", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Ollama.com saytidan “{{searchValue}}”ni torting", "Pull a model from Ollama.com": "Ollama.com dan modelni torting", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "So'rovni yaratish taklifi", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/vi-VN/translation.json b/src/lib/i18n/locales/vi-VN/translation.json index 637321ef3a..5b190c6b1c 100644 --- a/src/lib/i18n/locales/vi-VN/translation.json +++ b/src/lib/i18n/locales/vi-VN/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "Bạn có chắc chắn muốn xóa kênh này không?", "Are you sure you want to delete this message?": "Bạn có chắc chắn muốn xóa tin nhắn này không?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "Bạn có chắc chắn muốn bỏ lưu trữ tất cả các cuộc trò chuyện đã lưu trữ không?", "Arena Models": "Các Mô hình Arena", "Artifacts": "Kết quả tạo ra", @@ -486,6 +487,7 @@ "Default User Role": "Vai trò mặc định", "Defaults": "", "Delete": "Xóa", + "Delete {{name}}": "", "Delete a model": "Xóa mô hình", "Delete All": "", "Delete All Chats": "Xóa mọi cuộc Chat", @@ -578,6 +580,7 @@ "Downloading stats...": "", "Draw": "Vẽ", "Drop any files here to upload": "", + "Drop files here": "", "Drop files here to upload": "", "DuckDuckGo": "", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "vd: '30s','10m'. Đơn vị thời gian hợp lệ là 's', 'm', 'h'.", @@ -897,6 +900,7 @@ "Focus Chat Input": "", "Folder": "", "Folder Background Image": "", + "Folder created successfully": "", "Folder deleted successfully": "Xóa thư mục thành công", "Folder Max File Count": "", "Folder name": "", @@ -1304,6 +1308,7 @@ "No file selected": "Chưa có tệp nào được chọn", "No files found": "", "No files in this knowledge base.": "", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "", "No groups found": "", "No history available": "", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "Tải \"{{searchValue}}\" từ Ollama.com", "Pull a model from Ollama.com": "Tải mô hình từ Ollama.com", "Pull Model": "", + "Pyodide file browser": "", "Query Generation Prompt": "Prompt Tạo Truy vấn", "Querying": "", "Quick Actions": "", diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json index 744785c78a..6ca92acdc0 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "您确认要删除此频道吗?", "Are you sure you want to delete this message?": "您确认要删除此消息吗?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "您确认要删除此版本吗?其子版本将重新链接到该版本的上一级。", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "您确认要取消所有已归档的对话吗?", "Arena Models": "启用竞技场匿名评价模型", "Artifacts": "产物", @@ -486,6 +487,7 @@ "Default User Role": "默认用户角色", "Defaults": "默认值", "Delete": "删除", + "Delete {{name}}": "", "Delete a model": "删除模型", "Delete All": "全部删除", "Delete All Chats": "删除所有对话记录", @@ -578,6 +580,7 @@ "Downloading stats...": "正在下载统计数据...", "Draw": "平局", "Drop any files here to upload": "拖拽文件至此上传", + "Drop files here": "", "Drop files here to upload": "将文件拖到此处即可上传", "DuckDuckGo": "DuckDuckGo", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "例如:“30s”,“10m”。有效的时间单位包括:“s”(秒), “m”(分), “h”(时)", @@ -897,6 +900,7 @@ "Focus Chat Input": "聚焦对话框", "Folder": "分组", "Folder Background Image": "分组背景图", + "Folder created successfully": "", "Folder deleted successfully": "分组删除成功", "Folder Max File Count": "分组最大文件数量", "Folder name": "文件夹名称", @@ -1304,6 +1308,7 @@ "No file selected": "未选中文件", "No files found": "未找到文件", "No files in this knowledge base.": "此知识库中没有文件。", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "未找到函数", "No groups found": "暂无权限组", "No history available": "暂无历史记录", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "从 Ollama.com 下载 “{{searchValue}}”", "Pull a model from Ollama.com": "从 Ollama.com 下载模型", "Pull Model": "下载模型", + "Pyodide file browser": "", "Query Generation Prompt": "查询生成提示词", "Querying": "查询中", "Quick Actions": "快捷操作", diff --git a/src/lib/i18n/locales/zh-TW/translation.json b/src/lib/i18n/locales/zh-TW/translation.json index eba4340e1b..dcff1e5746 100644 --- a/src/lib/i18n/locales/zh-TW/translation.json +++ b/src/lib/i18n/locales/zh-TW/translation.json @@ -183,6 +183,7 @@ "Are you sure you want to delete this channel?": "您確定要刪除此頻道嗎?", "Are you sure you want to delete this message?": "您確定要刪除此訊息嗎?", "Are you sure you want to delete this version? Child versions will be relinked to this version's parent.": "您確定要刪除此版本嗎?子版本將重新連結至上一層版本。", + "Are you sure you want to delete this?": "", "Are you sure you want to unarchive all archived chats?": "您確定要解除封存所有封存的對話記錄嗎?", "Arena Models": "競技場模型", "Artifacts": "產物", @@ -486,6 +487,7 @@ "Default User Role": "預設使用者角色", "Defaults": "預設值", "Delete": "刪除", + "Delete {{name}}": "", "Delete a model": "刪除模型", "Delete All": "全部刪除", "Delete All Chats": "刪除所有對話紀錄", @@ -578,6 +580,7 @@ "Downloading stats...": "正在下載統計資料...", "Draw": "平手", "Drop any files here to upload": "拖曳檔案至此處進行上傳", + "Drop files here": "", "Drop files here to upload": "將檔案拖曳至此即可上傳", "DuckDuckGo": "DuckDuckGo", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "例如:'30s'、'10m'。有效的時間單位為 's'、'm'、'h'。", @@ -897,6 +900,7 @@ "Focus Chat Input": "聚焦對話輸入框", "Folder": "分組", "Folder Background Image": "分組背景圖", + "Folder created successfully": "", "Folder deleted successfully": "成功刪除分組", "Folder Max File Count": "分組最大檔案數量", "Folder name": "資料夾名稱", @@ -1304,6 +1308,7 @@ "No file selected": "未選取檔案", "No files found": "找不到檔案", "No files in this knowledge base.": "此知識庫中沒有檔案。", + "No files yet. Upload files or run Python code to create them.": "", "No functions found": "未找到函式", "No groups found": "暫無權限群組", "No history available": "暫無歷史紀錄", @@ -1511,6 +1516,7 @@ "Pull \"{{searchValue}}\" from Ollama.com": "從 Ollama.com 下載「{{searchValue}}」", "Pull a model from Ollama.com": "從 Ollama.com 下載模型", "Pull Model": "下載模型", + "Pyodide file browser": "", "Query Generation Prompt": "查詢生成提示詞", "Querying": "查詢中", "Quick Actions": "快速操作", diff --git a/src/lib/workers/pyodide.worker.ts b/src/lib/workers/pyodide.worker.ts index a9334b4faf..7ef3916731 100644 --- a/src/lib/workers/pyodide.worker.ts +++ b/src/lib/workers/pyodide.worker.ts @@ -123,9 +123,7 @@ function fsUploadFiles(files: { name: string; data: ArrayBuffer }[], dir = '/mnt function fsList(path: string) { const entries: { name: string; type: 'file' | 'directory'; size: number }[] = []; try { - const items = self.pyodide.FS.readdir(path).filter( - (n: string) => n !== '.' && n !== '..' - ); + const items = self.pyodide.FS.readdir(path).filter((n: string) => n !== '.' && n !== '..'); for (const name of items) { try { const stat = self.pyodide.FS.stat(`${path}/${name}`); @@ -155,9 +153,7 @@ function fsDelete(path: string) { const stat = self.pyodide.FS.stat(path); if (self.pyodide.FS.isDir(stat.mode)) { // Recursively delete directory contents - const items = self.pyodide.FS.readdir(path).filter( - (n: string) => n !== '.' && n !== '..' - ); + const items = self.pyodide.FS.readdir(path).filter((n: string) => n !== '.' && n !== '..'); for (const item of items) { fsDelete(`${path}/${item}`); } @@ -178,7 +174,11 @@ function fsMkdir(path: string) { // Code execution // --------------------------------------------------------------------------- -async function executeCode(id: string, code: string, files?: { name: string; data: ArrayBuffer }[]) { +async function executeCode( + id: string, + code: string, + files?: { name: string; data: ArrayBuffer }[] +) { self.stdout = null; self.stderr = null; self.result = null; @@ -282,7 +282,11 @@ self.onmessage = async (event) => { const buffer = fsRead(data.path); self.postMessage({ id, type: 'fs:read', data: buffer }, { transfer: [buffer] }); } catch (err: unknown) { - self.postMessage({ id, type: 'fs:read', error: err instanceof Error ? err.message : String(err) }); + self.postMessage({ + id, + type: 'fs:read', + error: err instanceof Error ? err.message : String(err) + }); } break; } From d0c318037646e8b19cad6b7aa5c13c13d150e218 Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sun, 8 Mar 2026 03:15:00 +0100 Subject: [PATCH 102/114] changelog: 0.8.9 (#22186) * changelog: terminal keepalive fix * changelog: add chat archive handler fix * changelog: terminal keepalive, chat archive handler, BeautifulSoup4 dependency * changelog: button spinner, terminal keepalive, chat archive, beautifulsoup4 * changelog: group users sort, button spinner, terminal keepalive, chat archive, beautifulsoup4 * changelog: add event call timeout configuration * changelog: add general improvements and French translations * changelog: file refresh button, group sort, event timeout, translations * changelog: add office file previews support * changelog: add Open Terminal port viewing feature * changelog: add Open Terminal video previews entry * changelog: Open Terminal syntax highlighting and XLSX improvements * changelog: add JSON tree view and SVG rendering entry * changelog: add Open Terminal Jupyter Notebook previews entry * changelog: update chat performance entry to reflect broader markdown rendering improvements * changelog: add SQLite browser feature to Open Terminal * changelog: add Open Terminal file copy button entry * changelog: add Open Terminal auto-refresh entry * changelog: open terminal, mermaid, diagrams * changelog: add Open Terminal notebook cell execution entry * changelog: reorder Open Terminal entries by impact * changelog: add initial page load speed entry * changelog: opentelemetry, metrics, telemetry * changelog: fix artifacts memory leak (PR #22303) * changelog: message list performance, array operations optimization * changelog: streaming markdown performance fix * changelog: sqlcipher, stability, memory leak * changelog: chat streaming performance * changelog: fix Floating Quick Actions for unavailable models * changelog: follow-up suggestions, prompt template, JSON format * changelog: banner, navigation, homepage * changelog: api middleware, streaming performance * changelog: tts, thinking content, playback * changelog: add system metrics via OpenTelemetry * changelog: tool access permissions fix * changelog: source list performance fix * changelog: source list performance optimization * changelog: chat message tree performance, #22194 * changelog: add Finnish translations, update version date * changelog: fix parameterless tool calls during streaming * changelog: add stale pinned models cleanup fix * changelog: move performance entries from Fixed to Added section * changelog: android, photo capture, canvas * changelog: action priority query optimization (PR #22301) * changelog: move action priority query to Added section * changelog: group Open Terminal entries together * changelog: group Open Terminal entries together * changelog: move API key middleware entry to Added section * changelog: open-terminal, html-editing * changelog: web search tool guidance update * changelog: add Turkish translations to v0.8.9 * changelog: add German translations * changelog: fix stop sequence error handling * changelog: Open Terminal permission fix for issue #22374 * changelog: add Windows path fix for Open Terminal * changelog: add Simplified Chinese and Traditional Chinese to translations * changelog: fix profile image sizing in chat overview * changelog: queued messages display fix (#22176) * changelog: model list loading performance optimization * changelog: model list performance optimization update * changelog: artifacts reactive loop fix * changelog: artifact navigation fix * changelog: fix image generation in temporary chats * changelog: non-streaming token tracking, admin analytics * changelog: add citation parser error handling fix * changelog: tool server URL trailing slash fix * changelog: inline code typing fix (#20417) * changelog: variable input newlines fix * changelog: add migration memory usage fix for large deployments * changelog: Microsoft OAuth refresh token fix * changelog: add issue link to variable input newlines entry * changelog: tool files access, artifact thinking block fix * changelog: ollama, model unload, proxy fix * changelog: fix banner type dropdown requiring two clicks * changelog: move migration memory fix to top of Fixed section * changelog: fix analytics URL encoding for models with slashes * changelog: fix tool call streaming for GPT-5 models * changelog: fix analytics chat list duplicate error * changelog: pyodide file system support for code interpreter * changelog: fix folder knowledge base native tool call duplicate query * changelog: folder knowledge base native tool call fix with follow-up commit * changelog: nested folders support * changelog: update Pyodide file system entry with pip guidance --- CHANGELOG.md | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92a9dee71c..8e945a6769 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,86 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.8.9] - 2026-03-09 + +### Added + +- 📁 **Pyodide file system support.** Users can now upload files for Python code execution in the code interpreter. Uploaded files are available in the `/mnt/uploads/` directory, and code can write output files there for download. The file system persists across code executions within the same session. The code interpreter now also informs models that pip install is not available in the Pyodide environment, guiding them to use alternative approaches with available modules. [#3583](https://github.com/open-webui/open-webui/issues/3583), [Commit](https://github.com/open-webui/open-webui/commit/ce0ca894fea8a2904bc6f832ff186d5fe53dd0b9), [Commit](https://github.com/open-webui/open-webui/commit/989938856fdb4b4afa584ae2d18c88d5be614ae2) +- ▶️ **Open Terminal notebook cell execution.** Users can now run Jupyter Notebook code cells directly in the Open Terminal file navigator, execute entire notebooks with a single click, edit and modify cells before running, and control the kernel - bringing full interactive notebook execution to the browser. [Commit](https://github.com/open-webui/open-webui/commit/4b3ed3e802d6f2ec8ee7caf358af810b7d09f789) +- 🗃️ **Open Terminal SQLite browser.** Users can now browse SQLite database files directly in the Open Terminal file navigator, viewing tables and running queries without downloading them first. [Commit](https://github.com/open-webui/open-webui/commit/a181b4a731a9ec7856be08d0b045a454d1341cf4) +- 📊 **Open Terminal Mermaid diagram rendering.** Markdown files with Mermaid code blocks are now rendered as diagrams directly in the Open Terminal file navigator, making it easier to visualize flowcharts and other diagrams. [Commit](https://github.com/open-webui/open-webui/commit/aaa49bdd6d6e5c10e8be554039d3cac673008fc2) +- 📓 **Open Terminal Jupyter Notebook previews.** Users can now preview Jupyter Notebook files directly in the Open Terminal file navigator, making it easier to view notebook content without downloading them first. [Commit](https://github.com/open-webui/open-webui/commit/b081e33c0a37585a1ee60b6e0e1ea03457f1e5f4) +- 🔃 **Open Terminal auto-refresh.** The Open Terminal file navigator now automatically refreshes when the model writes or modifies files, keeping the view in sync without manual refresh. [Commit](https://github.com/open-webui/open-webui/commit/828656b35f04bf486609183799cf8aa2e9850a76) +- 📋 **Open Terminal file copy button.** Users can now copy file contents directly to clipboard in the Open Terminal file navigator with a single click, making it easier to quickly grab file content without downloading. [Commit](https://github.com/open-webui/open-webui/commit/f5ea1ce250cb02fbc583c6cb3f52a923912d0178) +- 💻 **Code syntax highlighting and XLSX improvements in Open Terminal.** Code files now display with syntax highlighting in the Open Terminal file navigator, and XLSX spreadsheets now show column headers and row numbers for easier navigation. [Commit](https://github.com/open-webui/open-webui/commit/f962bae98306ea9264967b78b803397f4821f9b0) +- 🌳 **Open Terminal JSON tree view.** JSON, JSONC, JSONL, and JSON5 files now display as interactive collapsible tree views in the Open Terminal file navigator, and SVG files render as preview images with syntax highlighting support. [Commit](https://github.com/open-webui/open-webui/commit/f4c38e6001dd9d4853ed923e0bc5e790c4fd9941) +- 🔌 **Open Terminal port viewing.** Users can now view listening ports in the Open Terminal file navigator and open proxy connections to them directly from the UI. [Commit](https://github.com/open-webui/open-webui/commit/e08341dab3bb10e26a64eb44cbebd2d507087b03) +- 🎬 **Open Terminal video previews.** Users can now preview video and audio files directly in the Open Terminal file navigator, making it easier to view media without downloading them first. [Commit](https://github.com/open-webui/open-webui/commit/c40f26946f2eaeb1587a1f8b0c643b4a5121fc06) +- ✏️ **Open Terminal HTML editing.** Users can now edit HTML source files in Open Terminal with CodeMirror editor, and the save button is properly hidden in preview mode. [Commit](https://github.com/open-webui/open-webui/commit/7806cd5aef9fb0505b2c642ef70599a403cf14ba) +- 🧰 **Tool files access.** Tools can now access the files from the current chat context via the files property in their metadata, enabling more powerful tool integrations. [Commit](https://github.com/open-webui/open-webui/commit/35bc8310772c222fd8a466f7d00113a84e0402d0) +- ⚡ **Chat performance.** Chat messages now load and display significantly faster thanks to optimized markdown rendering, eliminating delays when viewing messages with mathematical expressions. [#22196](https://github.com/open-webui/open-webui/pull/22196), [#20878](https://github.com/open-webui/open-webui/discussions/20878) +- ⚡ **Message list performance.** Improved message list rendering performance by optimizing array operations, reducing complexity from O(n²) to O(n). [#22280](https://github.com/open-webui/open-webui/pull/22280) +- ⚡ **Streaming markdown performance.** Improved chat responsiveness during streaming by skipping unnecessary markdown re-parsing when the content hasn't changed, eliminating wasted processing during model pauses. [#22183](https://github.com/open-webui/open-webui/pull/22183) +- ⚡ **Chat streaming performance.** Chat streaming is now faster for users not using the voice call feature by skipping unnecessary text parsing that was running on every token. [#22195](https://github.com/open-webui/open-webui/pull/22195) +- ⚡ **Source list performance.** Source lists in chat now render faster thanks to optimized computation that avoids unnecessary recalculations. [#22279](https://github.com/open-webui/open-webui/pull/22279), [Commit](https://github.com/open-webui/open-webui/commit/88af78c) +- ⚡ **Source list performance.** Optimized source list rendering by moving sourceIds computation to a reactive variable, reducing unnecessary recomputations. [Commit](https://github.com/open-webui/open-webui/commit/339ed1d72e100c89d8eb26de761dfefe842ef90c) +- 💨 **Chat message tree operations.** Chat message tree operations are now significantly faster, improving overall chat responsiveness. [#22194](https://github.com/open-webui/open-webui/pull/22194) +- 🚀 **Initial page load speed.** Page load is now significantly faster thanks to deferred loading of the syntax highlighting library, reducing the initial JavaScript bundle by several megabytes. [#22304](https://github.com/open-webui/open-webui/pull/22304) +- ⚡ **Action priority query optimization.** Improved performance of action priority resolution by fixing an N+1 query pattern, reducing database round-trips when loading model actions. [#22301](https://github.com/open-webui/open-webui/pull/22301) +- ⚡ **API key middleware optimization.** The API key restriction middleware was converted to a pure ASGI middleware for improved streaming performance, removing per-chunk call overhead. [#22188](https://github.com/open-webui/open-webui/pull/22188) +- 🏎️ **Model list loading performance.** Model lists now load significantly faster thanks to optimized custom model matching that uses dictionary lookups instead of nested loops. [#22299](https://github.com/open-webui/open-webui/pull/22299), [Commit](https://github.com/open-webui/open-webui/commit/29160741a3defa8768a43100cb6e63c56400279c), [Commit](https://github.com/open-webui/open-webui/commit/03c6caac1fc8625f85cf1164f5a977be8005c1bc) +- ⏱️ **Event call timeout configuration.** Administrators can now configure the WebSocket event call timeout via the WEBSOCKET_EVENT_CALLER_TIMEOUT environment variable, giving users more time to respond to event_call forms instead of timing out after 60 seconds. [#22222](https://github.com/open-webui/open-webui/pull/22222), [#22220](https://github.com/open-webui/open-webui/issues/22220) +- 📑 **Office file previews.** Users can now preview DOCX, XLSX, and PPTX files directly in the chat file navigator, making it easier to view documents without downloading them first. [Commit](https://github.com/open-webui/open-webui/commit/890949abe6b01d201355a86c50317e20da07dd34) +- 📁 **File refresh button visibility.** The refresh button in the chat file navigator now appears when viewing files as well as directories, allowing users to refresh the file view at any time. [Commit](https://github.com/open-webui/open-webui/commit/49a2e5bf573415dae6d4c7e5bd635e499c8de77a) +- 📂 **Nested folders support.** Users can now create subfolders within parent folders, improving organization of chats. A new "Create Subfolder" option is available in the folder context menu. [#22073](https://github.com/open-webui/open-webui/pull/22073), [Commit](https://github.com/open-webui/open-webui/commit/8913f37c3d8fde7dea6d54a550357f1d495b3941) +- 📢 **Banner loading on navigation.** Admin-configured banners now load when navigating to the homepage, not just on page refresh, ensuring users see new banners immediately. [#22340](https://github.com/open-webui/open-webui/pull/22340), [#22180](https://github.com/open-webui/open-webui/issues/22180) +- 📊 **System metrics via OpenTelemetry.** Administrators can now monitor Python runtime and system metrics including CPU, memory, garbage collection, and thread counts through the existing OpenTelemetry pipeline. [#22265](https://github.com/open-webui/open-webui/pull/22265) +- 🔄 **General improvements.** Various improvements were implemented across the application to enhance performance, stability, and security. +- 🌐 Translations for French, Finnish, Turkish, German, Simplified Chinese, and Traditional Chinese were enhanced and expanded. +- 🔍 **Web search tool guidance.** The web search tool description was updated to encourage direct usage without first checking knowledge bases, making it clearer for users who want to search the web immediately. [#22264](https://github.com/open-webui/open-webui/pull/22264) + +### Fixed + +- 🗄️ **Migration memory usage.** Database migration on large deployments now processes messages in batches instead of loading everything into memory, preventing out-of-memory errors during upgrades. [#21542](https://github.com/open-webui/open-webui/pull/21542), [#21539](https://github.com/open-webui/open-webui/discussions/21539) +- 🔒 **SQLCipher connection stability.** Fixed a crash that occurred when using database encryption with SQLCipher by changing the default connection pool behavior, ensuring stable operation during multi-threaded operations like user signup. [#22273](https://github.com/open-webui/open-webui/pull/22273), [#22258](https://github.com/open-webui/open-webui/issues/22258) +- 🛑 **Stop sequence error.** Fixed a bug where setting stop sequences on a model caused the chat to fail with a split error, preventing any responses from being returned. The fix handles both string and array formats for stop tokens. [#22251](https://github.com/open-webui/open-webui/issues/22251), [Commit](https://github.com/open-webui/open-webui/commit/c7d1d1e390a79c6c86d4bfe439fd7de6f5fb060f) +- 🔐 **Microsoft OAuth refresh token fix.** Fixed a bug where Microsoft OAuth refresh token requests failed with error AADSTS90009 by adding support for the required scope parameter. Users can now stay logged in reliably with Microsoft OAuth. [#22359](https://github.com/open-webui/open-webui/pull/22359) +- 🔧 **Parameterless tool calls.** Fixed parameterless tool calls failing during streaming by correcting the default arguments initialization, eliminating unnecessary model retries. [#22189](https://github.com/open-webui/open-webui/pull/22189) +- 🔧 **Tool call streaming fixes.** Fixed two bugs where streaming tool calls failed silently for models like GPT-5: function names were incorrectly duplicated when sent in multiple delta chunks, and arguments containing multiple JSON objects were not properly split. Tools now execute correctly instead of failing without explanation. [#22177](https://github.com/open-webui/open-webui/issues/22177), [Commit](https://github.com/open-webui/open-webui/commit/d7efdcce2b1cdbe1637a469294bf9d52dbacab53), [Commit](https://github.com/open-webui/open-webui/commit/459a60a24240eab33441ed50f4f68cc27e65a037) +- 🔗 **Tool server URL trailing slash.** Fixed tool server connection failures when URLs have trailing slashes by stripping them before path concatenation. Previously, URLs like "http://host:8080/v1/" + "/openapi.json" produced double-slash URLs that some servers rejected. [#22116](https://github.com/open-webui/open-webui/pull/22116), [#21917](https://github.com/open-webui/open-webui/issues/21917) +- 🔧 **Citation parser error handling.** Fixed crashes when tools return error strings instead of expected data structures by adding type guards to the citation parser. The system now returns an empty source list instead of crashing with AttributeError. [#22118](https://github.com/open-webui/open-webui/pull/22118) +- 🧠 **Artifacts memory leak.** Fixed a memory leak where Svelte store subscriptions in the Artifacts component were not properly cleaned up when the component unmounted, causing memory to accumulate over time. [#22303](https://github.com/open-webui/open-webui/pull/22303) +- ♾️ **Artifacts reactive loop fix.** Fixed an infinite reactive loop in chat when artifacts are present by moving the animation frame logic outside the reactive block, preventing continuous re-rendering and CPU usage. [#22238](https://github.com/open-webui/open-webui/pull/22238), [Commit](https://github.com/open-webui/open-webui/commit/626fcff417afba642f4f71e0498267a21435c524) +- 🔀 **Artifact navigation.** Artifact navigation via arrow buttons now works correctly; the selected artifact is no longer reset when content updates. [#22239](https://github.com/open-webui/open-webui/pull/22239) +- 🖼️ **Artifact thinking block fix.** Fixed a bug where HTML preview rendered code blocks inside thinking blocks for certain models like Mistral and Z.ai, causing stray code with ">" symbols to appear before the actual artifact. The fix strips thinking blocks before extracting code for artifact rendering. [#22267](https://github.com/open-webui/open-webui/issues/22267), [Commit](https://github.com/open-webui/open-webui/commit/35bc8310772c222fd8a466f7d00113a84e0402d0) +- 💬 **Floating Quick Actions availability.** Fixed an issue where the "Ask" and "Explain" Floating Quick Actions were missing when selecting text in chats that used a model that is no longer available. [#22149](https://github.com/open-webui/open-webui/pull/22149), [#22139](https://github.com/open-webui/open-webui/issues/22139) +- 💬 **Follow-up suggestions.** Fixed follow-up suggestions not appearing by correcting contradictory format instructions in the prompt template, ensuring the LLM returns the correct JSON object format. [#22212](https://github.com/open-webui/open-webui/pull/22212) +- 🔊 **TTS thinking content.** Fixed TTS playback reading think tags instead of skipping them by handling edge cases where code blocks inside thinking content prevented proper tag removal. [#22237](https://github.com/open-webui/open-webui/pull/22237), [#22197](https://github.com/open-webui/open-webui/issues/22197) +- 🎨 **Button spinner alignment.** Button spinners across multiple modals now align correctly and stay on the same line as the button text, fixing layout issues when loading states are displayed. [#22227](https://github.com/open-webui/open-webui/pull/22227) +- 🔌 **Terminal keepalive.** Terminal connections now stay active without being closed by idle timeouts from proxies or load balancers, and spurious disconnection messages no longer appear. [Commit](https://github.com/open-webui/open-webui/commit/ca2aaf0321c219d041e92e2c0c842a4e424732ef) +- 📁 **Chat archive handler.** The archive button in the chat navbar now actually archives the chat and refreshes the chat list, instead of doing nothing. [#22229](https://github.com/open-webui/open-webui/pull/22229) +- 🐍 **BeautifulSoup4 dependency.** Added the missing BeautifulSoup4 package to backend requirements, fixing failures when using features that depend on HTML parsing. [#22231](https://github.com/open-webui/open-webui/pull/22231) +- 👥 **Group users default sort.** Group members in the admin panel now sort by last active time by default instead of creation date, making it easier to find active users. [#22211](https://github.com/open-webui/open-webui/pull/22211) +- 🔧 **Tool access permissions.** Users can now change tool and skill access permissions from private to public without errors. [#22325](https://github.com/open-webui/open-webui/pull/22325), [#22324](https://github.com/open-webui/open-webui/issues/22324) +- 🖥️ **Open Terminal permission fix.** Open Terminal is now visible without requiring "Allow Speech to Text" permission, fixing an issue where users without microphone access couldn't access the terminal feature. [#22374](https://github.com/open-webui/open-webui/issues/22374), [Commit](https://github.com/open-webui/open-webui/commit/70a31a9a57bdd0690ac270f31ebd1b46e8fdfa98) +- 📌 **Stale pinned models cleanup.** Pinned models that are deleted or hidden are now automatically unpinned, keeping your pinned models list up to date. [Commit](https://github.com/open-webui/open-webui/commit/af4500e5040c8343d339cd88dd1d2fb6138c7a72) +- 🔧 **OpenTelemetry metric descriptions.** Fixed conflicting metric instrument descriptions that caused warnings in the OpenTelemetry collector, resulting in cleaner telemetry logs for administrators. [#22293](https://github.com/open-webui/open-webui/pull/22293) +- 📊 **Non-streaming token tracking.** Token usage from non-streaming chat responses is now correctly saved to the database, fixing missing token counts in the Admin Panel analytics. Previously, non-streaming responses saved NULL usage data, causing messages to be excluded from token aggregation queries. [#22166](https://github.com/open-webui/open-webui/pull/22166) +- 🔧 **Citation parser error handling.** Fixed crashes when tools return error strings instead of expected data structures by adding type guards to the citation parser. The system now returns an empty source list instead of crashing with AttributeError. [#22118](https://github.com/open-webui/open-webui/pull/22118) +- 🔗 **Tool server URL trailing slash.** Fixed tool server connection failures when URLs have trailing slashes by stripping them before path concatenation. Previously, URLs like "http://host:8080/v1/" + "/openapi.json" produced double-slash URLs that some servers rejected. [#22116](https://github.com/open-webui/open-webui/pull/22116), [#21917](https://github.com/open-webui/open-webui/issues/21917) +- 📝 **Inline code typing.** Fixed a bug where typing inline code with backticks incorrectly deleted the character immediately before the opening backtick, so text formatted as inline code now correctly produces the full word instead of missing the last character. [#20417](https://github.com/open-webui/open-webui/issues/20417), [Commit](https://github.com/open-webui/open-webui/commit/e303c3da3b174da9e92a79b174f85ba574ca06ef) +- 📝 **Variable input newlines.** Fixed a bug where variables containing newlines were not displayed correctly in chat messages, and input values from Windows systems are now properly normalized to use standard line endings. [#21447](https://github.com/open-webui/open-webui/issues/21447), [Commit](https://github.com/open-webui/open-webui/commit/7b2f597b30c77ef300d1966e1c6a3edfdb0c465d) +- 📷 **Android photo capture.** Fixed an issue where the first photo taken in chat appeared completely black on some Android devices by using an alternative canvas export method. [#22317](https://github.com/open-webui/open-webui/pull/22317) +- 🖥️ **Open Terminal Windows path fix.** Fixed a bug where navigating back to parent directories on Windows added an incorrect leading slash, causing directory loads to fail. Paths are now properly normalized for Windows drive letters. [#22352](https://github.com/open-webui/open-webui/issues/22352), [Commit](https://github.com/open-webui/open-webui/commit/044fd1bd15cae06a5c56a321ca79d8362942f66a) +- 🖼️ **Chat overview profile image sizing.** Fixed a bug where profile images in the chat overview could shrink incorrectly in tight spaces. The images now maintain their proper size with the flex-shrink-0 property. [#22261](https://github.com/open-webui/open-webui/pull/22261) +- 💬 **Queued messages display.** Fixed an issue where queued messages could be cut off or hidden. The queued messages area now scrolls properly when content exceeds the visible area, showing up to 25% of the viewport height. [#22176](https://github.com/open-webui/open-webui/pull/22176) +- 🎨 **Image generation in temporary chats.** Generated images now display correctly in temporary chat mode when using builtin image generation tools. Previously, images were not shown because the code was overwriting the image list with a null database response. [#22330](https://github.com/open-webui/open-webui/pull/22330), [#22309](https://github.com/open-webui/open-webui/issues/22309) +- 🤖 **Ollama model unload fix.** Fixed a bug where unloading a model from Ollama via the Open WebUI proxy failed with a "Field required" error for the prompt field. The proxy now correctly allows omitting the prompt when using keep_alive: 0 to unload models. [#22260](https://github.com/open-webui/open-webui/issues/22260), [Commit](https://github.com/open-webui/open-webui/commit/95b65ff751f91131b633cb128ff2decdd87c4a85) +- 📢 **Banner type dropdown fix.** Fixed a bug where selecting a banner type required two clicks to register, as the first selection was being swallowed due to DOM structure changes. The dropdown now works correctly on the first click. [#22378](https://github.com/open-webui/open-webui/pull/22378) +- 📊 **Analytics URL encoding fix.** Fixed a bug where the Analytics page failed to load data for models with slashes in their ID, such as "anthropic/claude-opus-4.6". The frontend now properly URL-encodes forward slashes, allowing model analytics to load correctly. [#22380](https://github.com/open-webui/open-webui/issues/22380), [#22382](https://github.com/open-webui/open-webui/pull/22382) +- 📊 **Analytics chat list duplicate fix.** Fixed a bug where the Analytics page chat list threw an "each_key_duplicate" Svelte error when chat IDs were duplicated during pagination. The fix adds deterministic ordering to prevent duplicate entries. [#22383](https://github.com/open-webui/open-webui/pull/22383) +- 📁 **Folder knowledge base native tool call fix.** Fixed a bug where folders with attached knowledge bases were querying the knowledge base twice when using native tool call mode. The fix now correctly separates knowledge files from regular attachments, letting the builtin query_knowledge_files tool handle knowledge searches instead of duplicating RAG queries. [#22236](https://github.com/open-webui/open-webui/issues/22236), [Commit](https://github.com/open-webui/open-webui/commit/967b1137dcb7a52615f17d086ee89095bb9b60f3), [Commit](https://github.com/open-webui/open-webui/commit/80b5896b70d07ea868e2010b187430d43c9808f0) + ## [0.8.8] - 2026-03-02 ### Added From 223c14f48bfa647e05bc84e7362390e5617bbedd Mon Sep 17 00:00:00 2001 From: Classic298 <27028174+Classic298@users.noreply.github.com> Date: Sun, 8 Mar 2026 03:16:50 +0100 Subject: [PATCH 103/114] fix: add deterministic tiebreaker to all paginated chat queries (#22387) Add Chat.id as a secondary sort key to all paginated chat queries that use offset/limit pagination. When multiple chats share the same updated_at timestamp, the database does not guarantee a stable order across page boundaries, causing chats to appear on multiple pages. This produces duplicate keys in the Svelte sidebar each-block (each_key_duplicate error). Adding Chat.id as a tiebreaker ensures fully deterministic ordering. Extends the fix from #22383 (which addressed get_chat_ids_by_model_id) to all remaining paginated chat queries. --- backend/open_webui/models/chats.py | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/backend/open_webui/models/chats.py b/backend/open_webui/models/chats.py index 8c6eb830b5..9b8261b8d4 100644 --- a/backend/open_webui/models/chats.py +++ b/backend/open_webui/models/chats.py @@ -734,13 +734,13 @@ def get_archived_chat_list_by_user_id( raise ValueError("Invalid order_by field") if direction.lower() == "asc": - query = query.order_by(getattr(Chat, order_by).asc()) + query = query.order_by(getattr(Chat, order_by).asc(), Chat.id) elif direction.lower() == "desc": - query = query.order_by(getattr(Chat, order_by).desc()) + query = query.order_by(getattr(Chat, order_by).desc(), Chat.id) else: raise ValueError("Invalid direction for ordering") else: - query = query.order_by(Chat.updated_at.desc()) + query = query.order_by(Chat.updated_at.desc(), Chat.id) query = query.with_entities( Chat.id, Chat.title, Chat.updated_at, Chat.created_at @@ -793,13 +793,13 @@ def get_shared_chat_list_by_user_id( raise ValueError("Invalid order_by field") if direction.lower() == "asc": - query = query.order_by(getattr(Chat, order_by).asc()) + query = query.order_by(getattr(Chat, order_by).asc(), Chat.id) elif direction.lower() == "desc": - query = query.order_by(getattr(Chat, order_by).desc()) + query = query.order_by(getattr(Chat, order_by).desc(), Chat.id) else: raise ValueError("Invalid direction for ordering") else: - query = query.order_by(Chat.updated_at.desc()) + query = query.order_by(Chat.updated_at.desc(), Chat.id) # Select only the columns needed for SharedChatResponse # to avoid loading the heavy chat JSON blob @@ -854,13 +854,13 @@ def get_chat_list_by_user_id( if order_by and direction and getattr(Chat, order_by): if direction.lower() == "asc": - query = query.order_by(getattr(Chat, order_by).asc()) + query = query.order_by(getattr(Chat, order_by).asc(), Chat.id) elif direction.lower() == "desc": - query = query.order_by(getattr(Chat, order_by).desc()) + query = query.order_by(getattr(Chat, order_by).desc(), Chat.id) else: raise ValueError("Invalid direction for ordering") else: - query = query.order_by(Chat.updated_at.desc()) + query = query.order_by(Chat.updated_at.desc(), Chat.id) if skip: query = query.offset(skip) @@ -892,7 +892,7 @@ def get_chat_title_id_list_by_user_id( if not include_archived: query = query.filter_by(archived=False) - query = query.order_by(Chat.updated_at.desc()).with_entities( + query = query.order_by(Chat.updated_at.desc(), Chat.id).with_entities( Chat.id, Chat.title, Chat.updated_at, Chat.created_at ) @@ -1039,14 +1039,14 @@ def get_chats_by_user_id( if order_by and direction: if hasattr(Chat, order_by): if direction.lower() == "asc": - query = query.order_by(getattr(Chat, order_by).asc()) + query = query.order_by(getattr(Chat, order_by).asc(), Chat.id) elif direction.lower() == "desc": - query = query.order_by(getattr(Chat, order_by).desc()) + query = query.order_by(getattr(Chat, order_by).desc(), Chat.id) else: - query = query.order_by(Chat.updated_at.desc()) + query = query.order_by(Chat.updated_at.desc(), Chat.id) else: - query = query.order_by(Chat.updated_at.desc()) + query = query.order_by(Chat.updated_at.desc(), Chat.id) total = query.count() @@ -1188,7 +1188,7 @@ def get_chats_by_user_id_and_search_text( if folder_ids: query = query.filter(Chat.folder_id.in_(folder_ids)) - query = query.order_by(Chat.updated_at.desc()) + query = query.order_by(Chat.updated_at.desc(), Chat.id) # Check if the database dialect is either 'sqlite' or 'postgresql' dialect_name = db.bind.dialect.name @@ -1309,7 +1309,7 @@ def get_chats_by_folder_id_and_user_id( query = query.filter(or_(Chat.pinned == False, Chat.pinned == None)) query = query.filter_by(archived=False) - query = query.order_by(Chat.updated_at.desc()) + query = query.order_by(Chat.updated_at.desc(), Chat.id) if skip: query = query.offset(skip) From bd456ed10b04ae1b614f69b7f929c78fee1a12a2 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:17:51 -0600 Subject: [PATCH 104/114] doc: changelog --- CHANGELOG.md | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8e945a6769..8fe8064414 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,10 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [0.8.9] - 2026-03-09 +## [0.8.9] - 2026-03-07 ### Added -- 📁 **Pyodide file system support.** Users can now upload files for Python code execution in the code interpreter. Uploaded files are available in the `/mnt/uploads/` directory, and code can write output files there for download. The file system persists across code executions within the same session. The code interpreter now also informs models that pip install is not available in the Pyodide environment, guiding them to use alternative approaches with available modules. [#3583](https://github.com/open-webui/open-webui/issues/3583), [Commit](https://github.com/open-webui/open-webui/commit/ce0ca894fea8a2904bc6f832ff186d5fe53dd0b9), [Commit](https://github.com/open-webui/open-webui/commit/989938856fdb4b4afa584ae2d18c88d5be614ae2) - ▶️ **Open Terminal notebook cell execution.** Users can now run Jupyter Notebook code cells directly in the Open Terminal file navigator, execute entire notebooks with a single click, edit and modify cells before running, and control the kernel - bringing full interactive notebook execution to the browser. [Commit](https://github.com/open-webui/open-webui/commit/4b3ed3e802d6f2ec8ee7caf358af810b7d09f789) - 🗃️ **Open Terminal SQLite browser.** Users can now browse SQLite database files directly in the Open Terminal file navigator, viewing tables and running queries without downloading them first. [Commit](https://github.com/open-webui/open-webui/commit/a181b4a731a9ec7856be08d0b045a454d1341cf4) - 📊 **Open Terminal Mermaid diagram rendering.** Markdown files with Mermaid code blocks are now rendered as diagrams directly in the Open Terminal file navigator, making it easier to visualize flowcharts and other diagrams. [Commit](https://github.com/open-webui/open-webui/commit/aaa49bdd6d6e5c10e8be554039d3cac673008fc2) @@ -21,24 +20,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 🔌 **Open Terminal port viewing.** Users can now view listening ports in the Open Terminal file navigator and open proxy connections to them directly from the UI. [Commit](https://github.com/open-webui/open-webui/commit/e08341dab3bb10e26a64eb44cbebd2d507087b03) - 🎬 **Open Terminal video previews.** Users can now preview video and audio files directly in the Open Terminal file navigator, making it easier to view media without downloading them first. [Commit](https://github.com/open-webui/open-webui/commit/c40f26946f2eaeb1587a1f8b0c643b4a5121fc06) - ✏️ **Open Terminal HTML editing.** Users can now edit HTML source files in Open Terminal with CodeMirror editor, and the save button is properly hidden in preview mode. [Commit](https://github.com/open-webui/open-webui/commit/7806cd5aef9fb0505b2c642ef70599a403cf14ba) +- 📁 **Pyodide file system support.** Users can now upload files for Python code execution in the code interpreter. Uploaded files are available in the `/mnt/uploads/` directory, and code can write output files there for download. The file system persists across code executions within the same session. The code interpreter now also informs models that pip install is not available in the Pyodide environment, guiding them to use alternative approaches with available modules. [#3583](https://github.com/open-webui/open-webui/issues/3583), [Commit](https://github.com/open-webui/open-webui/commit/ce0ca894fea8a2904bc6f832ff186d5fe53dd0b9), [Commit](https://github.com/open-webui/open-webui/commit/989938856fdb4b4afa584ae2d18c88d5be614ae2) - 🧰 **Tool files access.** Tools can now access the files from the current chat context via the files property in their metadata, enabling more powerful tool integrations. [Commit](https://github.com/open-webui/open-webui/commit/35bc8310772c222fd8a466f7d00113a84e0402d0) - ⚡ **Chat performance.** Chat messages now load and display significantly faster thanks to optimized markdown rendering, eliminating delays when viewing messages with mathematical expressions. [#22196](https://github.com/open-webui/open-webui/pull/22196), [#20878](https://github.com/open-webui/open-webui/discussions/20878) -- ⚡ **Message list performance.** Improved message list rendering performance by optimizing array operations, reducing complexity from O(n²) to O(n). [#22280](https://github.com/open-webui/open-webui/pull/22280) -- ⚡ **Streaming markdown performance.** Improved chat responsiveness during streaming by skipping unnecessary markdown re-parsing when the content hasn't changed, eliminating wasted processing during model pauses. [#22183](https://github.com/open-webui/open-webui/pull/22183) -- ⚡ **Chat streaming performance.** Chat streaming is now faster for users not using the voice call feature by skipping unnecessary text parsing that was running on every token. [#22195](https://github.com/open-webui/open-webui/pull/22195) -- ⚡ **Source list performance.** Source lists in chat now render faster thanks to optimized computation that avoids unnecessary recalculations. [#22279](https://github.com/open-webui/open-webui/pull/22279), [Commit](https://github.com/open-webui/open-webui/commit/88af78c) -- ⚡ **Source list performance.** Optimized source list rendering by moving sourceIds computation to a reactive variable, reducing unnecessary recomputations. [Commit](https://github.com/open-webui/open-webui/commit/339ed1d72e100c89d8eb26de761dfefe842ef90c) +- 📋 **Message list performance.** Improved message list rendering performance by optimizing array operations, reducing complexity from O(n²) to O(n). [#22280](https://github.com/open-webui/open-webui/pull/22280) +- 🧵 **Streaming markdown performance.** Improved chat responsiveness during streaming by skipping unnecessary markdown re-parsing when the content hasn't changed, eliminating wasted processing during model pauses. [#22183](https://github.com/open-webui/open-webui/pull/22183) +- 🏃 **Chat streaming performance.** Chat streaming is now faster for users not using the voice call feature by skipping unnecessary text parsing that was running on every token. [#22195](https://github.com/open-webui/open-webui/pull/22195) +- 📑 **Source list performance.** Source lists in chat now render faster thanks to optimized computation that avoids unnecessary recalculations, including moving sourceIds computation to a reactive variable. [#22279](https://github.com/open-webui/open-webui/pull/22279), [Commit](https://github.com/open-webui/open-webui/commit/88af78c), [Commit](https://github.com/open-webui/open-webui/commit/339ed1d72e100c89d8eb26de761dfefe842ef90c) - 💨 **Chat message tree operations.** Chat message tree operations are now significantly faster, improving overall chat responsiveness. [#22194](https://github.com/open-webui/open-webui/pull/22194) - 🚀 **Initial page load speed.** Page load is now significantly faster thanks to deferred loading of the syntax highlighting library, reducing the initial JavaScript bundle by several megabytes. [#22304](https://github.com/open-webui/open-webui/pull/22304) -- ⚡ **Action priority query optimization.** Improved performance of action priority resolution by fixing an N+1 query pattern, reducing database round-trips when loading model actions. [#22301](https://github.com/open-webui/open-webui/pull/22301) -- ⚡ **API key middleware optimization.** The API key restriction middleware was converted to a pure ASGI middleware for improved streaming performance, removing per-chunk call overhead. [#22188](https://github.com/open-webui/open-webui/pull/22188) +- 🗂️ **Action priority query optimization.** Improved performance of action priority resolution by fixing an N+1 query pattern, reducing database round-trips when loading model actions. [#22301](https://github.com/open-webui/open-webui/pull/22301) +- 🔑 **API key middleware optimization.** The API key restriction middleware was converted to a pure ASGI middleware for improved streaming performance, removing per-chunk call overhead. [#22188](https://github.com/open-webui/open-webui/pull/22188) - 🏎️ **Model list loading performance.** Model lists now load significantly faster thanks to optimized custom model matching that uses dictionary lookups instead of nested loops. [#22299](https://github.com/open-webui/open-webui/pull/22299), [Commit](https://github.com/open-webui/open-webui/commit/29160741a3defa8768a43100cb6e63c56400279c), [Commit](https://github.com/open-webui/open-webui/commit/03c6caac1fc8625f85cf1164f5a977be8005c1bc) - ⏱️ **Event call timeout configuration.** Administrators can now configure the WebSocket event call timeout via the WEBSOCKET_EVENT_CALLER_TIMEOUT environment variable, giving users more time to respond to event_call forms instead of timing out after 60 seconds. [#22222](https://github.com/open-webui/open-webui/pull/22222), [#22220](https://github.com/open-webui/open-webui/issues/22220) - 📑 **Office file previews.** Users can now preview DOCX, XLSX, and PPTX files directly in the chat file navigator, making it easier to view documents without downloading them first. [Commit](https://github.com/open-webui/open-webui/commit/890949abe6b01d201355a86c50317e20da07dd34) -- 📁 **File refresh button visibility.** The refresh button in the chat file navigator now appears when viewing files as well as directories, allowing users to refresh the file view at any time. [Commit](https://github.com/open-webui/open-webui/commit/49a2e5bf573415dae6d4c7e5bd635e499c8de77a) +- 🔄 **File refresh button visibility.** The refresh button in the chat file navigator now appears when viewing files as well as directories, allowing users to refresh the file view at any time. [Commit](https://github.com/open-webui/open-webui/commit/49a2e5bf573415dae6d4c7e5bd635e499c8de77a) - 📂 **Nested folders support.** Users can now create subfolders within parent folders, improving organization of chats. A new "Create Subfolder" option is available in the folder context menu. [#22073](https://github.com/open-webui/open-webui/pull/22073), [Commit](https://github.com/open-webui/open-webui/commit/8913f37c3d8fde7dea6d54a550357f1d495b3941) - 📢 **Banner loading on navigation.** Admin-configured banners now load when navigating to the homepage, not just on page refresh, ensuring users see new banners immediately. [#22340](https://github.com/open-webui/open-webui/pull/22340), [#22180](https://github.com/open-webui/open-webui/issues/22180) -- 📊 **System metrics via OpenTelemetry.** Administrators can now monitor Python runtime and system metrics including CPU, memory, garbage collection, and thread counts through the existing OpenTelemetry pipeline. [#22265](https://github.com/open-webui/open-webui/pull/22265) +- 📡 **System metrics via OpenTelemetry.** Administrators can now monitor Python runtime and system metrics including CPU, memory, garbage collection, and thread counts through the existing OpenTelemetry pipeline. [#22265](https://github.com/open-webui/open-webui/pull/22265) - 🔄 **General improvements.** Various improvements were implemented across the application to enhance performance, stability, and security. - 🌐 Translations for French, Finnish, Turkish, German, Simplified Chinese, and Traditional Chinese were enhanced and expanded. - 🔍 **Web search tool guidance.** The web search tool description was updated to encourage direct usage without first checking knowledge bases, making it clearer for users who want to search the web immediately. [#22264](https://github.com/open-webui/open-webui/pull/22264) @@ -49,41 +48,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 🔒 **SQLCipher connection stability.** Fixed a crash that occurred when using database encryption with SQLCipher by changing the default connection pool behavior, ensuring stable operation during multi-threaded operations like user signup. [#22273](https://github.com/open-webui/open-webui/pull/22273), [#22258](https://github.com/open-webui/open-webui/issues/22258) - 🛑 **Stop sequence error.** Fixed a bug where setting stop sequences on a model caused the chat to fail with a split error, preventing any responses from being returned. The fix handles both string and array formats for stop tokens. [#22251](https://github.com/open-webui/open-webui/issues/22251), [Commit](https://github.com/open-webui/open-webui/commit/c7d1d1e390a79c6c86d4bfe439fd7de6f5fb060f) - 🔐 **Microsoft OAuth refresh token fix.** Fixed a bug where Microsoft OAuth refresh token requests failed with error AADSTS90009 by adding support for the required scope parameter. Users can now stay logged in reliably with Microsoft OAuth. [#22359](https://github.com/open-webui/open-webui/pull/22359) -- 🔧 **Parameterless tool calls.** Fixed parameterless tool calls failing during streaming by correcting the default arguments initialization, eliminating unnecessary model retries. [#22189](https://github.com/open-webui/open-webui/pull/22189) +- 🛠️ **Parameterless tool calls.** Fixed parameterless tool calls failing during streaming by correcting the default arguments initialization, eliminating unnecessary model retries. [#22189](https://github.com/open-webui/open-webui/pull/22189) - 🔧 **Tool call streaming fixes.** Fixed two bugs where streaming tool calls failed silently for models like GPT-5: function names were incorrectly duplicated when sent in multiple delta chunks, and arguments containing multiple JSON objects were not properly split. Tools now execute correctly instead of failing without explanation. [#22177](https://github.com/open-webui/open-webui/issues/22177), [Commit](https://github.com/open-webui/open-webui/commit/d7efdcce2b1cdbe1637a469294bf9d52dbacab53), [Commit](https://github.com/open-webui/open-webui/commit/459a60a24240eab33441ed50f4f68cc27e65a037) - 🔗 **Tool server URL trailing slash.** Fixed tool server connection failures when URLs have trailing slashes by stripping them before path concatenation. Previously, URLs like "http://host:8080/v1/" + "/openapi.json" produced double-slash URLs that some servers rejected. [#22116](https://github.com/open-webui/open-webui/pull/22116), [#21917](https://github.com/open-webui/open-webui/issues/21917) -- 🔧 **Citation parser error handling.** Fixed crashes when tools return error strings instead of expected data structures by adding type guards to the citation parser. The system now returns an empty source list instead of crashing with AttributeError. [#22118](https://github.com/open-webui/open-webui/pull/22118) +- 🛡️ **Citation parser error handling.** Fixed crashes when tools return error strings instead of expected data structures by adding type guards to the citation parser. The system now returns an empty source list instead of crashing with AttributeError. [#22118](https://github.com/open-webui/open-webui/pull/22118) - 🧠 **Artifacts memory leak.** Fixed a memory leak where Svelte store subscriptions in the Artifacts component were not properly cleaned up when the component unmounted, causing memory to accumulate over time. [#22303](https://github.com/open-webui/open-webui/pull/22303) - ♾️ **Artifacts reactive loop fix.** Fixed an infinite reactive loop in chat when artifacts are present by moving the animation frame logic outside the reactive block, preventing continuous re-rendering and CPU usage. [#22238](https://github.com/open-webui/open-webui/pull/22238), [Commit](https://github.com/open-webui/open-webui/commit/626fcff417afba642f4f71e0498267a21435c524) - 🔀 **Artifact navigation.** Artifact navigation via arrow buttons now works correctly; the selected artifact is no longer reset when content updates. [#22239](https://github.com/open-webui/open-webui/pull/22239) -- 🖼️ **Artifact thinking block fix.** Fixed a bug where HTML preview rendered code blocks inside thinking blocks for certain models like Mistral and Z.ai, causing stray code with ">" symbols to appear before the actual artifact. The fix strips thinking blocks before extracting code for artifact rendering. [#22267](https://github.com/open-webui/open-webui/issues/22267), [Commit](https://github.com/open-webui/open-webui/commit/35bc8310772c222fd8a466f7d00113a84e0402d0) +- 🧩 **Artifact thinking block fix.** Fixed a bug where HTML preview rendered code blocks inside thinking blocks for certain models like Mistral and Z.ai, causing stray code with ">" symbols to appear before the actual artifact. The fix strips thinking blocks before extracting code for artifact rendering. [#22267](https://github.com/open-webui/open-webui/issues/22267), [Commit](https://github.com/open-webui/open-webui/commit/35bc8310772c222fd8a466f7d00113a84e0402d0) - 💬 **Floating Quick Actions availability.** Fixed an issue where the "Ask" and "Explain" Floating Quick Actions were missing when selecting text in chats that used a model that is no longer available. [#22149](https://github.com/open-webui/open-webui/pull/22149), [#22139](https://github.com/open-webui/open-webui/issues/22139) -- 💬 **Follow-up suggestions.** Fixed follow-up suggestions not appearing by correcting contradictory format instructions in the prompt template, ensuring the LLM returns the correct JSON object format. [#22212](https://github.com/open-webui/open-webui/pull/22212) +- 💡 **Follow-up suggestions.** Fixed follow-up suggestions not appearing by correcting contradictory format instructions in the prompt template, ensuring the LLM returns the correct JSON object format. [#22212](https://github.com/open-webui/open-webui/pull/22212) - 🔊 **TTS thinking content.** Fixed TTS playback reading think tags instead of skipping them by handling edge cases where code blocks inside thinking content prevented proper tag removal. [#22237](https://github.com/open-webui/open-webui/pull/22237), [#22197](https://github.com/open-webui/open-webui/issues/22197) - 🎨 **Button spinner alignment.** Button spinners across multiple modals now align correctly and stay on the same line as the button text, fixing layout issues when loading states are displayed. [#22227](https://github.com/open-webui/open-webui/pull/22227) - 🔌 **Terminal keepalive.** Terminal connections now stay active without being closed by idle timeouts from proxies or load balancers, and spurious disconnection messages no longer appear. [Commit](https://github.com/open-webui/open-webui/commit/ca2aaf0321c219d041e92e2c0c842a4e424732ef) -- 📁 **Chat archive handler.** The archive button in the chat navbar now actually archives the chat and refreshes the chat list, instead of doing nothing. [#22229](https://github.com/open-webui/open-webui/pull/22229) +- 🗃️ **Chat archive handler.** The archive button in the chat navbar now actually archives the chat and refreshes the chat list, instead of doing nothing. [#22229](https://github.com/open-webui/open-webui/pull/22229) - 🐍 **BeautifulSoup4 dependency.** Added the missing BeautifulSoup4 package to backend requirements, fixing failures when using features that depend on HTML parsing. [#22231](https://github.com/open-webui/open-webui/pull/22231) - 👥 **Group users default sort.** Group members in the admin panel now sort by last active time by default instead of creation date, making it easier to find active users. [#22211](https://github.com/open-webui/open-webui/pull/22211) -- 🔧 **Tool access permissions.** Users can now change tool and skill access permissions from private to public without errors. [#22325](https://github.com/open-webui/open-webui/pull/22325), [#22324](https://github.com/open-webui/open-webui/issues/22324) +- 🔓 **Tool access permissions.** Users can now change tool and skill access permissions from private to public without errors. [#22325](https://github.com/open-webui/open-webui/pull/22325), [#22324](https://github.com/open-webui/open-webui/issues/22324) - 🖥️ **Open Terminal permission fix.** Open Terminal is now visible without requiring "Allow Speech to Text" permission, fixing an issue where users without microphone access couldn't access the terminal feature. [#22374](https://github.com/open-webui/open-webui/issues/22374), [Commit](https://github.com/open-webui/open-webui/commit/70a31a9a57bdd0690ac270f31ebd1b46e8fdfa98) - 📌 **Stale pinned models cleanup.** Pinned models that are deleted or hidden are now automatically unpinned, keeping your pinned models list up to date. [Commit](https://github.com/open-webui/open-webui/commit/af4500e5040c8343d339cd88dd1d2fb6138c7a72) -- 🔧 **OpenTelemetry metric descriptions.** Fixed conflicting metric instrument descriptions that caused warnings in the OpenTelemetry collector, resulting in cleaner telemetry logs for administrators. [#22293](https://github.com/open-webui/open-webui/pull/22293) -- 📊 **Non-streaming token tracking.** Token usage from non-streaming chat responses is now correctly saved to the database, fixing missing token counts in the Admin Panel analytics. Previously, non-streaming responses saved NULL usage data, causing messages to be excluded from token aggregation queries. [#22166](https://github.com/open-webui/open-webui/pull/22166) -- 🔧 **Citation parser error handling.** Fixed crashes when tools return error strings instead of expected data structures by adding type guards to the citation parser. The system now returns an empty source list instead of crashing with AttributeError. [#22118](https://github.com/open-webui/open-webui/pull/22118) -- 🔗 **Tool server URL trailing slash.** Fixed tool server connection failures when URLs have trailing slashes by stripping them before path concatenation. Previously, URLs like "http://host:8080/v1/" + "/openapi.json" produced double-slash URLs that some servers rejected. [#22116](https://github.com/open-webui/open-webui/pull/22116), [#21917](https://github.com/open-webui/open-webui/issues/21917) -- 📝 **Inline code typing.** Fixed a bug where typing inline code with backticks incorrectly deleted the character immediately before the opening backtick, so text formatted as inline code now correctly produces the full word instead of missing the last character. [#20417](https://github.com/open-webui/open-webui/issues/20417), [Commit](https://github.com/open-webui/open-webui/commit/e303c3da3b174da9e92a79b174f85ba574ca06ef) +- 📏 **OpenTelemetry metric descriptions.** Fixed conflicting metric instrument descriptions that caused warnings in the OpenTelemetry collector, resulting in cleaner telemetry logs for administrators. [#22293](https://github.com/open-webui/open-webui/pull/22293) +- 🔢 **Non-streaming token tracking.** Token usage from non-streaming chat responses is now correctly saved to the database, fixing missing token counts in the Admin Panel analytics. Previously, non-streaming responses saved NULL usage data, causing messages to be excluded from token aggregation queries. [#22166](https://github.com/open-webui/open-webui/pull/22166) +- ⌨️ **Inline code typing.** Fixed a bug where typing inline code with backticks incorrectly deleted the character immediately before the opening backtick, so text formatted as inline code now correctly produces the full word instead of missing the last character. [#20417](https://github.com/open-webui/open-webui/issues/20417), [Commit](https://github.com/open-webui/open-webui/commit/e303c3da3b174da9e92a79b174f85ba574ca06ef) - 📝 **Variable input newlines.** Fixed a bug where variables containing newlines were not displayed correctly in chat messages, and input values from Windows systems are now properly normalized to use standard line endings. [#21447](https://github.com/open-webui/open-webui/issues/21447), [Commit](https://github.com/open-webui/open-webui/commit/7b2f597b30c77ef300d1966e1c6a3edfdb0c465d) - 📷 **Android photo capture.** Fixed an issue where the first photo taken in chat appeared completely black on some Android devices by using an alternative canvas export method. [#22317](https://github.com/open-webui/open-webui/pull/22317) -- 🖥️ **Open Terminal Windows path fix.** Fixed a bug where navigating back to parent directories on Windows added an incorrect leading slash, causing directory loads to fail. Paths are now properly normalized for Windows drive letters. [#22352](https://github.com/open-webui/open-webui/issues/22352), [Commit](https://github.com/open-webui/open-webui/commit/044fd1bd15cae06a5c56a321ca79d8362942f66a) +- 🪟 **Open Terminal Windows path fix.** Fixed a bug where navigating back to parent directories on Windows added an incorrect leading slash, causing directory loads to fail. Paths are now properly normalized for Windows drive letters. [#22352](https://github.com/open-webui/open-webui/issues/22352), [Commit](https://github.com/open-webui/open-webui/commit/044fd1bd15cae06a5c56a321ca79d8362942f66a) - 🖼️ **Chat overview profile image sizing.** Fixed a bug where profile images in the chat overview could shrink incorrectly in tight spaces. The images now maintain their proper size with the flex-shrink-0 property. [#22261](https://github.com/open-webui/open-webui/pull/22261) -- 💬 **Queued messages display.** Fixed an issue where queued messages could be cut off or hidden. The queued messages area now scrolls properly when content exceeds the visible area, showing up to 25% of the viewport height. [#22176](https://github.com/open-webui/open-webui/pull/22176) +- 📨 **Queued messages display.** Fixed an issue where queued messages could be cut off or hidden. The queued messages area now scrolls properly when content exceeds the visible area, showing up to 25% of the viewport height. [#22176](https://github.com/open-webui/open-webui/pull/22176) - 🎨 **Image generation in temporary chats.** Generated images now display correctly in temporary chat mode when using builtin image generation tools. Previously, images were not shown because the code was overwriting the image list with a null database response. [#22330](https://github.com/open-webui/open-webui/pull/22330), [#22309](https://github.com/open-webui/open-webui/issues/22309) - 🤖 **Ollama model unload fix.** Fixed a bug where unloading a model from Ollama via the Open WebUI proxy failed with a "Field required" error for the prompt field. The proxy now correctly allows omitting the prompt when using keep_alive: 0 to unload models. [#22260](https://github.com/open-webui/open-webui/issues/22260), [Commit](https://github.com/open-webui/open-webui/commit/95b65ff751f91131b633cb128ff2decdd87c4a85) - 📢 **Banner type dropdown fix.** Fixed a bug where selecting a banner type required two clicks to register, as the first selection was being swallowed due to DOM structure changes. The dropdown now works correctly on the first click. [#22378](https://github.com/open-webui/open-webui/pull/22378) -- 📊 **Analytics URL encoding fix.** Fixed a bug where the Analytics page failed to load data for models with slashes in their ID, such as "anthropic/claude-opus-4.6". The frontend now properly URL-encodes forward slashes, allowing model analytics to load correctly. [#22380](https://github.com/open-webui/open-webui/issues/22380), [#22382](https://github.com/open-webui/open-webui/pull/22382) +- 📈 **Analytics URL encoding fix.** Fixed a bug where the Analytics page failed to load data for models with slashes in their ID, such as "anthropic/claude-opus-4.6". The frontend now properly URL-encodes forward slashes, allowing model analytics to load correctly. [#22380](https://github.com/open-webui/open-webui/issues/22380), [#22382](https://github.com/open-webui/open-webui/pull/22382) - 📊 **Analytics chat list duplicate fix.** Fixed a bug where the Analytics page chat list threw an "each_key_duplicate" Svelte error when chat IDs were duplicated during pagination. The fix adds deterministic ordering to prevent duplicate entries. [#22383](https://github.com/open-webui/open-webui/pull/22383) -- 📁 **Folder knowledge base native tool call fix.** Fixed a bug where folders with attached knowledge bases were querying the knowledge base twice when using native tool call mode. The fix now correctly separates knowledge files from regular attachments, letting the builtin query_knowledge_files tool handle knowledge searches instead of duplicating RAG queries. [#22236](https://github.com/open-webui/open-webui/issues/22236), [Commit](https://github.com/open-webui/open-webui/commit/967b1137dcb7a52615f17d086ee89095bb9b60f3), [Commit](https://github.com/open-webui/open-webui/commit/80b5896b70d07ea868e2010b187430d43c9808f0) +- 📂 **Folder knowledge base native tool call fix.** Fixed a bug where folders with attached knowledge bases were querying the knowledge base twice when using native tool call mode. The fix now correctly separates knowledge files from regular attachments, letting the builtin query_knowledge_files tool handle knowledge searches instead of duplicating RAG queries. [#22236](https://github.com/open-webui/open-webui/issues/22236), [Commit](https://github.com/open-webui/open-webui/commit/967b1137dcb7a52615f17d086ee89095bb9b60f3), [Commit](https://github.com/open-webui/open-webui/commit/80b5896b70d07ea868e2010b187430d43c9808f0) ## [0.8.8] - 2026-03-02 From 0948235c3b09427830b9e3eb06dd5f1eb497a17f Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:21:06 -0600 Subject: [PATCH 105/114] refac --- CHANGELOG.md | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fe8064414..259f2f61ee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,32 +11,34 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - ▶️ **Open Terminal notebook cell execution.** Users can now run Jupyter Notebook code cells directly in the Open Terminal file navigator, execute entire notebooks with a single click, edit and modify cells before running, and control the kernel - bringing full interactive notebook execution to the browser. [Commit](https://github.com/open-webui/open-webui/commit/4b3ed3e802d6f2ec8ee7caf358af810b7d09f789) - 🗃️ **Open Terminal SQLite browser.** Users can now browse SQLite database files directly in the Open Terminal file navigator, viewing tables and running queries without downloading them first. [Commit](https://github.com/open-webui/open-webui/commit/a181b4a731a9ec7856be08d0b045a454d1341cf4) -- 📊 **Open Terminal Mermaid diagram rendering.** Markdown files with Mermaid code blocks are now rendered as diagrams directly in the Open Terminal file navigator, making it easier to visualize flowcharts and other diagrams. [Commit](https://github.com/open-webui/open-webui/commit/aaa49bdd6d6e5c10e8be554039d3cac673008fc2) +- 📉 **Open Terminal Mermaid diagram rendering.** Markdown files with Mermaid code blocks are now rendered as diagrams directly in the Open Terminal file navigator, making it easier to visualize flowcharts and other diagrams. [Commit](https://github.com/open-webui/open-webui/commit/aaa49bdd6d6e5c10e8be554039d3cac673008fc2) - 📓 **Open Terminal Jupyter Notebook previews.** Users can now preview Jupyter Notebook files directly in the Open Terminal file navigator, making it easier to view notebook content without downloading them first. [Commit](https://github.com/open-webui/open-webui/commit/b081e33c0a37585a1ee60b6e0e1ea03457f1e5f4) - 🔃 **Open Terminal auto-refresh.** The Open Terminal file navigator now automatically refreshes when the model writes or modifies files, keeping the view in sync without manual refresh. [Commit](https://github.com/open-webui/open-webui/commit/828656b35f04bf486609183799cf8aa2e9850a76) -- 📋 **Open Terminal file copy button.** Users can now copy file contents directly to clipboard in the Open Terminal file navigator with a single click, making it easier to quickly grab file content without downloading. [Commit](https://github.com/open-webui/open-webui/commit/f5ea1ce250cb02fbc583c6cb3f52a923912d0178) +- 📎 **Open Terminal file copy button.** Users can now copy file contents directly to clipboard in the Open Terminal file navigator with a single click, making it easier to quickly grab file content without downloading. [Commit](https://github.com/open-webui/open-webui/commit/f5ea1ce250cb02fbc583c6cb3f52a923912d0178) - 💻 **Code syntax highlighting and XLSX improvements in Open Terminal.** Code files now display with syntax highlighting in the Open Terminal file navigator, and XLSX spreadsheets now show column headers and row numbers for easier navigation. [Commit](https://github.com/open-webui/open-webui/commit/f962bae98306ea9264967b78b803397f4821f9b0) - 🌳 **Open Terminal JSON tree view.** JSON, JSONC, JSONL, and JSON5 files now display as interactive collapsible tree views in the Open Terminal file navigator, and SVG files render as preview images with syntax highlighting support. [Commit](https://github.com/open-webui/open-webui/commit/f4c38e6001dd9d4853ed923e0bc5e790c4fd9941) -- 🔌 **Open Terminal port viewing.** Users can now view listening ports in the Open Terminal file navigator and open proxy connections to them directly from the UI. [Commit](https://github.com/open-webui/open-webui/commit/e08341dab3bb10e26a64eb44cbebd2d507087b03) +- 🛜 **Open Terminal port viewing.** Users can now view listening ports in the Open Terminal file navigator and open proxy connections to them directly from the UI. [Commit](https://github.com/open-webui/open-webui/commit/e08341dab3bb10e26a64eb44cbebd2d507087b03) - 🎬 **Open Terminal video previews.** Users can now preview video and audio files directly in the Open Terminal file navigator, making it easier to view media without downloading them first. [Commit](https://github.com/open-webui/open-webui/commit/c40f26946f2eaeb1587a1f8b0c643b4a5121fc06) - ✏️ **Open Terminal HTML editing.** Users can now edit HTML source files in Open Terminal with CodeMirror editor, and the save button is properly hidden in preview mode. [Commit](https://github.com/open-webui/open-webui/commit/7806cd5aef9fb0505b2c642ef70599a403cf14ba) +- 📄 **Open Terminal DOCX preview.** Word documents generated or modified by the AI can now be viewed directly in the file navigator with formatted text, tables, and images rendered inline — no need to download and open in a separate application. [Commit](https://github.com/open-webui/open-webui/commit/890949abe6b01d201355a86c50317e20da07dd34) +- 📊 **Open Terminal XLSX preview.** Excel spreadsheets in the file navigator now render as interactive tables with column headers and row numbers, making it easy to verify data the AI has generated or processed. [Commit](https://github.com/open-webui/open-webui/commit/890949abe6b01d201355a86c50317e20da07dd34) +- 📽️ **Open Terminal PPTX preview.** PowerPoint presentations created by the AI can now be viewed slide-by-slide directly in the file navigator, enabling quick review and iteration without leaving the browser. [Commit](https://github.com/open-webui/open-webui/commit/890949abe6b01d201355a86c50317e20da07dd34) - 📁 **Pyodide file system support.** Users can now upload files for Python code execution in the code interpreter. Uploaded files are available in the `/mnt/uploads/` directory, and code can write output files there for download. The file system persists across code executions within the same session. The code interpreter now also informs models that pip install is not available in the Pyodide environment, guiding them to use alternative approaches with available modules. [#3583](https://github.com/open-webui/open-webui/issues/3583), [Commit](https://github.com/open-webui/open-webui/commit/ce0ca894fea8a2904bc6f832ff186d5fe53dd0b9), [Commit](https://github.com/open-webui/open-webui/commit/989938856fdb4b4afa584ae2d18c88d5be614ae2) - 🧰 **Tool files access.** Tools can now access the files from the current chat context via the files property in their metadata, enabling more powerful tool integrations. [Commit](https://github.com/open-webui/open-webui/commit/35bc8310772c222fd8a466f7d00113a84e0402d0) - ⚡ **Chat performance.** Chat messages now load and display significantly faster thanks to optimized markdown rendering, eliminating delays when viewing messages with mathematical expressions. [#22196](https://github.com/open-webui/open-webui/pull/22196), [#20878](https://github.com/open-webui/open-webui/discussions/20878) -- 📋 **Message list performance.** Improved message list rendering performance by optimizing array operations, reducing complexity from O(n²) to O(n). [#22280](https://github.com/open-webui/open-webui/pull/22280) +- 📜 **Message list performance.** Improved message list rendering performance by optimizing array operations, reducing complexity from O(n²) to O(n). [#22280](https://github.com/open-webui/open-webui/pull/22280) - 🧵 **Streaming markdown performance.** Improved chat responsiveness during streaming by skipping unnecessary markdown re-parsing when the content hasn't changed, eliminating wasted processing during model pauses. [#22183](https://github.com/open-webui/open-webui/pull/22183) - 🏃 **Chat streaming performance.** Chat streaming is now faster for users not using the voice call feature by skipping unnecessary text parsing that was running on every token. [#22195](https://github.com/open-webui/open-webui/pull/22195) -- 📑 **Source list performance.** Source lists in chat now render faster thanks to optimized computation that avoids unnecessary recalculations, including moving sourceIds computation to a reactive variable. [#22279](https://github.com/open-webui/open-webui/pull/22279), [Commit](https://github.com/open-webui/open-webui/commit/88af78c), [Commit](https://github.com/open-webui/open-webui/commit/339ed1d72e100c89d8eb26de761dfefe842ef90c) +- 🔖 **Source list performance.** Source lists in chat now render faster thanks to optimized computation that avoids unnecessary recalculations, including moving sourceIds computation to a reactive variable. [#22279](https://github.com/open-webui/open-webui/pull/22279), [Commit](https://github.com/open-webui/open-webui/commit/88af78c), [Commit](https://github.com/open-webui/open-webui/commit/339ed1d72e100c89d8eb26de761dfefe842ef90c) - 💨 **Chat message tree operations.** Chat message tree operations are now significantly faster, improving overall chat responsiveness. [#22194](https://github.com/open-webui/open-webui/pull/22194) - 🚀 **Initial page load speed.** Page load is now significantly faster thanks to deferred loading of the syntax highlighting library, reducing the initial JavaScript bundle by several megabytes. [#22304](https://github.com/open-webui/open-webui/pull/22304) -- 🗂️ **Action priority query optimization.** Improved performance of action priority resolution by fixing an N+1 query pattern, reducing database round-trips when loading model actions. [#22301](https://github.com/open-webui/open-webui/pull/22301) +- 🗓️ **Action priority query optimization.** Improved performance of action priority resolution by fixing an N+1 query pattern, reducing database round-trips when loading model actions. [#22301](https://github.com/open-webui/open-webui/pull/22301) - 🔑 **API key middleware optimization.** The API key restriction middleware was converted to a pure ASGI middleware for improved streaming performance, removing per-chunk call overhead. [#22188](https://github.com/open-webui/open-webui/pull/22188) - 🏎️ **Model list loading performance.** Model lists now load significantly faster thanks to optimized custom model matching that uses dictionary lookups instead of nested loops. [#22299](https://github.com/open-webui/open-webui/pull/22299), [Commit](https://github.com/open-webui/open-webui/commit/29160741a3defa8768a43100cb6e63c56400279c), [Commit](https://github.com/open-webui/open-webui/commit/03c6caac1fc8625f85cf1164f5a977be8005c1bc) - ⏱️ **Event call timeout configuration.** Administrators can now configure the WebSocket event call timeout via the WEBSOCKET_EVENT_CALLER_TIMEOUT environment variable, giving users more time to respond to event_call forms instead of timing out after 60 seconds. [#22222](https://github.com/open-webui/open-webui/pull/22222), [#22220](https://github.com/open-webui/open-webui/issues/22220) -- 📑 **Office file previews.** Users can now preview DOCX, XLSX, and PPTX files directly in the chat file navigator, making it easier to view documents without downloading them first. [Commit](https://github.com/open-webui/open-webui/commit/890949abe6b01d201355a86c50317e20da07dd34) -- 🔄 **File refresh button visibility.** The refresh button in the chat file navigator now appears when viewing files as well as directories, allowing users to refresh the file view at any time. [Commit](https://github.com/open-webui/open-webui/commit/49a2e5bf573415dae6d4c7e5bd635e499c8de77a) +- 🔁 **File refresh button visibility.** The refresh button in the chat file navigator now appears when viewing files as well as directories, allowing users to refresh the file view at any time. [Commit](https://github.com/open-webui/open-webui/commit/49a2e5bf573415dae6d4c7e5bd635e499c8de77a) - 📂 **Nested folders support.** Users can now create subfolders within parent folders, improving organization of chats. A new "Create Subfolder" option is available in the folder context menu. [#22073](https://github.com/open-webui/open-webui/pull/22073), [Commit](https://github.com/open-webui/open-webui/commit/8913f37c3d8fde7dea6d54a550357f1d495b3941) -- 📢 **Banner loading on navigation.** Admin-configured banners now load when navigating to the homepage, not just on page refresh, ensuring users see new banners immediately. [#22340](https://github.com/open-webui/open-webui/pull/22340), [#22180](https://github.com/open-webui/open-webui/issues/22180) +- 🔔 **Banner loading on navigation.** Admin-configured banners now load when navigating to the homepage, not just on page refresh, ensuring users see new banners immediately. [#22340](https://github.com/open-webui/open-webui/pull/22340), [#22180](https://github.com/open-webui/open-webui/issues/22180) - 📡 **System metrics via OpenTelemetry.** Administrators can now monitor Python runtime and system metrics including CPU, memory, garbage collection, and thread counts through the existing OpenTelemetry pipeline. [#22265](https://github.com/open-webui/open-webui/pull/22265) - 🔄 **General improvements.** Various improvements were implemented across the application to enhance performance, stability, and security. - 🌐 Translations for French, Finnish, Turkish, German, Simplified Chinese, and Traditional Chinese were enhanced and expanded. @@ -60,8 +62,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 💡 **Follow-up suggestions.** Fixed follow-up suggestions not appearing by correcting contradictory format instructions in the prompt template, ensuring the LLM returns the correct JSON object format. [#22212](https://github.com/open-webui/open-webui/pull/22212) - 🔊 **TTS thinking content.** Fixed TTS playback reading think tags instead of skipping them by handling edge cases where code blocks inside thinking content prevented proper tag removal. [#22237](https://github.com/open-webui/open-webui/pull/22237), [#22197](https://github.com/open-webui/open-webui/issues/22197) - 🎨 **Button spinner alignment.** Button spinners across multiple modals now align correctly and stay on the same line as the button text, fixing layout issues when loading states are displayed. [#22227](https://github.com/open-webui/open-webui/pull/22227) -- 🔌 **Terminal keepalive.** Terminal connections now stay active without being closed by idle timeouts from proxies or load balancers, and spurious disconnection messages no longer appear. [Commit](https://github.com/open-webui/open-webui/commit/ca2aaf0321c219d041e92e2c0c842a4e424732ef) -- 🗃️ **Chat archive handler.** The archive button in the chat navbar now actually archives the chat and refreshes the chat list, instead of doing nothing. [#22229](https://github.com/open-webui/open-webui/pull/22229) +- 📶 **Terminal keepalive.** Terminal connections now stay active without being closed by idle timeouts from proxies or load balancers, and spurious disconnection messages no longer appear. [Commit](https://github.com/open-webui/open-webui/commit/ca2aaf0321c219d041e92e2c0c842a4e424732ef) +- 📥 **Chat archive handler.** The archive button in the chat navbar now actually archives the chat and refreshes the chat list, instead of doing nothing. [#22229](https://github.com/open-webui/open-webui/pull/22229) - 🐍 **BeautifulSoup4 dependency.** Added the missing BeautifulSoup4 package to backend requirements, fixing failures when using features that depend on HTML parsing. [#22231](https://github.com/open-webui/open-webui/pull/22231) - 👥 **Group users default sort.** Group members in the admin panel now sort by last active time by default instead of creation date, making it easier to find active users. [#22211](https://github.com/open-webui/open-webui/pull/22211) - 🔓 **Tool access permissions.** Users can now change tool and skill access permissions from private to public without errors. [#22325](https://github.com/open-webui/open-webui/pull/22325), [#22324](https://github.com/open-webui/open-webui/issues/22324) @@ -75,11 +77,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - 🪟 **Open Terminal Windows path fix.** Fixed a bug where navigating back to parent directories on Windows added an incorrect leading slash, causing directory loads to fail. Paths are now properly normalized for Windows drive letters. [#22352](https://github.com/open-webui/open-webui/issues/22352), [Commit](https://github.com/open-webui/open-webui/commit/044fd1bd15cae06a5c56a321ca79d8362942f66a) - 🖼️ **Chat overview profile image sizing.** Fixed a bug where profile images in the chat overview could shrink incorrectly in tight spaces. The images now maintain their proper size with the flex-shrink-0 property. [#22261](https://github.com/open-webui/open-webui/pull/22261) - 📨 **Queued messages display.** Fixed an issue where queued messages could be cut off or hidden. The queued messages area now scrolls properly when content exceeds the visible area, showing up to 25% of the viewport height. [#22176](https://github.com/open-webui/open-webui/pull/22176) -- 🎨 **Image generation in temporary chats.** Generated images now display correctly in temporary chat mode when using builtin image generation tools. Previously, images were not shown because the code was overwriting the image list with a null database response. [#22330](https://github.com/open-webui/open-webui/pull/22330), [#22309](https://github.com/open-webui/open-webui/issues/22309) +- 🖌️ **Image generation in temporary chats.** Generated images now display correctly in temporary chat mode when using builtin image generation tools. Previously, images were not shown because the code was overwriting the image list with a null database response. [#22330](https://github.com/open-webui/open-webui/pull/22330), [#22309](https://github.com/open-webui/open-webui/issues/22309) - 🤖 **Ollama model unload fix.** Fixed a bug where unloading a model from Ollama via the Open WebUI proxy failed with a "Field required" error for the prompt field. The proxy now correctly allows omitting the prompt when using keep_alive: 0 to unload models. [#22260](https://github.com/open-webui/open-webui/issues/22260), [Commit](https://github.com/open-webui/open-webui/commit/95b65ff751f91131b633cb128ff2decdd87c4a85) -- 📢 **Banner type dropdown fix.** Fixed a bug where selecting a banner type required two clicks to register, as the first selection was being swallowed due to DOM structure changes. The dropdown now works correctly on the first click. [#22378](https://github.com/open-webui/open-webui/pull/22378) +- 🏷️ **Banner type dropdown fix.** Fixed a bug where selecting a banner type required two clicks to register, as the first selection was being swallowed due to DOM structure changes. The dropdown now works correctly on the first click. [#22378](https://github.com/open-webui/open-webui/pull/22378) - 📈 **Analytics URL encoding fix.** Fixed a bug where the Analytics page failed to load data for models with slashes in their ID, such as "anthropic/claude-opus-4.6". The frontend now properly URL-encodes forward slashes, allowing model analytics to load correctly. [#22380](https://github.com/open-webui/open-webui/issues/22380), [#22382](https://github.com/open-webui/open-webui/pull/22382) -- 📊 **Analytics chat list duplicate fix.** Fixed a bug where the Analytics page chat list threw an "each_key_duplicate" Svelte error when chat IDs were duplicated during pagination. The fix adds deterministic ordering to prevent duplicate entries. [#22383](https://github.com/open-webui/open-webui/pull/22383) +- 📋 **Analytics chat list duplicate fix.** Fixed a bug where the Analytics page chat list threw an "each_key_duplicate" Svelte error when chat IDs were duplicated during pagination. The fix adds deterministic ordering to prevent duplicate entries. [#22383](https://github.com/open-webui/open-webui/pull/22383) - 📂 **Folder knowledge base native tool call fix.** Fixed a bug where folders with attached knowledge bases were querying the knowledge base twice when using native tool call mode. The fix now correctly separates knowledge files from regular attachments, letting the builtin query_knowledge_files tool handle knowledge searches instead of duplicating RAG queries. [#22236](https://github.com/open-webui/open-webui/issues/22236), [Commit](https://github.com/open-webui/open-webui/commit/967b1137dcb7a52615f17d086ee89095bb9b60f3), [Commit](https://github.com/open-webui/open-webui/commit/80b5896b70d07ea868e2010b187430d43c9808f0) ## [0.8.8] - 2026-03-02 From 9bb226dc52b13a38922328a3dd58a22137c2cd47 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:21:33 -0600 Subject: [PATCH 106/114] refac --- .github/pull_request_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index e19c790a5b..d50d38d848 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -92,7 +92,7 @@ Deleting it will trigger the CLA-Bot to INVALIDATE your PR. Your PR will NOT be reviewed or merged until you check the box below confirming that you have read and agree to the terms of the CLA. --> -- [ ] By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](./CLA.md), and I am providing my contributions under its terms. +- [ ] By submitting this pull request, I confirm that I have read and fully agree to the [Contributor License Agreement (CLA)](https://github.com/open-webui/open-webui/blob/main/CONTRIBUTOR_LICENSE_AGREEMENT), and I am providing my contributions under its terms. > [!NOTE] > Deleting the CLA section will lead to immediate closure of your PR and it will not be merged in. From b1048fc9bcc55ced07a431fa4a14e8b1f7e4a170 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:22:01 -0600 Subject: [PATCH 107/114] refac --- backend/open_webui/models/chats.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/backend/open_webui/models/chats.py b/backend/open_webui/models/chats.py index 9b8261b8d4..78aa4d3ded 100644 --- a/backend/open_webui/models/chats.py +++ b/backend/open_webui/models/chats.py @@ -1039,9 +1039,13 @@ def get_chats_by_user_id( if order_by and direction: if hasattr(Chat, order_by): if direction.lower() == "asc": - query = query.order_by(getattr(Chat, order_by).asc(), Chat.id) + query = query.order_by( + getattr(Chat, order_by).asc(), Chat.id + ) elif direction.lower() == "desc": - query = query.order_by(getattr(Chat, order_by).desc(), Chat.id) + query = query.order_by( + getattr(Chat, order_by).desc(), Chat.id + ) else: query = query.order_by(Chat.updated_at.desc(), Chat.id) From 368912ca6261788123c5bc847ff8973a38db48c3 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:28:17 -0600 Subject: [PATCH 108/114] refac --- backend/open_webui/utils/middleware.py | 29 +++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 40b8dc78a3..db9321f5e1 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -4493,14 +4493,29 @@ async def flush_pending_delta_data(threshold: int = 0): form_data["messages"], ) - # Combine file and tool sources into one RAG - # template application. - form_data["messages"] = apply_source_context_to_messages( - request, - form_data["messages"], - metadata.get("sources", []) + all_tool_call_sources, - user_message, + # Build context: file sources with content, + # tool sources as citation markers only. + ctx = get_source_context(metadata.get("sources", [])) + ctx += get_source_context( + all_tool_call_sources, include_content=False ) + ctx = ctx.strip() + if ctx: + rag = rag_template( + request.app.state.config.RAG_TEMPLATE, + ctx, + user_message, + ) + if RAG_SYSTEM_CONTEXT: + form_data["messages"] = ( + add_or_update_system_message( + rag, form_data["messages"], append=True + ) + ) + else: + form_data["messages"] = add_or_update_user_message( + rag, form_data["messages"], append=False + ) tool_call_sources.clear() await event_emitter( From f047b6b3aec1b6872c94873d5581c0d0d742e4e6 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:30:42 -0600 Subject: [PATCH 109/114] refac --- backend/open_webui/utils/middleware.py | 35 +++++++++++++------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index db9321f5e1..2afd5f87bf 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -929,25 +929,21 @@ def apply_source_context_to_messages( if not sources or not user_message: return messages - context_string = get_source_context(sources, include_content) + context = get_source_context(sources, include_content) - context_string = context_string.strip() - if not context_string: + context = context.strip() + if not context: return messages if RAG_SYSTEM_CONTEXT: return add_or_update_system_message( - rag_template( - request.app.state.config.RAG_TEMPLATE, context_string, user_message - ), + rag_template(request.app.state.config.RAG_TEMPLATE, context, user_message), messages, append=True, ) else: return add_or_update_user_message( - rag_template( - request.app.state.config.RAG_TEMPLATE, context_string, user_message - ), + rag_template(request.app.state.config.RAG_TEMPLATE, context, user_message), messages, append=False, ) @@ -4495,26 +4491,31 @@ async def flush_pending_delta_data(threshold: int = 0): # Build context: file sources with content, # tool sources as citation markers only. - ctx = get_source_context(metadata.get("sources", [])) - ctx += get_source_context( + source_context = get_source_context( + metadata.get("sources", []) + ) + get_source_context( all_tool_call_sources, include_content=False ) - ctx = ctx.strip() - if ctx: - rag = rag_template( + source_context = source_context.strip() + if source_context: + rag_content = rag_template( request.app.state.config.RAG_TEMPLATE, - ctx, + source_context, user_message, ) if RAG_SYSTEM_CONTEXT: form_data["messages"] = ( add_or_update_system_message( - rag, form_data["messages"], append=True + rag_content, + form_data["messages"], + append=True, ) ) else: form_data["messages"] = add_or_update_user_message( - rag, form_data["messages"], append=False + rag_content, + form_data["messages"], + append=False, ) tool_call_sources.clear() From e24299e66d838126faad739474b2a49a714f7755 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:36:54 -0600 Subject: [PATCH 110/114] refac --- .github/workflows/deploy-to-hf-spaces.yml | 64 ----------------------- 1 file changed, 64 deletions(-) delete mode 100644 .github/workflows/deploy-to-hf-spaces.yml diff --git a/.github/workflows/deploy-to-hf-spaces.yml b/.github/workflows/deploy-to-hf-spaces.yml deleted file mode 100644 index cda9f1eb4b..0000000000 --- a/.github/workflows/deploy-to-hf-spaces.yml +++ /dev/null @@ -1,64 +0,0 @@ -name: Deploy to HuggingFace Spaces - -on: - push: - branches: - - dev - - main - workflow_dispatch: - -jobs: - check-secret: - runs-on: ubuntu-latest - outputs: - token-set: ${{ steps.check-key.outputs.defined }} - steps: - - id: check-key - env: - HF_TOKEN: ${{ secrets.HF_TOKEN }} - if: "${{ env.HF_TOKEN != '' }}" - run: echo "defined=true" >> $GITHUB_OUTPUT - - deploy: - runs-on: ubuntu-latest - needs: [check-secret] - if: needs.check-secret.outputs.token-set == 'true' - env: - HF_TOKEN: ${{ secrets.HF_TOKEN }} - steps: - - name: Checkout repository - uses: actions/checkout@v5 - with: - lfs: true - - - name: Remove git history - run: rm -rf .git - - - name: Prepend YAML front matter to README.md - run: | - echo "---" > temp_readme.md - echo "title: Open WebUI" >> temp_readme.md - echo "emoji: 🐳" >> temp_readme.md - echo "colorFrom: purple" >> temp_readme.md - echo "colorTo: gray" >> temp_readme.md - echo "sdk: docker" >> temp_readme.md - echo "app_port: 8080" >> temp_readme.md - echo "---" >> temp_readme.md - cat README.md >> temp_readme.md - mv temp_readme.md README.md - - - name: Configure git - run: | - git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" - git config --global user.name "github-actions[bot]" - - name: Set up Git and push to Space - run: | - git init --initial-branch=main - git lfs install - git lfs track "*.ttf" - git lfs track "*.jpg" - rm demo.png - rm banner.png - git add . - git commit -m "GitHub deploy: ${{ github.sha }}" - git push --force https://open-webui:${HF_TOKEN}@huggingface.co/spaces/open-webui/open-webui main From 2bff50f736afd2fe41d4f0efbea4a4a7bfab835d Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:42:21 -0600 Subject: [PATCH 111/114] refac --- backend/open_webui/utils/middleware.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 2afd5f87bf..1bc581233c 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -890,21 +890,24 @@ def handle_responses_streaming_event( return current_output, None -def get_source_context(sources: list, include_content: bool = True) -> str: +def get_source_context( + sources: list, source_id_map: dict = None, include_content: bool = True +) -> str: """ Build tag context string from citation sources. """ context_string = "" - citation_idx = {} + if source_id_map is None: + source_id_map = {} for source in sources: for doc, meta in zip(source.get("document", []), source.get("metadata", [])): src_id = meta.get("source") or source.get("source", {}).get("id") or "N/A" - if src_id not in citation_idx: - citation_idx[src_id] = len(citation_idx) + 1 + if src_id not in source_id_map: + source_id_map[src_id] = len(source_id_map) + 1 src_name = source.get("source", {}).get("name") body = doc if include_content else "" context_string += ( - f'{body}\n" ) @@ -929,7 +932,7 @@ def apply_source_context_to_messages( if not sources or not user_message: return messages - context = get_source_context(sources, include_content) + context = get_source_context(sources, include_content=include_content) context = context.strip() if not context: @@ -4491,10 +4494,13 @@ async def flush_pending_delta_data(threshold: int = 0): # Build context: file sources with content, # tool sources as citation markers only. + source_id_map = {} source_context = get_source_context( - metadata.get("sources", []) + metadata.get("sources", []), source_id_map ) + get_source_context( - all_tool_call_sources, include_content=False + all_tool_call_sources, + source_id_map, + include_content=False, ) source_context = source_context.strip() if source_context: From 710b5270a111cfbef8af27ac2b7231a6365af983 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:43:45 -0600 Subject: [PATCH 112/114] refac --- backend/open_webui/utils/middleware.py | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 1bc581233c..8bfed7d391 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -891,23 +891,25 @@ def handle_responses_streaming_event( def get_source_context( - sources: list, source_id_map: dict = None, include_content: bool = True + sources: list, source_ids: dict = None, include_content: bool = True ) -> str: """ Build tag context string from citation sources. """ context_string = "" - if source_id_map is None: - source_id_map = {} + if source_ids is None: + source_ids = {} for source in sources: for doc, meta in zip(source.get("document", []), source.get("metadata", [])): - src_id = meta.get("source") or source.get("source", {}).get("id") or "N/A" - if src_id not in source_id_map: - source_id_map[src_id] = len(source_id_map) + 1 + source_id = ( + meta.get("source") or source.get("source", {}).get("id") or "N/A" + ) + if source_id not in source_ids: + source_ids[source_id] = len(source_ids) + 1 src_name = source.get("source", {}).get("name") body = doc if include_content else "" context_string += ( - f'{body}\n" ) @@ -4494,12 +4496,12 @@ async def flush_pending_delta_data(threshold: int = 0): # Build context: file sources with content, # tool sources as citation markers only. - source_id_map = {} + source_ids = {} source_context = get_source_context( - metadata.get("sources", []), source_id_map + metadata.get("sources", []), source_ids ) + get_source_context( all_tool_call_sources, - source_id_map, + source_ids, include_content=False, ) source_context = source_context.strip() From 124ad948fe1d8120a21f449cf46c5fa2900a3a6f Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sat, 7 Mar 2026 20:56:05 -0600 Subject: [PATCH 113/114] refac --- .github/workflows/build-release.yml | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 019fbb6bae..2ecb013e0b 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -27,28 +27,17 @@ jobs: echo "::set-output name=version::$VERSION" - name: Extract latest CHANGELOG entry - id: changelog run: | - CHANGELOG_CONTENT=$(awk 'BEGIN {print_section=0;} /^## \[/ {if (print_section == 0) {print_section=1;} else {exit;}} print_section {print;}' CHANGELOG.md) - CHANGELOG_ESCAPED=$(echo "$CHANGELOG_CONTENT" | sed ':a;N;$!ba;s/\n/%0A/g') - echo "Extracted latest release notes from CHANGELOG.md:" - echo -e "$CHANGELOG_CONTENT" - echo "::set-output name=content::$CHANGELOG_ESCAPED" + VERSION="${{ steps.get_version.outputs.version }}" + awk "/^## \[${VERSION}\]/{found=1; next} /^## \[/{if(found) exit} found{print}" CHANGELOG.md > /tmp/release-notes.md - name: Create GitHub release - uses: actions/github-script@v8 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const changelog = `${{ steps.changelog.outputs.content }}`; - const release = await github.rest.repos.createRelease({ - owner: context.repo.owner, - repo: context.repo.repo, - tag_name: `v${{ steps.get_version.outputs.version }}`, - name: `v${{ steps.get_version.outputs.version }}`, - body: changelog, - }) - console.log(`Created release ${release.data.html_url}`) + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + gh release create "v${{ steps.get_version.outputs.version }}" \ + --title "v${{ steps.get_version.outputs.version }}" \ + --notes-file /tmp/release-notes.md - name: Upload package to GitHub release uses: actions/upload-artifact@v4 From 0c30518e41adba73f29bd80b529616d8a77cb239 Mon Sep 17 00:00:00 2001 From: orenzhang <41963680+OrenZhang@users.noreply.github.com> Date: Sun, 8 Mar 2026 14:57:34 +0800 Subject: [PATCH 114/114] chore(repo): merge from remote --- CHANGELOG_EXTRA.md | 6 + .../open_webui/static/apple-touch-icon.png | Bin 1658 -> 0 bytes backend/open_webui/static/custom.css | 0 backend/open_webui/static/favicon-96x96.png | Bin 3826 -> 0 bytes backend/open_webui/static/favicon-dark.png | Bin 15919 -> 0 bytes backend/open_webui/static/favicon.ico | Bin 15086 -> 0 bytes backend/open_webui/static/favicon.png | Bin 10655 -> 0 bytes backend/open_webui/static/favicon.svg | 3 - backend/open_webui/static/loader.js | 0 backend/open_webui/static/logo.png | Bin 5367 -> 0 bytes backend/open_webui/static/site.webmanifest | 21 --- backend/open_webui/static/splash-dark.png | Bin 5419 -> 0 bytes backend/open_webui/static/splash.png | Bin 5239 -> 0 bytes backend/open_webui/static/user-import.csv | 1 - backend/open_webui/static/user.png | Bin 7858 -> 0 bytes .../static/web-app-manifest-192x192.png | Bin 8349 -> 0 bytes .../static/web-app-manifest-512x512.png | Bin 30105 -> 0 bytes package-lock.json | 20 +-- src/lib/i18n/locales/en-US/translation.json | 143 ++++++++++++++++++ src/lib/i18n/locales/zh-CN/translation.json | 2 +- 20 files changed, 160 insertions(+), 36 deletions(-) delete mode 100644 backend/open_webui/static/apple-touch-icon.png delete mode 100644 backend/open_webui/static/custom.css delete mode 100644 backend/open_webui/static/favicon-96x96.png delete mode 100644 backend/open_webui/static/favicon-dark.png delete mode 100644 backend/open_webui/static/favicon.ico delete mode 100644 backend/open_webui/static/favicon.png delete mode 100644 backend/open_webui/static/favicon.svg delete mode 100644 backend/open_webui/static/loader.js delete mode 100644 backend/open_webui/static/logo.png delete mode 100644 backend/open_webui/static/site.webmanifest delete mode 100644 backend/open_webui/static/splash-dark.png delete mode 100644 backend/open_webui/static/splash.png delete mode 100644 backend/open_webui/static/user-import.csv delete mode 100644 backend/open_webui/static/user.png delete mode 100644 backend/open_webui/static/web-app-manifest-192x192.png delete mode 100644 backend/open_webui/static/web-app-manifest-512x512.png diff --git a/CHANGELOG_EXTRA.md b/CHANGELOG_EXTRA.md index 6d7bcb7cab..be0201145f 100644 --- a/CHANGELOG_EXTRA.md +++ b/CHANGELOG_EXTRA.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.8.9.1] - 2026.03.08 + +### Changed + +- 合并官方 0.8.9 改动 + ## [0.8.8.1] - 2026.03.03 ### Changed diff --git a/backend/open_webui/static/apple-touch-icon.png b/backend/open_webui/static/apple-touch-icon.png deleted file mode 100644 index 9807373436540a5b80ae43960cd3cb86f31eec4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1658 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 diff --git a/backend/open_webui/static/favicon-dark.png b/backend/open_webui/static/favicon-dark.png deleted file mode 100644 index 08627a23f7934510cfcc442d1a6ee943e748af7e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15919 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 diff --git a/backend/open_webui/static/favicon.ico b/backend/open_webui/static/favicon.ico deleted file mode 100644 index 14c5f9c6d437ed109a8579031cf181ee52bdf30e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 15086 zcmdU#S!h(*7KTrZG2)mu&SMnCE4H+@a(!vJR}o)CRD4h{Vyig3L=?n_esG@K2~;E< z<4EM9_@Fr4t0)m?X(z;aNEB4Wc^>1s>)X~oT_<&_QdK!xU5otLr_R}HuYa#S4~~=J zWIEluI~wLW|LNp7|8yKDFE8{v$8m1!yBrPqKB=bTEYJx5&^W5%{Hoynw-6D@R5Vny zQ4CZpR~%H_RJ>GFgupZJ__jq)1fIL62RR_Pr{j(y~0tdLn zRSp`D`cAo}((h{CBXEIJmF+>}&~8#u-_>kPfm5$obxFU|N7DBHt^&8HeXD+>@BJQq zWU~H&+i!klpzj%1zvbAJEa%F4aP*AR`a46x_?<3NqD0;Kl0GwkDpMpRZ{NO^YuB#H z@#Dv3TNkY15_|%$_}4?%ur{4~H_1 z^b_?+L*~HD0TY^wUAlBhCQh6vZQ8VvtgI{{DT^94YDi8_jtm<%Otx;_DxW|54(&BK%Q;$DuUyIi?sJu@>?YS*qUwQAM!%@bu+xg4s=AI@+esEA7r zA3iLtTD9`&a0QKLp?d_XAx{&25| zNg(tQyWw^D_3PL1sF^aFIdi6~OB>j+V~5cVfIr;Roqt^QhyF0!|7B%maryt%t5-5) z$PibTay)qOU{L;tdtB{zK#pwU; z+_~fFKijr#E9cIgi>{zwDk>_ZYuBzWck+!NtOQX1;m#OPr7(W=@891ue)aC%+th`R zA3u8Z;eGY$RT(^Zu!lQyi(|+BTHXb~pRqTt`2&4D^|nQe79LJbnlv#!U9ez*Y~Q|J zii(P4{P^+GxpQYvUhzHi>u?ExKiu0W9)+hH?V0)8vSrJB=WjJ@)->Z3{bP7Lx6h+S zjS}?3rJDTV40qj>6Dtmjyh+I_JKeFpR+cCF2N)vlXZdsOTGjC^q% zc9-P6WtBb z{QNt~EXaiME9JNHE+-7jPv!htKUlxm(E82wqxGxxvqr@4+|$Za{96&kJuR&d%@z5I zBE_GI$BNGi7Qa06j&H>{+@SyBhE7gIzJ~%LUn&o{I1}D ziG2Fm)Yra3Ty)SSjUN)>q4DX1E-B~(6S1q&J%TQ2kd`@Dtcr)m>!Y}@fPYXzTBO-0 zmVNzBzKKUU1}&sX+P;3!_mnq&3NqiCoJU9-8xi$E-%(G37&kSUn1YSp!^=T`)5fT) z)v0T$9+zMPTW;IbXWD8^zdw8SOm5t`Av<^Olx^F#$;FEo(D{5i*@9Jo`FfPHLY+qdjF1Lh1K`=zC&5qAVE;memVo4t4LdQ6xw zAyNCZ1K)O6**<3ve!@N{d(MeQ)G{l8|-8smTJ;Fc|063suh z|5QZOKkfi^@7~?yi+Zqc-#&A$Ykff5#7AAabTMT_$XR{@)b_{yBW%}>_kWoIQJ19zA*#(Jm7mf3$rw2BmcT4RJ`>{3B#PrSq>4hm_4f zv5#n7=%Yx<{QD~d!vQ~}Wc?Awf%=e=^_S&9s2uG2lm3D}i+GE(MsS z+Xui&P^?~QD4lXmleDpcEo@?&eTp1Ko+6Qb3eDp$ibBOT1#23>bD`oFP0m;JTdv{{ z#Y+YLqs*+>^5YwEa>Enhx8i?__X@u{ps$VajX1=0)6i$qQ4PndZG_a7KX&zw19?r4x^NYKHj z*A&KAoMUtEi8;sl^XJW3e7A1h%>6O=a2JI6b4buZ_k(@GJrM3b*}DhKGscY@C;j^M zGx@2cj~coj{h>pLy86t;NV9L>zOnS-;Niby$r5v)yQHK<;Lkmk82k%W-}ukY`|%(5 zjoRy7%*Bfrn>APr|3#D^KBla=3u))q(aJAW2a>KoA^mFA->@{2YCq^(QD53RNx4wA bfagL*MEiZNd%>mb_i9fBsuCLy9d!Q>dBe1} diff --git a/backend/open_webui/static/favicon.png b/backend/open_webui/static/favicon.png deleted file mode 100644 index 63735ad4616fa452325af0fe351139dca01ca0ab..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10655 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 \ No newline at end of file diff --git a/backend/open_webui/static/loader.js b/backend/open_webui/static/loader.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/backend/open_webui/static/logo.png b/backend/open_webui/static/logo.png deleted file mode 100644 index a652a5fb87acf0f253a727d0ed9d672b9837a780..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5367 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 diff --git a/backend/open_webui/static/splash.png b/backend/open_webui/static/splash.png deleted file mode 100644 index 389196ca6a364b9e4b7daa0fc13be463b914b251..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5239 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 GEB_DGHk4cd diff --git a/backend/open_webui/static/user-import.csv b/backend/open_webui/static/user-import.csv deleted file mode 100644 index 918a92aad7..0000000000 --- a/backend/open_webui/static/user-import.csv +++ /dev/null @@ -1 +0,0 @@ -Name,Email,Password,Role diff --git a/backend/open_webui/static/user.png b/backend/open_webui/static/user.png deleted file mode 100644 index 7bdc70d159cfb0a032bec208e3775ab82755b299..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7858 zcmY*-2{e@N`~Dc)*oTs}j5kZ!36U_vU_{84E&G~%mwk(&Fr(~bn?ypE>`O5iAsIr} zlI0_z8TapoaemfzV7FKp6h+jd*0{1t|S9JEhc(ydJqW2q>Vxvf%?X_^Bh(PxmZ_GVZ|8-~b#*eM@ zbKLeOf2JumUu~VFF^f*}CKS>(hpdwBG}z<+mgyn-l;u$9~7c{PI#{V$#W z&bjr!_*g>!KS6r~jCllHH98)0K^=Kf!T%qIcD7UE4Kx7YC}fbUiyPq7wB@l>vsZ)L ztH~$O89Q#>e4h+BUG8~N#?b@A%MUrO zu&^*Q>qnlwn_S;L8W{a_w$e9kDDG^0&s{(sIn-ySg9drGQaGY*SAw(=4v-|)mtdoc zjm^yht9exwS)05hG8(kUMa1Hve z#+kvt9|n`1ni~$oBkDS=M6Uy|TK>if?lO?fjt#v9Wx5?W#n*G|U{amD`bBuL;1a1~ zA6R@O0-T-ZRV5CNEkBjHUP~&L=tM+a{gU zJ0E$>=X=zAdC2$}0#i@4LrRQDK2pYc-=0?z1}eO>5}6s?IG78Q(F*&=VFMG>?ShTV zAQ@X@^P6>y_hKI1Y4$uyJuu)tJ8E^uHPJq!!KUz6wLC{6ivl@0_pD^!@qdMXt11j0 zR=pi*09{RAtt{Qupm~ioXgdCMm={A3N3UdGcj8#jO6l@C`6!4);ui`%zo^r3mUhu7 zQY;;V#<6cVA9Y5w&!OPR*}=nH4XRW5W;$4hChlYPcp*M4OUMf;h#O{UV2 z=;F`6<$jL<>5W>mZi`xmP7%CWV#8TniJUDiG%^)WZ^qrDU=xw3ujW-Ah#qAs-);?4 zlvVu*6LEShm&*VvJh7Kg5XFUTob;yfAeWXso__QRJN-C+rCPn-@l3~|H(meiB%R;hFF5`7L=#UmK19Ut`ZIa4t;M^2wKi1XbhSSq%dIreJ0D{aFjWNvth+`i9Rs7oc_3siS< z-qid7vNv~cYZV64b&DQ&vwRnfP^{)>>mG{Z6q2fR8S!3gc~MbkmHv5f0Bi^12k@Wg z>zf5gWcko9mj&+6o7Pwdak_?vnfG*OczlEXveG!cF_{Bk~j!{>kIJ6@1t z0y-PQz6k=W47tzwzkW~C5@Lx33CWvTbZj`ZOMy^np4x4sR(KVb&KXKY@m;3;btsUI zbD&%sNK{5$V4Rrtb{^n6gcf3V7UamG2yf8M<#Q_dBA9_h2mCtw*xP%lNPh@5`+6P?GrPD z@gk{OKJb5*6`|i0%=3`(j_n_+OEyjS(j@vD7ASV`@Q;2;L9ZM^P%b$_zsUV1=U%q# z9LfqGZE>4j)!=WQR?@tL{`IOC>%S_Gh@1p!x#611N zcc|S1y8Tix>AZ}#!}{IFKOgw976-d+{$pB_l{3xu=*weWe3sBH?nLP!UPAtyHyXEQ z3p)>Tpru~>BY@UNZf3gFd`?~&(I93rf)}+Ih@(2L$+(&23d%!?;_CH4&DUs9YC%Kz zR)+xBduhHK>20@Y+*hPh>&}XtS=6YwlQL_jZ_OW4k^o|JC4X)ApG&JUv=sK^A4%rN zB>yZ`s4zgBmSJUe?!qZiKzl4^UN^bmh`g~Otk~^CwrM&XwUdogv9!hT)|-t!*+fCS z(rQQ4cN+A~V|>dHB74fUBWU^2G3yMk{BMc-M#3B>o~Zt(w6*wmwoTu@bdy^sN#0IK z>q$Ab%X|VtC6Kgv_r%$l6LZlSqgXzq998uq+fn}Ye_`MJu}d#9x_#rCB`j3}+a&bbIf4yCFt0_i&Mck;PIx#6W<-Nc zvf|*`qJ#lIMw-e}FBi~WpzPM&u2aFwSUznu9)7IeGz5oYr=&J@xd`-J_Zy8RgdjXB z0qG4aV!6ziK-iK(G6O^n>GA89a0U8>8^!lAIImWj4-Br0^4;z0*uC+FYKb>yKtuwD z<}V_5*B^(nOtr_{wX~IOjfQz}zONhi+ZxCnqX0~7hYjvRhco3&Gv^v *S`Cr$hj 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 diff --git a/backend/open_webui/static/web-app-manifest-192x192.png b/backend/open_webui/static/web-app-manifest-192x192.png deleted file mode 100644 index fbd2eab6e2b8bcd7c510fca905f432c93a4f2ebc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8349 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 and all its contents.": "", @@ -1907,6 +2034,7 @@ "Tiktoken": "", "Time & Calculation": "", "Timeout": "", + "Timestamp cannot be empty": "", "Title": "", "Title Auto-Generation": "", "Title cannot be an empty string.": "", @@ -1952,6 +2080,12 @@ "Top": "", "Top K": "", "Top K Reranker": "", + "Topic": "", + "Topic is required": "", + "Total Credit Cost": "", + "Total Payment": "", + "Total Token Cost": "", + "Trace ticket qrcode pay to input QR_CODE_OFFLINE": "", "Transformers": "", "Trouble accessing Ollama?": "", "Trust Proxy Environment": "", @@ -1970,6 +2104,7 @@ "Unarchive All Archived Chats": "", "Unarchive Chat": "", "Underline": "", + "Unit: 1M tokens or 1M requests": "", "Unknown": "", "Unknown User": "", "Unloads {{FROM_NOW}}": "", @@ -1988,6 +2123,7 @@ "Updated": "", "Updated at": "", "Updated At": "", + "Updating...": "", "Upgrade to a licensed plan for enhanced capabilities, including custom theming and branding, and dedicated support.": "", "Upload": "", "Upload a GGUF model": "", @@ -2015,14 +2151,20 @@ "Use LLM": "", "Use no proxy to fetch page contents.": "", "Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "", + "Used": "", + "Used At": "", + "Used By": "", "user": "", "User": "", "User Activity": "", + "User Credit Cost": "", "User Groups": "", "User location successfully retrieved.": "", "User menu": "", + "User Payment Stats": "", "User ratings (thumbs up/down)": "", "User Status": "", + "User Tokens Cost": "", "User Webhooks": "", "Username": "", "users": "", @@ -2100,6 +2242,7 @@ "Write a summary in 50 words that summarizes {{topic}}.": "", "Write something...": "", "Write your model system prompt content here\ne.g.) You are Mario from Super Mario Bros, acting as an assistant.": "Write your model system prompt content here\n e.g.) You are Mario from Super Mario Bros, acting as an assistant.", + "WXPay": "", "Yacy Instance URL": "", "Yacy Password": "", "Yacy Username": "", diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json index 59a73baf26..901097411c 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -1611,8 +1611,8 @@ "Pull \"{{searchValue}}\" from Ollama.com": "从 Ollama.com 下载 “{{searchValue}}”", "Pull a model from Ollama.com": "从 Ollama.com 下载模型", "Pull Model": "下载模型", - "QRCode": "二维码", "Pyodide file browser": "", + "QRCode": "二维码", "Query Generation Prompt": "查询生成提示词", "Querying": "查询中", "Quick Actions": "快捷操作",