Browse Source

Merge pull request #12809 from open-webui/dev

0.6.5
Tim Jaeryang Baek 2 months ago
parent
commit
07d8460126
72 changed files with 1195 additions and 369 deletions
  1. 15 0
      CHANGELOG.md
  2. 23 0
      backend/open_webui/config.py
  3. 15 8
      backend/open_webui/main.py
  4. 5 1
      backend/open_webui/routers/audio.py
  5. 3 1
      backend/open_webui/routers/auths.py
  6. 14 14
      backend/open_webui/routers/retrieval.py
  7. 3 0
      backend/open_webui/routers/users.py
  8. 11 10
      backend/open_webui/socket/main.py
  9. 14 7
      backend/open_webui/utils/middleware.py
  10. 496 102
      package-lock.json
  11. 4 4
      package.json
  12. 1 2
      src/lib/components/admin/Settings/Audio.svelte
  13. 3 0
      src/lib/components/admin/Users/Groups.svelte
  14. 31 5
      src/lib/components/admin/Users/Groups/Permissions.svelte
  15. 28 26
      src/lib/components/chat/Chat.svelte
  16. 2 2
      src/lib/components/chat/MessageInput.svelte
  17. 99 86
      src/lib/components/chat/Messages/ResponseMessage.svelte
  18. 3 1
      src/lib/components/chat/ModelSelector/Selector.svelte
  19. 29 0
      src/lib/components/chat/Settings/Interface.svelte
  20. 4 0
      src/lib/i18n/locales/ar-BH/translation.json
  21. 4 0
      src/lib/i18n/locales/ar/translation.json
  22. 4 0
      src/lib/i18n/locales/bg-BG/translation.json
  23. 4 0
      src/lib/i18n/locales/bn-BD/translation.json
  24. 4 0
      src/lib/i18n/locales/bo-TB/translation.json
  25. 4 0
      src/lib/i18n/locales/ca-ES/translation.json
  26. 4 0
      src/lib/i18n/locales/ceb-PH/translation.json
  27. 4 0
      src/lib/i18n/locales/cs-CZ/translation.json
  28. 4 0
      src/lib/i18n/locales/da-DK/translation.json
  29. 4 0
      src/lib/i18n/locales/de-DE/translation.json
  30. 4 0
      src/lib/i18n/locales/dg-DG/translation.json
  31. 4 0
      src/lib/i18n/locales/el-GR/translation.json
  32. 4 0
      src/lib/i18n/locales/en-GB/translation.json
  33. 4 0
      src/lib/i18n/locales/en-US/translation.json
  34. 4 0
      src/lib/i18n/locales/es-ES/translation.json
  35. 4 0
      src/lib/i18n/locales/et-EE/translation.json
  36. 4 0
      src/lib/i18n/locales/eu-ES/translation.json
  37. 4 0
      src/lib/i18n/locales/fa-IR/translation.json
  38. 4 0
      src/lib/i18n/locales/fi-FI/translation.json
  39. 4 0
      src/lib/i18n/locales/fr-CA/translation.json
  40. 4 0
      src/lib/i18n/locales/fr-FR/translation.json
  41. 4 0
      src/lib/i18n/locales/he-IL/translation.json
  42. 4 0
      src/lib/i18n/locales/hi-IN/translation.json
  43. 4 0
      src/lib/i18n/locales/hr-HR/translation.json
  44. 4 0
      src/lib/i18n/locales/hu-HU/translation.json
  45. 4 0
      src/lib/i18n/locales/id-ID/translation.json
  46. 4 0
      src/lib/i18n/locales/ie-GA/translation.json
  47. 4 0
      src/lib/i18n/locales/it-IT/translation.json
  48. 4 0
      src/lib/i18n/locales/ja-JP/translation.json
  49. 4 0
      src/lib/i18n/locales/ka-GE/translation.json
  50. 4 0
      src/lib/i18n/locales/ko-KR/translation.json
  51. 4 0
      src/lib/i18n/locales/lt-LT/translation.json
  52. 4 0
      src/lib/i18n/locales/ms-MY/translation.json
  53. 4 0
      src/lib/i18n/locales/nb-NO/translation.json
  54. 4 0
      src/lib/i18n/locales/nl-NL/translation.json
  55. 4 0
      src/lib/i18n/locales/pa-IN/translation.json
  56. 4 0
      src/lib/i18n/locales/pl-PL/translation.json
  57. 4 0
      src/lib/i18n/locales/pt-BR/translation.json
  58. 4 0
      src/lib/i18n/locales/pt-PT/translation.json
  59. 4 0
      src/lib/i18n/locales/ro-RO/translation.json
  60. 55 51
      src/lib/i18n/locales/ru-RU/translation.json
  61. 4 0
      src/lib/i18n/locales/sk-SK/translation.json
  62. 4 0
      src/lib/i18n/locales/sr-RS/translation.json
  63. 4 0
      src/lib/i18n/locales/sv-SE/translation.json
  64. 4 0
      src/lib/i18n/locales/th-TH/translation.json
  65. 4 0
      src/lib/i18n/locales/tk-TW/translation.json
  66. 4 0
      src/lib/i18n/locales/tr-TR/translation.json
  67. 4 0
      src/lib/i18n/locales/uk-UA/translation.json
  68. 4 0
      src/lib/i18n/locales/ur-PK/translation.json
  69. 4 0
      src/lib/i18n/locales/vi-VN/translation.json
  70. 21 17
      src/lib/i18n/locales/zh-CN/translation.json
  71. 4 0
      src/lib/i18n/locales/zh-TW/translation.json
  72. 120 32
      src/lib/utils/index.ts

+ 15 - 0
CHANGELOG.md

@@ -5,6 +5,21 @@ 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.6.5] - 2025-04-14
+
+### Added
+
+- 🛂 **Granular Voice Feature Permissions Per User Group**: Admins can now separately manage access to Speech-to-Text (record voice), Text-to-Speech (read aloud), and Tool Calls for each user group—giving teams tighter control over voice features and enhanced governance across roles.
+- 🗣️ **Toggle Voice Activity Detection (VAD) for Whisper STT**: New environment variable lets you enable/disable VAD filtering with built-in Whisper speech-to-text, giving you flexibility to optimize for different audio quality and response accuracy levels.
+- 📋 **Copy Formatted Response Mode**: You can now enable “Copy Formatted” in Settings > Interface to copy AI responses exactly as styled (with rich formatting, links, and structure preserved), making it faster and cleaner to paste into documents, emails, or reports.
+- ⚙️ **Backend Stability and Performance Enhancements**: General backend refactoring improves system resilience, consistency, and overall reliability—offering smoother performance across workflows whether chatting, generating media, or using external tools.
+- 🌎 **Translation Refinements Across Multiple Languages**: Updated translations deliver smoother language localization, clearer labels, and improved international usability throughout the UI—ensuring a better experience for non-English speakers.
+
+### Fixed
+
+- 🛠️ **LDAP Login Reliability Restored**: Resolved a critical issue where some LDAP setups failed due to attribute parsing—ensuring consistent, secure, and seamless user authentication across enterprise deployments.
+- 🖼️ **Image Generation in Temporary Chats Now Works Properly**: Fixed a bug where image outputs weren’t generated during temporary chats—visual content can now be used reliably in all chat modes without interruptions.
+
 ## [0.6.4] - 2025-04-12
 
 ### Fixed

+ 23 - 0
backend/open_webui/config.py

@@ -1062,6 +1062,18 @@ USER_PERMISSIONS_CHAT_EDIT = (
     os.environ.get("USER_PERMISSIONS_CHAT_EDIT", "True").lower() == "true"
 )
 
+USER_PERMISSIONS_CHAT_STT = (
+    os.environ.get("USER_PERMISSIONS_CHAT_STT", "True").lower() == "true"
+)
+
+USER_PERMISSIONS_CHAT_TTS = (
+    os.environ.get("USER_PERMISSIONS_CHAT_TTS", "True").lower() == "true"
+)
+
+USER_PERMISSIONS_CHAT_CALL = (
+    os.environ.get("USER_PERMISSIONS_CHAT_CALL", "True").lower() == "true"
+)
+
 USER_PERMISSIONS_CHAT_MULTIPLE_MODELS = (
     os.environ.get("USER_PERMISSIONS_CHAT_MULTIPLE_MODELS", "True").lower() == "true"
 )
@@ -1114,6 +1126,9 @@ DEFAULT_USER_PERMISSIONS = {
         "file_upload": USER_PERMISSIONS_CHAT_FILE_UPLOAD,
         "delete": USER_PERMISSIONS_CHAT_DELETE,
         "edit": USER_PERMISSIONS_CHAT_EDIT,
+        "stt": USER_PERMISSIONS_CHAT_STT,
+        "tts": USER_PERMISSIONS_CHAT_TTS,
+        "call": USER_PERMISSIONS_CHAT_CALL,
         "multiple_models": USER_PERMISSIONS_CHAT_MULTIPLE_MODELS,
         "temporary": USER_PERMISSIONS_CHAT_TEMPORARY,
         "temporary_enforced": USER_PERMISSIONS_CHAT_TEMPORARY_ENFORCED,
@@ -2489,6 +2504,13 @@ WHISPER_MODEL_AUTO_UPDATE = (
     and os.environ.get("WHISPER_MODEL_AUTO_UPDATE", "").lower() == "true"
 )
 
+WHISPER_VAD_FILTER = PersistentConfig(
+    "WHISPER_VAD_FILTER",
+    "audio.stt.whisper_vad_filter",
+    os.getenv("WHISPER_VAD_FILTER", "False").lower() == "true",
+)
+
+
 # Add Deepgram configuration
 DEEPGRAM_API_KEY = PersistentConfig(
     "DEEPGRAM_API_KEY",
@@ -2496,6 +2518,7 @@ DEEPGRAM_API_KEY = PersistentConfig(
     os.getenv("DEEPGRAM_API_KEY", ""),
 )
 
+
 AUDIO_STT_OPENAI_API_BASE_URL = PersistentConfig(
     "AUDIO_STT_OPENAI_API_BASE_URL",
     "audio.stt.openai.api_base_url",

+ 15 - 8
backend/open_webui/main.py

@@ -166,6 +166,7 @@ from open_webui.config import (
     FIRECRAWL_API_KEY,
     WEB_LOADER_ENGINE,
     WHISPER_MODEL,
+    WHISPER_VAD_FILTER,
     DEEPGRAM_API_KEY,
     WHISPER_MODEL_AUTO_UPDATE,
     WHISPER_MODEL_DIR,
@@ -789,6 +790,7 @@ app.state.config.STT_ENGINE = AUDIO_STT_ENGINE
 app.state.config.STT_MODEL = AUDIO_STT_MODEL
 
 app.state.config.WHISPER_MODEL = WHISPER_MODEL
+app.state.config.WHISPER_VAD_FILTER = WHISPER_VAD_FILTER
 app.state.config.DEEPGRAM_API_KEY = DEEPGRAM_API_KEY
 
 app.state.config.AUDIO_STT_AZURE_API_KEY = AUDIO_STT_AZURE_API_KEY
@@ -1023,14 +1025,19 @@ async def get_models(request: Request, user=Depends(get_verified_user)):
         if "pipeline" in model and model["pipeline"].get("type", None) == "filter":
             continue
 
-        model_tags = [
-            tag.get("name")
-            for tag in model.get("info", {}).get("meta", {}).get("tags", [])
-        ]
-        tags = [tag.get("name") for tag in model.get("tags", [])]
-
-        tags = list(set(model_tags + tags))
-        model["tags"] = [{"name": tag} for tag in tags]
+        try:
+            model_tags = [
+                tag.get("name")
+                for tag in model.get("info", {}).get("meta", {}).get("tags", [])
+            ]
+            tags = [tag.get("name") for tag in model.get("tags", [])]
+
+            tags = list(set(model_tags + tags))
+            model["tags"] = [{"name": tag} for tag in tags]
+        except Exception as e:
+            log.debug(f"Error processing model tags: {e}")
+            model["tags"] = []
+            pass
 
         models.append(model)
 

+ 5 - 1
backend/open_webui/routers/audio.py

@@ -497,7 +497,11 @@ def transcribe(request: Request, file_path):
             )
 
         model = request.app.state.faster_whisper_model
-        segments, info = model.transcribe(file_path, beam_size=5)
+        segments, info = model.transcribe(
+            file_path,
+            beam_size=5,
+            vad_filter=request.app.state.config.WHISPER_VAD_FILTER,
+        )
         log.info(
             "Detected language '%s' with probability %f"
             % (info.language, info.language_probability)

+ 3 - 1
backend/open_webui/routers/auths.py

@@ -230,13 +230,15 @@ async def ldap_auth(request: Request, response: Response, form_data: LdapForm):
 
         entry = connection_app.entries[0]
         username = str(entry[f"{LDAP_ATTRIBUTE_FOR_USERNAME}"]).lower()
-        email = entry[f"{LDAP_ATTRIBUTE_FOR_MAIL}"]
+        email = entry[f"{LDAP_ATTRIBUTE_FOR_MAIL}"].value  # retrive the Attribute value
         if not email:
             raise HTTPException(400, "User does not have a valid email address.")
         elif isinstance(email, str):
             email = email.lower()
         elif isinstance(email, list):
             email = email[0].lower()
+        else:
+            email = str(email).lower()
 
         cn = str(entry["cn"])
         user_dn = entry.entry_dn

+ 14 - 14
backend/open_webui/routers/retrieval.py

@@ -1520,20 +1520,20 @@ async def process_web_search(
         else:
             collection_names = []
             for doc_idx, doc in enumerate(docs):
-                collection_name = f"web-search-{calculate_sha256_string(form_data.query + '-' + urls[doc_idx])}"[
-                    :63
-                ]
-
-                collection_names.append(collection_name)
-
-                await run_in_threadpool(
-                    save_docs_to_vector_db,
-                    request,
-                    [doc],
-                    collection_name,
-                    overwrite=True,
-                    user=user,
-                )
+                if doc and doc.page_content:
+                    collection_name = f"web-search-{calculate_sha256_string(form_data.query + '-' + urls[doc_idx])}"[
+                        :63
+                    ]
+
+                    collection_names.append(collection_name)
+                    await run_in_threadpool(
+                        save_docs_to_vector_db,
+                        request,
+                        [doc],
+                        collection_name,
+                        overwrite=True,
+                        user=user,
+                    )
 
             return {
                 "status": True,

+ 3 - 0
backend/open_webui/routers/users.py

@@ -88,6 +88,9 @@ class ChatPermissions(BaseModel):
     file_upload: bool = True
     delete: bool = True
     edit: bool = True
+    stt: bool = True
+    tts: bool = True
+    call: bool = True
     multiple_models: bool = True
     temporary: bool = True
     temporary_enforced: bool = False

+ 11 - 10
backend/open_webui/socket/main.py

@@ -339,16 +339,17 @@ def get_event_emitter(request_info, update_db=True):
                     request_info["message_id"],
                 )
 
-                content = message.get("content", "")
-                content += event_data.get("data", {}).get("content", "")
-
-                Chats.upsert_message_to_chat_by_id_and_message_id(
-                    request_info["chat_id"],
-                    request_info["message_id"],
-                    {
-                        "content": content,
-                    },
-                )
+                if message:
+                    content = message.get("content", "")
+                    content += event_data.get("data", {}).get("content", "")
+
+                    Chats.upsert_message_to_chat_by_id_and_message_id(
+                        request_info["chat_id"],
+                        request_info["message_id"],
+                        {
+                            "content": content,
+                        },
+                    )
 
             if "type" in event_data and event_data["type"] == "replace":
                 content = event_data.get("data", {}).get("content", "")

+ 14 - 7
backend/open_webui/utils/middleware.py

@@ -534,13 +534,20 @@ async def chat_image_generation_handler(
             }
         )
 
-        for image in images:
-            await __event_emitter__(
-                {
-                    "type": "message",
-                    "data": {"content": f"![Generated Image]({image['url']})\n"},
-                }
-            )
+        await __event_emitter__(
+            {
+                "type": "files",
+                "data": {
+                    "files": [
+                        {
+                            "type": "image",
+                            "url": image["url"],
+                        }
+                        for image in images
+                    ]
+                },
+            }
+        )
 
         system_message_content = "<context>User is shown the generated image, tell the user that the image has been generated</context>"
     except Exception as e:

File diff suppressed because it is too large
+ 496 - 102
package-lock.json


+ 4 - 4
package.json

@@ -1,6 +1,6 @@
 {
 	"name": "open-webui",
-	"version": "0.6.4",
+	"version": "0.6.5",
 	"private": true,
 	"scripts": {
 		"dev": "npm run pyodide:fetch && vite dev --host",
@@ -72,11 +72,11 @@
 		"async": "^3.2.5",
 		"bits-ui": "^0.19.7",
 		"codemirror": "^6.0.1",
-		"codemirror-lang-hcl": "^0.0.0-beta.2",
 		"codemirror-lang-elixir": "^4.0.0",
+		"codemirror-lang-hcl": "^0.0.0-beta.2",
 		"crc-32": "^1.2.2",
 		"dayjs": "^1.11.10",
-		"dompurify": "^3.1.6",
+		"dompurify": "^3.2.5",
 		"eventsource-parser": "^1.1.2",
 		"file-saver": "^2.0.5",
 		"fuse.js": "^7.0.0",
@@ -92,7 +92,7 @@
 		"katex": "^0.16.21",
 		"kokoro-js": "^1.1.1",
 		"marked": "^9.1.0",
-		"mermaid": "^10.9.3",
+		"mermaid": "^11.6.0",
 		"paneforge": "^0.0.6",
 		"panzoom": "^9.4.3",
 		"prosemirror-commands": "^1.6.0",

+ 1 - 2
src/lib/components/admin/Settings/Audio.svelte

@@ -468,8 +468,7 @@
 										<option
 											value={voice.voiceURI}
 											class="bg-gray-100 dark:bg-gray-700"
-											selected={TTS_VOICE === voice.voiceURI}
-											>{voice.name.replace('+', ', ')}</option
+											selected={TTS_VOICE === voice.voiceURI}>{voice.name}</option
 										>
 									{/each}
 								</select>

+ 3 - 0
src/lib/components/admin/Users/Groups.svelte

@@ -63,6 +63,9 @@
 			file_upload: true,
 			delete: true,
 			edit: true,
+			stt: true,
+			tts: true,
+			call: true,
 			multiple_models: true,
 			temporary: true,
 			temporary_enforced: false

+ 31 - 5
src/lib/components/admin/Users/Groups/Permissions.svelte

@@ -21,9 +21,12 @@
 		},
 		chat: {
 			controls: true,
+			file_upload: true,
 			delete: true,
 			edit: true,
-			file_upload: true,
+			stt: true,
+			tts: true,
+			call: true,
 			multiple_models: true,
 			temporary: true,
 			temporary_enforced: false
@@ -243,18 +246,18 @@
 
 		<div class="  flex w-full justify-between my-2 pr-2">
 			<div class=" self-center text-xs font-medium">
-				{$i18n.t('Allow Chat Controls')}
+				{$i18n.t('Allow File Upload')}
 			</div>
 
-			<Switch bind:state={permissions.chat.controls} />
+			<Switch bind:state={permissions.chat.file_upload} />
 		</div>
 
 		<div class="  flex w-full justify-between my-2 pr-2">
 			<div class=" self-center text-xs font-medium">
-				{$i18n.t('Allow File Upload')}
+				{$i18n.t('Allow Chat Controls')}
 			</div>
 
-			<Switch bind:state={permissions.chat.file_upload} />
+			<Switch bind:state={permissions.chat.controls} />
 		</div>
 
 		<div class="  flex w-full justify-between my-2 pr-2">
@@ -273,6 +276,29 @@
 			<Switch bind:state={permissions.chat.edit} />
 		</div>
 
+		<div class="  flex w-full justify-between my-2 pr-2">
+			<div class=" self-center text-xs font-medium">
+				{$i18n.t('Allow Speech to Text')}
+			</div>
+
+			<Switch bind:state={permissions.chat.stt} />
+		</div>
+		<div class="  flex w-full justify-between my-2 pr-2">
+			<div class=" self-center text-xs font-medium">
+				{$i18n.t('Allow Text to Speech')}
+			</div>
+
+			<Switch bind:state={permissions.chat.tts} />
+		</div>
+
+		<div class="  flex w-full justify-between my-2 pr-2">
+			<div class=" self-center text-xs font-medium">
+				{$i18n.t('Allow Call')}
+			</div>
+
+			<Switch bind:state={permissions.chat.call} />
+		</div>
+
 		<div class="  flex w-full justify-between my-2 pr-2">
 			<div class=" self-center text-xs font-medium">
 				{$i18n.t('Allow Multiple Models in Chat')}

+ 28 - 26
src/lib/components/chat/Chat.svelte

@@ -262,6 +262,21 @@
 					} else {
 						message.statusHistory = [data];
 					}
+				} else if (type === 'chat:completion') {
+					chatCompletionEventHandler(data, message, event.chat_id);
+				} else if (type === 'chat:message:delta' || type === 'message') {
+					message.content += data.content;
+				} else if (type === 'chat:message' || type === 'replace') {
+					message.content = data.content;
+				} else if (type === 'chat:message:files' || type === 'files') {
+					message.files = data.files;
+				} else if (type === 'chat:title') {
+					chatTitle.set(data);
+					currentChatPage.set(1);
+					await chats.set(await getChatList(localStorage.token, $currentChatPage));
+				} else if (type === 'chat:tags') {
+					chat = await getChatById(localStorage.token, $chatId);
+					allTags.set(await getAllTags(localStorage.token));
 				} else if (type === 'source' || type === 'citation') {
 					if (data?.type === 'code_execution') {
 						// Code execution; update existing code execution by ID, or add new one.
@@ -288,19 +303,19 @@
 							message.sources = [data];
 						}
 					}
-				} else if (type === 'chat:completion') {
-					chatCompletionEventHandler(data, message, event.chat_id);
-				} else if (type === 'chat:title') {
-					chatTitle.set(data);
-					currentChatPage.set(1);
-					await chats.set(await getChatList(localStorage.token, $currentChatPage));
-				} else if (type === 'chat:tags') {
-					chat = await getChatById(localStorage.token, $chatId);
-					allTags.set(await getAllTags(localStorage.token));
-				} else if (type === 'chat:message:delta' || type === 'message') {
-					message.content += data.content;
-				} else if (type === 'chat:message' || type === 'replace') {
-					message.content = data.content;
+				} else if (type === 'notification') {
+					const toastType = data?.type ?? 'info';
+					const toastContent = data?.content ?? '';
+
+					if (toastType === 'success') {
+						toast.success(toastContent);
+					} else if (toastType === 'error') {
+						toast.error(toastContent);
+					} else if (toastType === 'warning') {
+						toast.warning(toastContent);
+					} else {
+						toast.info(toastContent);
+					}
 				} else if (type === 'confirmation') {
 					eventCallback = cb;
 
@@ -333,19 +348,6 @@
 					eventConfirmationMessage = data.message;
 					eventConfirmationInputPlaceholder = data.placeholder;
 					eventConfirmationInputValue = data?.value ?? '';
-				} else if (type === 'notification') {
-					const toastType = data?.type ?? 'info';
-					const toastContent = data?.content ?? '';
-
-					if (toastType === 'success') {
-						toast.success(toastContent);
-					} else if (toastType === 'error') {
-						toast.error(toastContent);
-					} else if (toastType === 'warning') {
-						toast.warning(toastContent);
-					} else {
-						toast.info(toastContent);
-					}
 				} else {
 					console.log('Unknown message type', data);
 				}

+ 2 - 2
src/lib/components/chat/MessageInput.svelte

@@ -1189,7 +1189,7 @@
 									</div>
 
 									<div class="self-end flex space-x-1 mr-1 shrink-0">
-										{#if !history?.currentId || history.messages[history.currentId]?.done == true}
+										{#if (!history?.currentId || history.messages[history.currentId]?.done == true) && ($_user?.role === 'admin' || ($_user?.permissions?.chat?.stt ?? true))}
 											<Tooltip content={$i18n.t('Record voice')}>
 												<button
 													id="voice-input-button"
@@ -1262,7 +1262,7 @@
 													</button>
 												</Tooltip>
 											</div>
-										{:else if prompt === '' && files.length === 0}
+										{:else if prompt === '' && files.length === 0 && ($_user?.role === 'admin' || ($_user?.permissions?.chat?.call ?? true))}
 											<div class=" flex items-center">
 												<Tooltip content={$i18n.t('Call')}>
 													<button

+ 99 - 86
src/lib/components/chat/Messages/ResponseMessage.svelte

@@ -47,6 +47,7 @@
 	import CodeExecutions from './CodeExecutions.svelte';
 	import ContentRenderer from './ContentRenderer.svelte';
 	import { KokoroWorker } from '$lib/workers/KokoroWorker';
+	import FileItem from '$lib/components/common/FileItem.svelte';
 
 	interface MessageType {
 		id: string;
@@ -155,7 +156,8 @@
 
 	const copyToClipboard = async (text) => {
 		text = removeAllDetails(text);
-		const res = await _copyToClipboard(text);
+
+		const res = await _copyToClipboard(text, $settings?.copyFormatted ?? false);
 		if (res) {
 			toast.success($i18n.t('Copying to clipboard was successful!'));
 		}
@@ -613,18 +615,6 @@
 			</Name>
 
 			<div>
-				{#if message?.files && message.files?.filter((f) => f.type === 'image').length > 0}
-					<div class="my-2.5 w-full flex overflow-x-auto gap-2 flex-wrap">
-						{#each message.files as file}
-							<div>
-								{#if file.type === 'image'}
-									<Image src={file.url} alt={message.content} />
-								{/if}
-							</div>
-						{/each}
-					</div>
-				{/if}
-
 				<div class="chat-{message.role} w-full min-w-full markdown-prose">
 					<div>
 						{#if (message?.statusHistory ?? [...(message?.status ? [message?.status] : [])]).length > 0}
@@ -703,6 +693,27 @@
 							{/if}
 						{/if}
 
+						{#if message?.files && message.files?.filter((f) => f.type === 'image').length > 0}
+							<div class="my-1 w-full flex overflow-x-auto gap-2 flex-wrap">
+								{#each message.files as file}
+									<div>
+										{#if file.type === 'image'}
+											<Image src={file.url} alt={message.content} />
+										{:else}
+											<FileItem
+												item={file}
+												url={file.url}
+												name={file.name}
+												type={file.type}
+												size={file?.size}
+												colorClassName="bg-white dark:bg-gray-850 "
+											/>
+										{/if}
+									</div>
+								{/each}
+							</div>
+						{/if}
+
 						{#if edit === true}
 							<div class="w-full bg-gray-50 dark:bg-gray-800 rounded-3xl px-5 py-3 my-2">
 								<textarea
@@ -1009,83 +1020,85 @@
 									</button>
 								</Tooltip>
 
-								<Tooltip content={$i18n.t('Read Aloud')} placement="bottom">
-									<button
-										id="speak-button-{message.id}"
-										class="{isLastMessage
-											? 'visible'
-											: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition"
-										on:click={() => {
-											if (!loadingSpeech) {
-												toggleSpeakMessage();
-											}
-										}}
-									>
-										{#if loadingSpeech}
-											<svg
-												class=" w-4 h-4"
-												fill="currentColor"
-												viewBox="0 0 24 24"
-												xmlns="http://www.w3.org/2000/svg"
-											>
-												<style>
-													.spinner_S1WN {
-														animation: spinner_MGfb 0.8s linear infinite;
-														animation-delay: -0.8s;
-													}
+								{#if $user?.role === 'admin' || ($user?.permissions?.chat?.tts ?? true)}
+									<Tooltip content={$i18n.t('Read Aloud')} placement="bottom">
+										<button
+											id="speak-button-{message.id}"
+											class="{isLastMessage
+												? 'visible'
+												: 'invisible group-hover:visible'} p-1.5 hover:bg-black/5 dark:hover:bg-white/5 rounded-lg dark:hover:text-white hover:text-black transition"
+											on:click={() => {
+												if (!loadingSpeech) {
+													toggleSpeakMessage();
+												}
+											}}
+										>
+											{#if loadingSpeech}
+												<svg
+													class=" w-4 h-4"
+													fill="currentColor"
+													viewBox="0 0 24 24"
+													xmlns="http://www.w3.org/2000/svg"
+												>
+													<style>
+														.spinner_S1WN {
+															animation: spinner_MGfb 0.8s linear infinite;
+															animation-delay: -0.8s;
+														}
 
-													.spinner_Km9P {
-														animation-delay: -0.65s;
-													}
+														.spinner_Km9P {
+															animation-delay: -0.65s;
+														}
 
-													.spinner_JApP {
-														animation-delay: -0.5s;
-													}
+														.spinner_JApP {
+															animation-delay: -0.5s;
+														}
 
-													@keyframes spinner_MGfb {
-														93.75%,
-														100% {
-															opacity: 0.2;
+														@keyframes spinner_MGfb {
+															93.75%,
+															100% {
+																opacity: 0.2;
+															}
 														}
-													}
-												</style>
-												<circle class="spinner_S1WN" cx="4" cy="12" r="3" />
-												<circle class="spinner_S1WN spinner_Km9P" cx="12" cy="12" r="3" />
-												<circle class="spinner_S1WN spinner_JApP" cx="20" cy="12" r="3" />
-											</svg>
-										{:else if speaking}
-											<svg
-												xmlns="http://www.w3.org/2000/svg"
-												fill="none"
-												viewBox="0 0 24 24"
-												stroke-width="2.3"
-												stroke="currentColor"
-												class="w-4 h-4"
-											>
-												<path
-													stroke-linecap="round"
-													stroke-linejoin="round"
-													d="M17.25 9.75 19.5 12m0 0 2.25 2.25M19.5 12l2.25-2.25M19.5 12l-2.25 2.25m-10.5-6 4.72-4.72a.75.75 0 0 1 1.28.53v15.88a.75.75 0 0 1-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.009 9.009 0 0 1 2.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75Z"
-												/>
-											</svg>
-										{:else}
-											<svg
-												xmlns="http://www.w3.org/2000/svg"
-												fill="none"
-												viewBox="0 0 24 24"
-												stroke-width="2.3"
-												stroke="currentColor"
-												class="w-4 h-4"
-											>
-												<path
-													stroke-linecap="round"
-													stroke-linejoin="round"
-													d="M19.114 5.636a9 9 0 010 12.728M16.463 8.288a5.25 5.25 0 010 7.424M6.75 8.25l4.72-4.72a.75.75 0 011.28.53v15.88a.75.75 0 01-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.01 9.01 0 012.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75z"
-												/>
-											</svg>
-										{/if}
-									</button>
-								</Tooltip>
+													</style>
+													<circle class="spinner_S1WN" cx="4" cy="12" r="3" />
+													<circle class="spinner_S1WN spinner_Km9P" cx="12" cy="12" r="3" />
+													<circle class="spinner_S1WN spinner_JApP" cx="20" cy="12" r="3" />
+												</svg>
+											{:else if speaking}
+												<svg
+													xmlns="http://www.w3.org/2000/svg"
+													fill="none"
+													viewBox="0 0 24 24"
+													stroke-width="2.3"
+													stroke="currentColor"
+													class="w-4 h-4"
+												>
+													<path
+														stroke-linecap="round"
+														stroke-linejoin="round"
+														d="M17.25 9.75 19.5 12m0 0 2.25 2.25M19.5 12l2.25-2.25M19.5 12l-2.25 2.25m-10.5-6 4.72-4.72a.75.75 0 0 1 1.28.53v15.88a.75.75 0 0 1-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.009 9.009 0 0 1 2.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75Z"
+													/>
+												</svg>
+											{:else}
+												<svg
+													xmlns="http://www.w3.org/2000/svg"
+													fill="none"
+													viewBox="0 0 24 24"
+													stroke-width="2.3"
+													stroke="currentColor"
+													class="w-4 h-4"
+												>
+													<path
+														stroke-linecap="round"
+														stroke-linejoin="round"
+														d="M19.114 5.636a9 9 0 010 12.728M16.463 8.288a5.25 5.25 0 010 7.424M6.75 8.25l4.72-4.72a.75.75 0 011.28.53v15.88a.75.75 0 01-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.01 9.01 0 012.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75z"
+													/>
+												</svg>
+											{/if}
+										</button>
+									</Tooltip>
+								{/if}
 
 								{#if $config?.features.enable_image_generation && ($user?.role === 'admin' || $user?.permissions?.features?.image_generation) && !readOnly}
 									<Tooltip content={$i18n.t('Generate Image')} placement="bottom">

+ 3 - 1
src/lib/components/chat/ModelSelector/Selector.svelte

@@ -634,7 +634,7 @@
 						{/if}
 					</button>
 				{:else}
-					<div>
+					<div class="">
 						<div class="block px-3 py-2 text-sm text-gray-700 dark:text-gray-100">
 							{$i18n.t('No results found')}
 						</div>
@@ -778,6 +778,8 @@
 						</div>
 					</button>
 				</div>
+			{:else if filteredItems.length === 0}
+				<div class="mb-3"></div>
 			{/if}
 
 			<div class="hidden w-[42rem]" />

+ 29 - 0
src/lib/components/chat/Settings/Interface.svelte

@@ -43,6 +43,7 @@
 	let chatBubble = true;
 	let chatDirection: 'LTR' | 'RTL' | 'auto' = 'auto';
 	let ctrlEnterToSend = false;
+	let copyFormatted = false;
 
 	let collapseCodeBlocks = false;
 	let expandDetails = false;
@@ -220,6 +221,11 @@
 		}
 	};
 
+	const toggleCopyFormatted = async () => {
+		copyFormatted = !copyFormatted;
+		saveSettings({ copyFormatted });
+	};
+
 	const toggleChangeChatDirection = async () => {
 		if (chatDirection === 'auto') {
 			chatDirection = 'LTR';
@@ -275,6 +281,7 @@
 		richTextInput = $settings.richTextInput ?? true;
 		promptAutocomplete = $settings.promptAutocomplete ?? false;
 		largeTextAsFile = $settings.largeTextAsFile ?? false;
+		copyFormatted = $settings.copyFormatted ?? false;
 
 		collapseCodeBlocks = $settings.collapseCodeBlocks ?? false;
 		expandDetails = $settings.expandDetails ?? false;
@@ -670,6 +677,28 @@
 				</div>
 			</div>
 
+			<div>
+				<div class=" py-0.5 flex w-full justify-between">
+					<div class=" self-center text-xs">
+						{$i18n.t('Copy Formatted Text')}
+					</div>
+
+					<button
+						class="p-1 px-3 text-xs flex rounded-sm transition"
+						on:click={() => {
+							toggleCopyFormatted();
+						}}
+						type="button"
+					>
+						{#if copyFormatted === true}
+							<span class="ml-2 self-center">{$i18n.t('On')}</span>
+						{:else}
+							<span class="ml-2 self-center">{$i18n.t('Off')}</span>
+						{/if}
+					</button>
+				</div>
+			</div>
+
 			<div>
 				<div class=" py-0.5 flex w-full justify-between">
 					<div class=" self-center text-xs">{$i18n.t('Always Collapse Code Blocks')}</div>

+ 4 - 0
src/lib/i18n/locales/ar-BH/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "جميع الملفات",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "يستطيع حذف المحادثات",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "تم نسخ عنوان URL للدردشة المشتركة إلى الحافظة",
 	"Copied to clipboard": "",
 	"Copy": "نسخ",
+	"Copy Formatted Text": "",
 	"Copy last code block": "انسخ كتلة التعليمات البرمجية الأخيرة",
 	"Copy last response": "انسخ الرد الأخير",
 	"Copy Link": "أنسخ الرابط",

+ 4 - 0
src/lib/i18n/locales/ar/translation.json

@@ -57,6 +57,7 @@
 	"All": "الكل",
 	"All Documents": "جميع المستندات",
 	"All models deleted successfully": "تم حذف جميع النماذج بنجاح",
+	"Allow Call": "",
 	"Allow Chat Controls": "السماح بوسائل التحكم في المحادثة",
 	"Allow Chat Delete": "السماح بحذف المحادثة",
 	"Allow Chat Deletion": "السماح بحذف المحادثة",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "السماح بتحميل الملفات",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "السماح بالأصوات غير المحلية",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "السماح بالمحادثة المؤقتة",
+	"Allow Text to Speech": "",
 	"Allow User Location": "السماح بتحديد موقع المستخدم",
 	"Allow Voice Interruption in Call": "السماح بانقطاع الصوت أثناء المكالمة",
 	"Allowed Endpoints": "النقاط النهائية المسموح بها",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "تم نسخ رابط المحادثة المشترك إلى الحافظة!",
 	"Copied to clipboard": "تم النسخ إلى الحافظة",
 	"Copy": "نسخ",
+	"Copy Formatted Text": "",
 	"Copy last code block": "نسخ آخر كتلة شيفرة",
 	"Copy last response": "نسخ آخر رد",
 	"Copy Link": "نسخ الرابط",

+ 4 - 0
src/lib/i18n/locales/bg-BG/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Всички Документи",
 	"All models deleted successfully": "Всички модели са изтрити успешно",
+	"Allow Call": "",
 	"Allow Chat Controls": "Разреши контроли на чата",
 	"Allow Chat Delete": "Разреши изтриване на чат",
 	"Allow Chat Deletion": "Позволи Изтриване на Чат",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Разреши качване на файлове",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Разреши нелокални гласове",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Разреши временен чат",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Разреши местоположение на потребителя",
 	"Allow Voice Interruption in Call": "Разреши прекъсване на гласа по време на разговор",
 	"Allowed Endpoints": "Разрешени крайни точки",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Копирана е връзката за споделен чат в клипборда!",
 	"Copied to clipboard": "Копирано в клипборда",
 	"Copy": "Копирай",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Копиране на последен код блок",
 	"Copy last response": "Копиране на последен отговор",
 	"Copy Link": "Копиране на връзка",

+ 4 - 0
src/lib/i18n/locales/bn-BD/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "সব ডকুমেন্ট",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "চ্যাট ডিলিট করতে দিন",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "শেয়ারকৃত কথা-ব্যবহারের URL ক্লিপবোর্ডে কপি করা হয়েছে!",
 	"Copied to clipboard": "",
 	"Copy": "অনুলিপি",
+	"Copy Formatted Text": "",
 	"Copy last code block": "সর্বশেষ কোড ব্লক কপি করুন",
 	"Copy last response": "সর্বশেষ রেসপন্স কপি করুন",
 	"Copy Link": "লিংক কপি করুন",

+ 4 - 0
src/lib/i18n/locales/bo-TB/translation.json

@@ -57,6 +57,7 @@
 	"All": "ཡོངས།",
 	"All Documents": "ཡིག་ཆ་ཡོངས།",
 	"All models deleted successfully": "དཔེ་དབྱིབས་ཡོངས་རྫོགས་ལེགས་པར་བསུབས་ཟིན།",
+	"Allow Call": "",
 	"Allow Chat Controls": "ཁ་བརྡའི་ཚོད་འཛིན་ལ་གནང་བ་སྤྲོད་པ།",
 	"Allow Chat Delete": "ཁ་བརྡ་བསུབ་པར་གནང་བ་སྤྲོད་པ།",
 	"Allow Chat Deletion": "ཁ་བརྡ་བསུབ་པར་གནང་བ་སྤྲོད་པ།",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "ཡིག་ཆ་སྤར་བར་གནང་བ་སྤྲོད་པ།",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "ས་གནས་མིན་པའི་སྐད་གདངས་ལ་གནང་བ་སྤྲོད་པ།",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "གནས་སྐབས་ཁ་བརྡར་གནང་བ་སྤྲོད་པ།",
+	"Allow Text to Speech": "",
 	"Allow User Location": "བེད་སྤྱོད་མཁན་གནས་ཡུལ་ལ་གནང་བ་སྤྲོད་པ།",
 	"Allow Voice Interruption in Call": "སྐད་འབོད་ནང་གི་སྐད་ཆའི་བར་ཆད་ལ་གནང་བ་སྤྲོད་པ།",
 	"Allowed Endpoints": "གནང་བ་ཐོབ་པའི་མཇུག་མཐུད།",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "མཉམ་སྤྱོད་ཁ་བརྡའི་ URL སྦྱར་སྡེར་དུ་འདྲ་བཤུས་བྱས་ཟིན།",
 	"Copied to clipboard": "སྦྱར་སྡེར་དུ་འདྲ་བཤུས་བྱས་པ།",
 	"Copy": "འདྲ་བཤུས།",
+	"Copy Formatted Text": "",
 	"Copy last code block": "ཀོཌ་གཏོགས་ཁོངས་མཐའ་མ་འདྲ་བཤུས།",
 	"Copy last response": "ལན་མཐའ་མ་འདྲ་བཤུས།",
 	"Copy Link": "སྦྲེལ་ཐག་འདྲ་བཤུས།",

+ 4 - 0
src/lib/i18n/locales/ca-ES/translation.json

@@ -57,6 +57,7 @@
 	"All": "Tots",
 	"All Documents": "Tots els documents",
 	"All models deleted successfully": "Tots els models s'han eliminat correctament",
+	"Allow Call": "",
 	"Allow Chat Controls": "Permetre els controls de xat",
 	"Allow Chat Delete": "Permetre eliminar el xat",
 	"Allow Chat Deletion": "Permetre la supressió del xat",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Permetre la pujada d'arxius",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Permetre veus no locals",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Permetre el xat temporal",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Permetre la ubicació de l'usuari",
 	"Allow Voice Interruption in Call": "Permetre la interrupció de la veu en una trucada",
 	"Allowed Endpoints": "Punts d'accés permesos",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "S'ha copiat l'URL compartida al porta-retalls!",
 	"Copied to clipboard": "Copiat al porta-retalls",
 	"Copy": "Copiar",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Copiar l'últim bloc de codi",
 	"Copy last response": "Copiar l'última resposta",
 	"Copy Link": "Copiar l'enllaç",

+ 4 - 0
src/lib/i18n/locales/ceb-PH/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "Tugoti nga mapapas ang mga chat",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "",
 	"Copied to clipboard": "",
 	"Copy": "",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Kopyaha ang katapusang bloke sa code",
 	"Copy last response": "Kopyaha ang kataposang tubag",
 	"Copy Link": "",

+ 4 - 0
src/lib/i18n/locales/cs-CZ/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Všechny dokumenty",
 	"All models deleted successfully": "Všechny modely úspěšně odstráněny",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "Povolit odstranění chatu",
 	"Allow Chat Deletion": "Povolit odstranění chatu",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Povolit nahrávat soubory",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Povolit ne-místní hlasy",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Povolit dočasný chat",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Povolit uživatelskou polohu",
 	"Allow Voice Interruption in Call": "Povolit přerušení hlasu při hovoru",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "URL sdíleného chatu zkopírován do schránky!",
 	"Copied to clipboard": "Zkopírováno do schránky",
 	"Copy": "Kopírovat",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Zkopírujte poslední blok kódu",
 	"Copy last response": "Zkopírujte poslední odpověď",
 	"Copy Link": "Kopírovat odkaz",

+ 4 - 0
src/lib/i18n/locales/da-DK/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Alle dokumenter",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "Tillad sletning af chats",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Tillad ikke-lokale stemmer",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Tillad midlertidig chat",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Tillad bruger-lokation",
 	"Allow Voice Interruption in Call": "Tillad afbrydelser i stemme i opkald",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Link til deling kopieret til udklipsholder",
 	"Copied to clipboard": "Kopieret til udklipsholder",
 	"Copy": "Kopier",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Kopier seneste kode",
 	"Copy last response": "Kopier senester svar",
 	"Copy Link": "Kopier link",

+ 4 - 0
src/lib/i18n/locales/de-DE/translation.json

@@ -57,6 +57,7 @@
 	"All": "Alle",
 	"All Documents": "Alle Dokumente",
 	"All models deleted successfully": "Alle Modelle erfolgreich gelöscht",
+	"Allow Call": "",
 	"Allow Chat Controls": "Chat-Steuerung erlauben",
 	"Allow Chat Delete": "Löschen von Chats erlauben",
 	"Allow Chat Deletion": "Löschen von Chats erlauben",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Hochladen von Dateien erlauben",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Nicht-lokale Stimmen erlauben",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Temporäre Chats erlauben",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Standort freigeben",
 	"Allow Voice Interruption in Call": "Unterbrechung durch Stimme im Anruf zulassen",
 	"Allowed Endpoints": "Erlaubte Endpunkte",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Freigabelink in die Zwischenablage kopiert!",
 	"Copied to clipboard": "In die Zwischenablage kopiert",
 	"Copy": "Kopieren",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Letzten Codeblock kopieren",
 	"Copy last response": "Letzte Antwort kopieren",
 	"Copy Link": "Link kopieren",

+ 4 - 0
src/lib/i18n/locales/dg-DG/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "Allow Delete Chats",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "",
 	"Copied to clipboard": "",
 	"Copy": "",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Copy last code block",
 	"Copy last response": "Copy last response",
 	"Copy Link": "",

+ 4 - 0
src/lib/i18n/locales/el-GR/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Όλα τα Έγγραφα",
 	"All models deleted successfully": "Όλα τα μοντέλα διαγράφηκαν με επιτυχία",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "Επιτρέπεται η διαγραφή συνομιλίας",
 	"Allow Chat Deletion": "Επιτρέπεται η Διαγραφή Συνομιλίας",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Επιτρέπεται η Αποστολή Αρχείων",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Επιτρέπονται μη τοπικές φωνές",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Επιτρέπεται η Προσωρινή Συνομιλία",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Επιτρέπεται η Τοποθεσία Χρήστη",
 	"Allow Voice Interruption in Call": "Επιτρέπεται η Παύση Φωνής στην Κλήση",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Αντιγράφηκε το URL της κοινόχρηστης συνομιλίας στο πρόχειρο!",
 	"Copied to clipboard": "Αντιγράφηκε στο πρόχειρο",
 	"Copy": "Αντιγραφή",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Αντιγραφή τελευταίου μπλοκ κώδικα",
 	"Copy last response": "Αντιγραφή τελευταίας απάντησης",
 	"Copy Link": "Αντιγραφή Συνδέσμου",

+ 4 - 0
src/lib/i18n/locales/en-GB/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "",
 	"Copied to clipboard": "",
 	"Copy": "",
+	"Copy Formatted Text": "",
 	"Copy last code block": "",
 	"Copy last response": "",
 	"Copy Link": "",

+ 4 - 0
src/lib/i18n/locales/en-US/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "",
 	"Copied to clipboard": "",
 	"Copy": "",
+	"Copy Formatted Text": "",
 	"Copy last code block": "",
 	"Copy last response": "",
 	"Copy Link": "",

+ 4 - 0
src/lib/i18n/locales/es-ES/translation.json

@@ -57,6 +57,7 @@
 	"All": "Todos",
 	"All Documents": "Todos los Documentos",
 	"All models deleted successfully": "Todos los modelos borrados correctamnete",
+	"Allow Call": "",
 	"Allow Chat Controls": "Permitir Controles del Chat",
 	"Allow Chat Delete": "Permitir Borrar Chat",
 	"Allow Chat Deletion": "Permitir Borrado de Chat",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Permitir Subida de Ficheros",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Permitir voces no locales",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Permitir Chat Temporal",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Permitir Ubicación de Usuari@",
 	"Allow Voice Interruption in Call": "Permitir Interrupción de Voz en Llamada",
 	"Allowed Endpoints": "Endpoints Permitidos",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "¡Copiada al portapapeles la URL del chat compartido!",
 	"Copied to clipboard": "Copiado al portapapeles",
 	"Copy": "Copiar",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Copia el último bloque de código",
 	"Copy last response": "Copia la última respuesta",
 	"Copy Link": "Copiar enlace",

+ 4 - 0
src/lib/i18n/locales/et-EE/translation.json

@@ -57,6 +57,7 @@
 	"All": "Kõik",
 	"All Documents": "Kõik dokumendid",
 	"All models deleted successfully": "Kõik mudelid edukalt kustutatud",
+	"Allow Call": "",
 	"Allow Chat Controls": "Luba vestluse kontrollnupud",
 	"Allow Chat Delete": "Luba vestluse kustutamine",
 	"Allow Chat Deletion": "Luba vestluse kustutamine",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Luba failide üleslaadimine",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Luba mitte-lokaalsed hääled",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Luba ajutine vestlus",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Luba kasutaja asukoht",
 	"Allow Voice Interruption in Call": "Luba hääle katkestamine kõnes",
 	"Allowed Endpoints": "Lubatud lõpp-punktid",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Jagatud vestluse URL kopeeritud lõikelauale!",
 	"Copied to clipboard": "Kopeeritud lõikelauale",
 	"Copy": "Kopeeri",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Kopeeri viimane koodiplokk",
 	"Copy last response": "Kopeeri viimane vastus",
 	"Copy Link": "Kopeeri link",

+ 4 - 0
src/lib/i18n/locales/eu-ES/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Dokumentu Guztiak",
 	"All models deleted successfully": "Eredu guztiak ongi ezabatu dira",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "Baimendu Txata Ezabatzea",
 	"Allow Chat Deletion": "Baimendu Txata Ezabatzea",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Baimendu Fitxategiak Igotzea",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Baimendu urruneko ahotsak",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Baimendu Behin-behineko Txata",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Baimendu Erabiltzailearen Kokapena",
 	"Allow Voice Interruption in Call": "Baimendu Ahots Etena Deietan",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Partekatutako txataren URLa arbelera kopiatu da!",
 	"Copied to clipboard": "Arbelera kopiatuta",
 	"Copy": "Kopiatu",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Kopiatu azken kode blokea",
 	"Copy last response": "Kopiatu azken erantzuna",
 	"Copy Link": "Kopiatu Esteka",

+ 4 - 0
src/lib/i18n/locales/fa-IR/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "همهٔ سند\u200cها",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "اجازهٔ حذف گفتگو",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "اجازهٔ گفتگوی موقتی",
+	"Allow Text to Speech": "",
 	"Allow User Location": "اجازهٔ موقعیت مکانی کاربر",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "URL چت به کلیپ بورد کپی شد!",
 	"Copied to clipboard": "به بریده\u200cدان کپی\u200cشد",
 	"Copy": "کپی",
+	"Copy Formatted Text": "",
 	"Copy last code block": "کپی آخرین بلوک کد",
 	"Copy last response": "کپی آخرین پاسخ",
 	"Copy Link": "کپی لینک",

+ 4 - 0
src/lib/i18n/locales/fi-FI/translation.json

@@ -57,6 +57,7 @@
 	"All": "Kaikki",
 	"All Documents": "Kaikki asiakirjat",
 	"All models deleted successfully": "Kaikki mallit poistettu onnistuneesti",
+	"Allow Call": "",
 	"Allow Chat Controls": "Salli keskustelujen hallinta",
 	"Allow Chat Delete": "Salli keskustelujen poisto",
 	"Allow Chat Deletion": "Salli keskustelujen poisto",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Salli tiedostojen lataus",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Salli ei-paikalliset äänet",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Salli väliaikaiset keskustelut",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Salli käyttäjän sijainti",
 	"Allow Voice Interruption in Call": "Salli äänen keskeytys puhelussa",
 	"Allowed Endpoints": "Hyväksytyt päätepisteet",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Jaettu keskustelulinkki kopioitu leikepöydälle!",
 	"Copied to clipboard": "Kopioitu leikepöydälle",
 	"Copy": "Kopioi",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Kopioi viimeisin koodilohko",
 	"Copy last response": "Kopioi viimeisin vastaus",
 	"Copy Link": "Kopioi linkki",

+ 4 - 0
src/lib/i18n/locales/fr-CA/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Tous les documents",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "Autoriser la suppression de l'historique de chat",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Autoriser les voix non locales",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Autoriser l'emplacement de l'utilisateur",
 	"Allow Voice Interruption in Call": "Autoriser l'interruption vocale pendant un appel",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "URL du chat copiée dans le presse-papiers\u00a0!",
 	"Copied to clipboard": "",
 	"Copy": "Copie",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Copier le dernier bloc de code",
 	"Copy last response": "Copier la dernière réponse",
 	"Copy Link": "Copier le lien",

+ 4 - 0
src/lib/i18n/locales/fr-FR/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Tous les documents",
 	"All models deleted successfully": "Tous les modèles ont été supprimés avec succès",
+	"Allow Call": "",
 	"Allow Chat Controls": "Autoriser les contrôles de chat",
 	"Allow Chat Delete": "Autoriser la suppression de la conversation",
 	"Allow Chat Deletion": "Autoriser la suppression de l'historique de chat",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Autoriser le téléchargement de fichiers",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Autoriser les voix non locales",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Autoriser le chat éphémère",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Autoriser l'emplacement de l'utilisateur",
 	"Allow Voice Interruption in Call": "Autoriser l'interruption vocale pendant un appel",
 	"Allowed Endpoints": "Points de terminaison autorisés",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "URL du chat copié dans le presse-papiers !",
 	"Copied to clipboard": "Copié dans le presse-papiers",
 	"Copy": "Copier",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Copier le dernier bloc de code",
 	"Copy last response": "Copier la dernière réponse",
 	"Copy Link": "Copier le lien",

+ 4 - 0
src/lib/i18n/locales/he-IL/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "כל המסמכים",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "אפשר מחיקת צ'אט",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "העתקת כתובת URL של צ'אט משותף ללוח!",
 	"Copied to clipboard": "",
 	"Copy": "העתק",
+	"Copy Formatted Text": "",
 	"Copy last code block": "העתק את בלוק הקוד האחרון",
 	"Copy last response": "העתק את התגובה האחרונה",
 	"Copy Link": "העתק קישור",

+ 4 - 0
src/lib/i18n/locales/hi-IN/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "सभी डॉक्यूमेंट्स",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "चैट हटाने की अनुमति दें",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "साझा चैट URL को क्लिपबोर्ड पर कॉपी किया गया!",
 	"Copied to clipboard": "",
 	"Copy": "कॉपी",
+	"Copy Formatted Text": "",
 	"Copy last code block": "अंतिम कोड ब्लॉक कॉपी करें",
 	"Copy last response": "अंतिम प्रतिक्रिया कॉपी करें",
 	"Copy Link": "लिंक को कॉपी करें",

+ 4 - 0
src/lib/i18n/locales/hr-HR/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Svi dokumenti",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "Dopusti brisanje razgovora",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Dopusti nelokalne glasove",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "URL dijeljenog razgovora kopiran u međuspremnik!",
 	"Copied to clipboard": "",
 	"Copy": "Kopiraj",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Kopiraj zadnji blok koda",
 	"Copy last response": "Kopiraj zadnji odgovor",
 	"Copy Link": "Kopiraj vezu",

+ 4 - 0
src/lib/i18n/locales/hu-HU/translation.json

@@ -57,6 +57,7 @@
 	"All": "Mind",
 	"All Documents": "Minden dokumentum",
 	"All models deleted successfully": "Minden modell sikeresen törölve",
+	"Allow Call": "",
 	"Allow Chat Controls": "Csevegésvezérlők engedélyezése",
 	"Allow Chat Delete": "Csevegés törlésének engedélyezése",
 	"Allow Chat Deletion": "Beszélgetések törlésének engedélyezése",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Fájlfeltöltés engedélyezése",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Nem helyi hangok engedélyezése",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Ideiglenes beszélgetés engedélyezése",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Felhasználói helyzet engedélyezése",
 	"Allow Voice Interruption in Call": "Hang megszakítás engedélyezése hívás közben",
 	"Allowed Endpoints": "Engedélyezett végpontok",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Megosztott beszélgetés URL másolva a vágólapra!",
 	"Copied to clipboard": "Vágólapra másolva",
 	"Copy": "Másolás",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Utolsó kódblokk másolása",
 	"Copy last response": "Utolsó válasz másolása",
 	"Copy Link": "Link másolása",

+ 4 - 0
src/lib/i18n/locales/id-ID/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Semua Dokumen",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "Izinkan Penghapusan Obrolan",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Izinkan suara non-lokal",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Izinkan Lokasi Pengguna",
 	"Allow Voice Interruption in Call": "Izinkan Gangguan Suara dalam Panggilan",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Menyalin URL obrolan bersama ke papan klip!",
 	"Copied to clipboard": "",
 	"Copy": "Menyalin",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Salin blok kode terakhir",
 	"Copy last response": "Salin tanggapan terakhir",
 	"Copy Link": "Salin Tautan",

+ 4 - 0
src/lib/i18n/locales/ie-GA/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Gach Doiciméad",
 	"All models deleted successfully": "Scriosadh na múnlaí go léir go rathúil",
+	"Allow Call": "",
 	"Allow Chat Controls": "Ceadaigh Rialuithe Comhrá",
 	"Allow Chat Delete": "Ceadaigh Comhrá a Scriosadh",
 	"Allow Chat Deletion": "Cead Scriosadh Comhrá",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Ceadaigh Uaslódáil Comhad",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Lig guthanna neamh-áitiúla",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Cead Comhrá Sealadach",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Ceadaigh Suíomh Úsáideora",
 	"Allow Voice Interruption in Call": "Ceadaigh Briseadh Guth i nGlao",
 	"Allowed Endpoints": "Críochphointí Ceadaithe",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Cóipeáladh URL an chomhrá roinnte chuig an ngearrthaisce!",
 	"Copied to clipboard": "Cóipeáilte go gear",
 	"Copy": "Cóipeáil",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Cóipeáil bloc cód deireanach",
 	"Copy last response": "Cóipeáil an fhreagairt",
 	"Copy Link": "Cóipeáil Nasc",

+ 4 - 0
src/lib/i18n/locales/it-IT/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Tutti i documenti",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "Consenti l'eliminazione della chat",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "URL della chat condivisa copiato negli appunti!",
 	"Copied to clipboard": "",
 	"Copy": "Copia",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Copia ultimo blocco di codice",
 	"Copy last response": "Copia ultima risposta",
 	"Copy Link": "Copia link",

+ 4 - 0
src/lib/i18n/locales/ja-JP/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "全てのドキュメント",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "チャットの削除を許可",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "ローカル以外のボイスを許可",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "一時的なチャットを許可",
+	"Allow Text to Speech": "",
 	"Allow User Location": "ユーザーロケーションの許可",
 	"Allow Voice Interruption in Call": "通話中に音声の割り込みを許可",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "共有チャットURLをクリップボードにコピーしました!",
 	"Copied to clipboard": "クリップボードにコピーしました。",
 	"Copy": "コピー",
+	"Copy Formatted Text": "",
 	"Copy last code block": "最後のコードブロックをコピー",
 	"Copy last response": "最後の応答をコピー",
 	"Copy Link": "リンクをコピー",

+ 4 - 0
src/lib/i18n/locales/ka-GE/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "ყველა დოკუმენტი",
 	"All models deleted successfully": "ყველა მოდელი წარმატებით წაიშალა",
+	"Allow Call": "",
 	"Allow Chat Controls": "ჩატის კონტროლის ელემენტების დაშვება",
 	"Allow Chat Delete": "ჩატის წაშლის დაშვება",
 	"Allow Chat Deletion": "ჩატის წაშლის დაშვება",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "ფაილის ატვირთვის დაშვება",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "არალოკალური ხმების დაშვება",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "დროებითი ჩატის დაშვება",
+	"Allow Text to Speech": "",
 	"Allow User Location": "მომხმარებლის მდებარეობის დაშვება",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "დაშვებული ბოლოწერტილები",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "გაზიარებული ჩატის ბმული დაკოპირდა ბუფერში!",
 	"Copied to clipboard": "დაკოპირდა გაცვლის ბაფერში",
 	"Copy": "კოპირება",
+	"Copy Formatted Text": "",
 	"Copy last code block": "ბოლო კოდის ბლოკის კოპირება",
 	"Copy last response": "ბოლო პასუხის კოპირება",
 	"Copy Link": "ბმულის კოპირება",

+ 4 - 0
src/lib/i18n/locales/ko-KR/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "모든 문서",
 	"All models deleted successfully": "성공적으로 모든 모델이 삭제되었습니다",
+	"Allow Call": "",
 	"Allow Chat Controls": "채팅 제어 허용",
 	"Allow Chat Delete": "채팅 삭제 허용",
 	"Allow Chat Deletion": "채팅 삭제 허용",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "파일 업로드 허용",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "외부 음성 허용",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "임시 채팅 허용",
+	"Allow Text to Speech": "",
 	"Allow User Location": "사용자 위치 활용 허용",
 	"Allow Voice Interruption in Call": "음성 기능에서 음성 방해 허용",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "채팅 공유 URL이 클립보드에 복사되었습니다!",
 	"Copied to clipboard": "클립보드에 복사되었습니다",
 	"Copy": "복사",
+	"Copy Formatted Text": "",
 	"Copy last code block": "마지막 코드 블록 복사",
 	"Copy last response": "마지막 응답 복사",
 	"Copy Link": "링크 복사",

+ 4 - 0
src/lib/i18n/locales/lt-LT/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Visi dokumentai",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "Leisti pokalbių ištrynimą",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Leisti nelokalius balsus",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Leisti naudotojo vietos matymą",
 	"Allow Voice Interruption in Call": "Leisti pertraukimą skambučio metu",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Nukopijavote pokalbio nuorodą",
 	"Copied to clipboard": "",
 	"Copy": "Kopijuoti",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Kopijuoti paskutinį kodo bloką",
 	"Copy last response": "Kopijuoti paskutinį atsakymą",
 	"Copy Link": "Kopijuoti nuorodą",

+ 4 - 0
src/lib/i18n/locales/ms-MY/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Semua Dokumen",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "Benarkan Penghapusan Perbualan",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Benarkan suara bukan tempatan ",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Benarkan Lokasi Pengguna",
 	"Allow Voice Interruption in Call": "Benarkan gangguan suara dalam panggilan",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Menyalin URL sembang kongsi ke papan klip",
 	"Copied to clipboard": "",
 	"Copy": "Salin",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Salin Blok Kod Terakhir",
 	"Copy last response": "Salin Respons Terakhir",
 	"Copy Link": "Salin Pautan",

+ 4 - 0
src/lib/i18n/locales/nb-NO/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Alle dokumenter",
 	"All models deleted successfully": "Alle modeller er slettet",
+	"Allow Call": "",
 	"Allow Chat Controls": "Tillatt chatkontroller",
 	"Allow Chat Delete": "Tillat sletting av chatter",
 	"Allow Chat Deletion": "Tillat sletting av chatter",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Tillatt opplasting av filer",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Tillat ikke-lokale stemmer",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Tillat midlertidige chatter",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Aktiver stedstjenester",
 	"Allow Voice Interruption in Call": "Muliggjør taleavbrytelse i samtaler",
 	"Allowed Endpoints": "Tillatte endepunkter",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Kopierte delt chat-URL til utklippstavlen!",
 	"Copied to clipboard": "Kopier til utklippstaveln",
 	"Copy": "Kopier",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Kopier siste kodeblokk",
 	"Copy last response": "Kopier siste svar",
 	"Copy Link": "Kopier lenke",

+ 4 - 0
src/lib/i18n/locales/nl-NL/translation.json

@@ -57,6 +57,7 @@
 	"All": "Alle",
 	"All Documents": "Alle documenten",
 	"All models deleted successfully": "Alle modellen zijn succesvol verwijderd",
+	"Allow Call": "",
 	"Allow Chat Controls": "Chatbesturing toestaan",
 	"Allow Chat Delete": "Chatverwijdering toestaan",
 	"Allow Chat Deletion": "Chatverwijdering toestaan",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Bestandenupload toestaan",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Niet-lokale stemmen toestaan",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Tijdelijke chat toestaan",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Gebruikerslocatie toestaan",
 	"Allow Voice Interruption in Call": "Stemonderbreking tijdens gesprek toestaan",
 	"Allowed Endpoints": "Endpoints toestaan",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "URL van gedeelde gesprekspagina gekopieerd naar klembord!",
 	"Copied to clipboard": "Gekopieerd naar klembord",
 	"Copy": "Kopieer",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Kopieer laatste codeblok",
 	"Copy last response": "Kopieer laatste antwoord",
 	"Copy Link": "Kopieer link",

+ 4 - 0
src/lib/i18n/locales/pa-IN/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "ਸਾਰੇ ਡਾਕੂਮੈਂਟ",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "ਗੱਲਬਾਤ ਮਿਟਾਉਣ ਦੀ ਆਗਿਆ ਦਿਓ",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "ਸਾਂਝੇ ਕੀਤੇ ਗੱਲਬਾਤ URL ਨੂੰ ਕਲਿੱਪਬੋਰਡ 'ਤੇ ਕਾਪੀ ਕਰ ਦਿੱਤਾ!",
 	"Copied to clipboard": "",
 	"Copy": "ਕਾਪੀ ਕਰੋ",
+	"Copy Formatted Text": "",
 	"Copy last code block": "ਆਖਰੀ ਕੋਡ ਬਲਾਕ ਨੂੰ ਕਾਪੀ ਕਰੋ",
 	"Copy last response": "ਆਖਰੀ ਜਵਾਬ ਨੂੰ ਕਾਪੀ ਕਰੋ",
 	"Copy Link": "ਲਿੰਕ ਕਾਪੀ ਕਰੋ",

+ 4 - 0
src/lib/i18n/locales/pl-PL/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Wszystkie dokumenty",
 	"All models deleted successfully": "Wszystkie modele zostały usunięte pomyślnie.",
+	"Allow Call": "",
 	"Allow Chat Controls": "Zezwól na dostęp do ustawień czatu",
 	"Allow Chat Delete": "Zezwól na usunięcie czatu",
 	"Allow Chat Deletion": "Zezwól na usuwanie czatu",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Pozwól na przesyłanie plików",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Pozwól na głosy spoza lokalnej społeczności",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Zezwól na tymczasową rozmowę",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Zezwól na lokalizację użytkownika",
 	"Allow Voice Interruption in Call": "Zezwól na przerwanie połączenia głosowego",
 	"Allowed Endpoints": "Dozwolone punkty końcowe",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Skopiowano udostępniony URL czatu do schowka!",
 	"Copied to clipboard": "Skopiowane do schowka",
 	"Copy": "Skopiuj",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Skopiuj ostatni fragment kodu",
 	"Copy last response": "Skopiuj ostatnią wypowiedź",
 	"Copy Link": "Skopiuj link",

+ 4 - 0
src/lib/i18n/locales/pt-BR/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Todos os Documentos",
 	"All models deleted successfully": "Todos os modelos foram excluídos com sucesso",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "Permitir Exclusão de Chats",
 	"Allow Chat Deletion": "Permitir Exclusão de Chats",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Permitir Envio de arquivos",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Permitir vozes não locais",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Permitir Conversa Temporária",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Permitir Localização do Usuário",
 	"Allow Voice Interruption in Call": "Permitir Interrupção de Voz na Chamada",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "URL de chat compartilhado copiado para a área de transferência!",
 	"Copied to clipboard": "Copiado para a área de transferência",
 	"Copy": "Copiar",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Copiar último bloco de código",
 	"Copy last response": "Copiar última resposta",
 	"Copy Link": "Copiar Link",

+ 4 - 0
src/lib/i18n/locales/pt-PT/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Todos os Documentos",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "Permitir Exclusão de Conversa",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Permitir vozes não locais",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "URL de Conversa partilhado copiada com sucesso!",
 	"Copied to clipboard": "",
 	"Copy": "Copiar",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Copiar último bloco de código",
 	"Copy last response": "Copiar última resposta",
 	"Copy Link": "Copiar link",

+ 4 - 0
src/lib/i18n/locales/ro-RO/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Toate documentele",
 	"All models deleted successfully": "Toate modelele au fost șterse cu succes",
+	"Allow Call": "",
 	"Allow Chat Controls": "Permite controalele chat-ului",
 	"Allow Chat Delete": "Permite ștergerea chat-ului",
 	"Allow Chat Deletion": "Permite ștergerea conversațiilor",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Permite încărcarea fișierelor",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Permite voci non-locale",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Permite chat temporar",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Permite localizarea utilizatorului",
 	"Allow Voice Interruption in Call": "Permite intreruperea vocii în apel",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "URL-ul conversației partajate a fost copiat în clipboard!",
 	"Copied to clipboard": "Copiat în clipboard",
 	"Copy": "Copiază",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Copiază ultimul bloc de cod",
 	"Copy last response": "Copiază ultimul răspuns",
 	"Copy Link": "Copiază Link",

+ 55 - 51
src/lib/i18n/locales/ru-RU/translation.json

@@ -57,14 +57,17 @@
 	"All": "Все",
 	"All Documents": "Все документы",
 	"All models deleted successfully": "Все модели успешно удалены",
+	"Allow Call": "",
 	"Allow Chat Controls": "Разрешить управление чатом",
 	"Allow Chat Delete": "Разрешить удаление чата",
 	"Allow Chat Deletion": "Разрешить удаление чата",
 	"Allow Chat Edit": "Разрешить редактирование чата",
 	"Allow File Upload": "Разрешить загрузку файлов",
-	"Allow Multiple Models in Chat": "",
+	"Allow Multiple Models in Chat": "Разрешить использование нескольких моделей в чате",
 	"Allow non-local voices": "Разрешить не локальные голоса",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Разрешить временные чаты",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Разрешить доступ к местоположению пользователя",
 	"Allow Voice Interruption in Call": "Разрешить прерывание голоса во время вызова",
 	"Allowed Endpoints": "Разрешенные энд-поинты",
@@ -73,10 +76,10 @@
 	"Always": "Всегда",
 	"Always Collapse Code Blocks": "Всегда сворачивать блоки кода",
 	"Always Expand Details": "Всегда разворачивать детали",
-	"Amazing": "Удивительный",
+	"Amazing": "Удивительно",
 	"an assistant": "ассистент",
 	"Analyzed": "Проанализировано",
-	"Analyzing...": "Анализирую",
+	"Analyzing...": "Анализирую...",
 	"and": "и",
 	"and {{COUNT}} more": "и еще {{COUNT}}",
 	"and create a new shared link.": "и создайте новую общую ссылку.",
@@ -154,7 +157,7 @@
 	"Change Password": "Изменить пароль",
 	"Channel Name": "Название канала",
 	"Channels": "Каналы",
-	"Character": "Персонаж",
+	"Character": "Символ",
 	"Character limit for autocomplete generation input": "Ограничение количества символов для ввода при генерации автозаполнения",
 	"Chart new frontiers": "Наметьте новые границы",
 	"Chat": "Чат",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Копирование в буфер обмена выполнено успешно!",
 	"Copied to clipboard": "Скопировано в буфер обмена",
 	"Copy": "Копировать",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Копировать последний блок кода",
 	"Copy last response": "Копировать последний ответ",
 	"Copy Link": "Копировать ссылку",
@@ -252,13 +256,13 @@
 	"Create a knowledge base": "Создайте базу знаний",
 	"Create a model": "Создание модели",
 	"Create Account": "Создать аккаунт",
-	"Create Admin Account": "Создать Аккаунт Администратора",
-	"Create Channel": "Создать Канал",
-	"Create Group": "Создать Группу",
-	"Create Knowledge": "Создать Знание",
+	"Create Admin Account": "Создать аккаунт Администратора",
+	"Create Channel": "Создать канал",
+	"Create Group": "Создать группу",
+	"Create Knowledge": "Создать знание",
 	"Create new key": "Создать новый ключ",
 	"Create new secret key": "Создать новый секретный ключ",
-	"Created at": "Создано",
+	"Created at": "Создан(а)",
 	"Created At": "Создано",
 	"Created by": "Создано",
 	"CSV Import": "Импорт CSV",
@@ -282,7 +286,7 @@
 	"Default Prompt Suggestions": "Предложения промптов по умолчанию",
 	"Default to 389 or 636 if TLS is enabled": "По умолчанию 389 или 636, если TLS включен.",
 	"Default to ALL": "По умолчанию ВСЕ",
-	"Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "",
+	"Default to segmented retrieval for focused and relevant content extraction, this is recommended for most cases.": "По умолчанию используется сегментированный поиск для целенаправленного извлечения релевантного контента, что рекомендуется в большинстве случаев.",
 	"Default User Role": "Роль пользователя по умолчанию",
 	"Delete": "Удалить",
 	"Delete a model": "Удалить модель",
@@ -304,13 +308,13 @@
 	"Deleted User": "Удалённый пользователь",
 	"Describe your knowledge base and objectives": "Опишите свою базу знаний и цели",
 	"Description": "Описание",
-	"Detect Artifacts Automatically": "",
+	"Detect Artifacts Automatically": "Автоматическое обнаружение артефактов",
 	"Didn't fully follow instructions": "Не полностью следует инструкциям",
 	"Direct": "Прямое",
 	"Direct Connections": "Прямые подключения",
 	"Direct Connections allow users to connect to their own OpenAI compatible API endpoints.": "Прямые подключения позволяют пользователям подключаться к своим собственным конечным точкам API, совместимым с OpenAI.",
 	"Direct Connections settings updated": "Настройки прямых подключений обновлены",
-	"Direct Tool Servers": "Прямые сервера инструментов",
+	"Direct Tool Servers": "Доступ к серверам инструментов",
 	"Disabled": "Отключено",
 	"Discover a function": "Найти функцию",
 	"Discover a model": "Найти модель",
@@ -318,10 +322,10 @@
 	"Discover a tool": "Найти инструмент",
 	"Discover how to use Open WebUI and seek support from the community.": "Узнайте, как использовать Open WebUI, и обратитесь за поддержкой к сообществу.",
 	"Discover wonders": "Откройте для себя чудеса",
-	"Discover, download, and explore custom functions": "Находите, загружайте и исследуйте пользовательские функции",
-	"Discover, download, and explore custom prompts": "Находите, загружайте и исследуйте пользовательские промпты",
-	"Discover, download, and explore custom tools": "Находите, загружайте и исследуйте пользовательские инструменты",
-	"Discover, download, and explore model presets": "Находите, загружайте и исследуйте пользовательские предустановки моделей",
+	"Discover, download, and explore custom functions": "Открывайте для себя, загружайте и исследуйте пользовательские функции",
+	"Discover, download, and explore custom prompts": "Открывайте для себя, загружайте и исследуйте пользовательские промпты",
+	"Discover, download, and explore custom tools": "Открывайте для себя, загружайте и исследуйте пользовательские инструменты",
+	"Discover, download, and explore model presets": "Открывайте для себя, загружайте и исследуйте пользовательские предустановки моделей",
 	"Dismissible": "Можно отклонить",
 	"Display": "Отображать",
 	"Display Emoji in Call": "Отображать эмодзи в вызовах",
@@ -360,7 +364,7 @@
 	"e.g. my_filter": "например, мой_фильтр",
 	"e.g. my_tools": "например, мой_инструмент",
 	"e.g. Tools for performing various operations": "например, инструменты для выполнения различных операций",
-	"e.g., en-US,ja-JP (leave blank for auto-detect)": "",
+	"e.g., en-US,ja-JP (leave blank for auto-detect)": "например, en-US,ja-JP (оставьте поле пустым для автоматического определения)",
 	"Edit": "Редактировать",
 	"Edit Arena Model": "Изменить модель арены",
 	"Edit Channel": "Редактировать канал",
@@ -410,8 +414,8 @@
 	"Enter Document Intelligence Key": "Введите ключ для анализа документов",
 	"Enter domains separated by commas (e.g., example.com,site.org)": "Введите домены, разделенные запятыми (например, example.com,site.org)",
 	"Enter Exa API Key": "Введите ключ API для Exa",
-	"Enter Firecrawl API Base URL": "",
-	"Enter Firecrawl API Key": "",
+	"Enter Firecrawl API Base URL": "Введите базовый URL-адрес Firecrawl API",
+	"Enter Firecrawl API Key": "Введите ключ API для Firecrawl",
 	"Enter Github Raw URL": "Введите необработанный URL-адрес Github",
 	"Enter Google PSE API Key": "Введите ключ API Google PSE",
 	"Enter Google PSE Engine Id": "Введите Id движка Google PSE",
@@ -429,8 +433,8 @@
 	"Enter Mojeek Search API Key": "Введите ключ API поиска Mojeek",
 	"Enter Number of Steps (e.g. 50)": "Введите количество шагов (например, 50)",
 	"Enter Perplexity API Key": "Введите ключ API Perplexity",
-	"Enter Playwright Timeout": "",
-	"Enter Playwright WebSocket URL": "",
+	"Enter Playwright Timeout": "Введите таймаут для Playwright",
+	"Enter Playwright WebSocket URL": "Введите URL-адрес Playwright WebSocket",
 	"Enter proxy URL (e.g. https://user:password@host:port)": "Введите URL прокси-сервера (например, https://user:password@host:port)",
 	"Enter reasoning effort": "Введите причинность рассудения",
 	"Enter Sampler (e.g. Euler a)": "Введите сэмплер (например, Euler a)",
@@ -448,13 +452,13 @@
 	"Enter server host": "Введите хост сервера",
 	"Enter server label": "Введите метку сервера",
 	"Enter server port": "Введите порт сервера",
-	"Enter Sougou Search API sID": "",
-	"Enter Sougou Search API SK": "",
+	"Enter Sougou Search API sID": "Введите Sougou Search API sID",
+	"Enter Sougou Search API SK": "Введите Sougou Search API SK",
 	"Enter stop sequence": "Введите последовательность остановки",
 	"Enter system prompt": "Введите системный промпт",
 	"Enter system prompt here": "Введите системный промпт здесь",
 	"Enter Tavily API Key": "Введите ключ API Tavily",
-	"Enter Tavily Extract Depth": "",
+	"Enter Tavily Extract Depth": "Укажите глубину извлечения Tavily",
 	"Enter the public URL of your WebUI. This URL will be used to generate links in the notifications.": "Введите общедоступный URL вашего WebUI. Этот URL будет использоваться для создания ссылок в уведомлениях.",
 	"Enter Tika Server URL": "Введите URL-адрес сервера Tika",
 	"Enter timeout in seconds": "Введите время ожидания в секундах",
@@ -535,8 +539,8 @@
 	"Filter is now globally enabled": "Фильтр теперь включен глобально",
 	"Filters": "Фильтры",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "Определение подделки отпечатка: Невозможно использовать инициалы в качестве аватара. По умолчанию используется изображение профиля по умолчанию.",
-	"Firecrawl API Base URL": "",
-	"Firecrawl API Key": "",
+	"Firecrawl API Base URL": "Базовый URL-адрес Firecrawl API",
+	"Firecrawl API Key": "Ключ API Firecrawl",
 	"Fluidly stream large external response chunks": "Плавная потоковая передача больших фрагментов внешних ответов",
 	"Focus chat input": "Фокус ввода чата",
 	"Folder deleted successfully": "Папка успешно удалена",
@@ -601,8 +605,8 @@
 	"Hybrid Search": "Гибридная поисковая система",
 	"I acknowledge that I have read and I understand the implications of my action. I am aware of the risks associated with executing arbitrary code and I have verified the trustworthiness of the source.": "Я подтверждаю, что прочитал и осознаю последствия своих действий. Я осознаю риски, связанные с выполнением произвольного кода, и я проверил достоверность источника.",
 	"ID": "",
-	"iframe Sandbox Allow Forms": "",
-	"iframe Sandbox Allow Same Origin": "",
+	"iframe Sandbox Allow Forms": "Позволять формы для iframe Sandbox",
+	"iframe Sandbox Allow Same Origin": "Позводять одно и то же происхождение для iframe Sandbox",
 	"Ignite curiosity": "Разожгите любопытство",
 	"Image": "Изображение",
 	"Image Compression": "Сжатие изображения",
@@ -652,7 +656,7 @@
 	"Key": "Ключ",
 	"Keyboard shortcuts": "Горячие клавиши",
 	"Knowledge": "Знания",
-	"Knowledge Access": "Доступ к Знаниям",
+	"Knowledge Access": "Доступ к знаниям",
 	"Knowledge created successfully.": "Знания созданы успешно.",
 	"Knowledge deleted successfully.": "Знания успешно удалены.",
 	"Knowledge Public Sharing": "Публичный обмен знаниями",
@@ -663,13 +667,13 @@
 	"Label": "Пометка",
 	"Landing Page Mode": "Режим целевой страницы",
 	"Language": "Язык",
-	"Language Locales": "",
-	"Last Active": "Последний активный",
+	"Language Locales": "Языковые особенности",
+	"Last Active": "Последняя активность",
 	"Last Modified": "Последнее изменение",
 	"Last reply": "Последний ответ",
 	"LDAP": "",
 	"LDAP server updated": "LDAP сервер обновлен",
-	"Leaderboard": "Таблица Лидеров",
+	"Leaderboard": "Таблица лидеров",
 	"Learn more about OpenAPI tool servers.": "Узнайте больше о серверах инструментов OpenAPI.",
 	"Leave empty for unlimited": "Оставьте пустым для неограниченного",
 	"Leave empty to include all models from \"{{url}}/api/tags\" endpoint": "Оставьте пустым, чтобы включить все модели из конечной точки \"{{url}}/api/tags\"",
@@ -688,7 +692,7 @@
 	"Local Models": "Локальные модели",
 	"Location access not allowed": "Доступ к местоположению запрещен",
 	"Logit Bias": "",
-	"Lost": "",
+	"Lost": "Поражение",
 	"LTR": "LTR",
 	"Made by Open WebUI Community": "Сделано сообществом OpenWebUI",
 	"Make sure to enclose them with": "Убедитесь, что они заключены в",
@@ -743,8 +747,8 @@
 	"Model updated successfully": "Модель успешно обновлена",
 	"Modelfile Content": "Содержимое файла модели",
 	"Models": "Модели",
-	"Models Access": "Доступ к Моделям",
-	"Models configuration saved successfully": "Конфигурация модели успешно сохранена.",
+	"Models Access": "Доступ к моделям",
+	"Models configuration saved successfully": "Конфигурация моделей успешно сохранена.",
 	"Models Public Sharing": "Публичный обмен моделями",
 	"Mojeek Search API Key": "Ключ API для поиска Mojeek",
 	"more": "больше",
@@ -847,7 +851,7 @@
 	"Pipelines Valves": "Вентили конвейеров",
 	"Plain text (.txt)": "Текст в формате .txt",
 	"Playground": "Песочница",
-	"Playwright Timeout (ms)": "",
+	"Playwright Timeout (ms)": "Таймаут Playwright (мс)",
 	"Playwright WebSocket URL": "",
 	"Please carefully review the following warnings:": "Пожалуйста, внимательно ознакомьтесь со следующими предупреждениями:",
 	"Please do not close the settings page while loading the model.": "Пожалуйста, не закрывайте страницу настроек во время загрузки модели.",
@@ -868,7 +872,7 @@
 	"Private": "Частное",
 	"Profile Image": "Изображение профиля",
 	"Prompt": "Промпт",
-	"Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Промпт (например, Расскажи мне интересный факт о Римской империи)",
+	"Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Промпт (напр., Расскажи мне интересный факт о Римской империи)",
 	"Prompt Autocompletion": "Автодополнение промпта",
 	"Prompt Content": "Содержание промпта",
 	"Prompt created successfully": "Промпт успешно создан",
@@ -894,11 +898,11 @@
 	"References from": "Отсылки к",
 	"Refused when it shouldn't have": "Отказано в доступе, когда это не должно было произойти",
 	"Regenerate": "Перегенерировать",
-	"Reindex": "",
-	"Reindex Knowledge Base Vectors": "",
+	"Reindex": "Переиндексировать",
+	"Reindex Knowledge Base Vectors": "Переиндексировать векторы базы знаний",
 	"Release Notes": "Примечания к выпуску",
-	"Relevance": "Актуальность",
-	"Relevance Threshold": "",
+	"Relevance": "Релевантность",
+	"Relevance Threshold": "Порог релевантности",
 	"Remove": "Удалить",
 	"Remove Model": "Удалить модель",
 	"Rename": "Переименовать",
@@ -1021,11 +1025,11 @@
 	"Show your support!": "Поддержите нас!",
 	"Showcased creativity": "Продемонстрирован творческий подход",
 	"Sign in": "Войти",
-	"Sign in to {{WEBUI_NAME}}": "Войти через {{WEBUI_NAME}}",
-	"Sign in to {{WEBUI_NAME}} with LDAP": "Войти через {{WEBUI_NAME}} по LDAP",
+	"Sign in to {{WEBUI_NAME}}": "Войти в {{WEBUI_NAME}}",
+	"Sign in to {{WEBUI_NAME}} with LDAP": "Войти в {{WEBUI_NAME}} по LDAP",
 	"Sign Out": "Выйти",
 	"Sign up": "Зарегистрироваться",
-	"Sign up to {{WEBUI_NAME}}": "Войти в {{WEBUI_NAME}}",
+	"Sign up to {{WEBUI_NAME}}": "Регистрация в {{WEBUI_NAME}}",
 	"Signing in to {{WEBUI_NAME}}": "Зарегистрироваться в {{WEBUI_NAME}}",
 	"sk-1234": "",
 	"Sougou Search API sID": "",
@@ -1039,7 +1043,7 @@
 	"Stream Chat Response": "Потоковый вывод ответа",
 	"STT Model": "Модель распознавания речи",
 	"STT Settings": "Настройки распознавания речи",
-	"Subtitle (e.g. about the Roman Empire)": "Подзаголовок (например, о Римской империи)",
+	"Subtitle (e.g. about the Roman Empire)": "Подзаголовок (напр., о Римской империи)",
 	"Success": "Успех",
 	"Successfully updated.": "Успешно обновлено.",
 	"Suggested": "Предложено",
@@ -1057,7 +1061,7 @@
 	"Tap to interrupt": "Нажмите, чтобы прервать",
 	"Tasks": "Задачи",
 	"Tavily API Key": "Ключ API Tavily",
-	"Tavily Extract Depth": "",
+	"Tavily Extract Depth": "Глубина извлечения Tavily",
 	"Tell us more:": "Пожалуйста, расскажите нам больше:",
 	"Temperature": "Температура",
 	"Template": "Шаблон",
@@ -1180,8 +1184,8 @@
 	"Use Gravatar": "Использовать Gravatar",
 	"Use groups to group your users and assign permissions.": "Используйте группы, чтобы группировать пользователей и назначать разрешения.",
 	"Use Initials": "Использовать инициалы",
-	"Use no proxy to fetch page contents.": "",
-	"Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "",
+	"Use no proxy to fetch page contents.": "Не используйте прокси-сервер для получения содержимого страницы.",
+	"Use proxy designated by http_proxy and https_proxy environment variables to fetch page contents.": "Используйте прокси-сервер, обозначенный переменными окружения http_proxy и https_proxy, для получения содержимого страницы.",
 	"use_mlock (Ollama)": "use_mlock (Ollama)",
 	"use_mmap (Ollama)": "use_mmap (Ollama)",
 	"user": "пользователь",
@@ -1199,7 +1203,7 @@
 	"variable": "переменная",
 	"variable to have them replaced with clipboard content.": "переменную, чтобы заменить их содержимым буфера обмена.",
 	"Verify Connection": "Проверить подключение",
-	"Verify SSL Certificate": "",
+	"Verify SSL Certificate": "Проверять SSL-сертификат",
 	"Version": "Версия",
 	"Version {{selectedVersion}} of {{totalVersions}}": "Версия {{selectedVersion}} из {{totalVersions}}",
 	"View Replies": "С ответами",
@@ -1214,7 +1218,7 @@
 	"Warning: Jupyter execution enables arbitrary code execution, posing severe security risks—proceed with extreme caution.": "Предупреждение: Выполнение Jupyter позволяет выполнять произвольный код, что создает серьезные угрозы безопасности — действуйте с особой осторожностью.",
 	"Web": "Веб",
 	"Web API": "Веб API",
-	"Web Loader Engine": "",
+	"Web Loader Engine": "Движок веб-загрузчика",
 	"Web Search": "Веб-поиск",
 	"Web Search Engine": "Поисковая система",
 	"Web Search in Chat": "Поисковая система в чате",
@@ -1233,7 +1237,7 @@
 	"Whisper (Local)": "Whisper (Локально)",
 	"Why?": "Почему?",
 	"Widescreen Mode": "Широкоэкранный режим",
-	"Won": "",
+	"Won": "Победа",
 	"Works together with top-k. A higher value (e.g., 0.95) will lead to more diverse text, while a lower value (e.g., 0.5) will generate more focused and conservative text.": "Работает совместно с top-k. Более высокое значение (например, 0,95) приведет к более разнообразному тексту, в то время как более низкое значение (например, 0,5) приведет к созданию более сфокусированного и консервативного текста.",
 	"Workspace": "Рабочее пространство",
 	"Workspace Permissions": "Разрешения для Рабочего пространства",

+ 4 - 0
src/lib/i18n/locales/sk-SK/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Všetky dokumenty",
 	"All models deleted successfully": "Všetky modely úspešne odstránené",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "Povoliť odstránenie chatu",
 	"Allow Chat Deletion": "Povoliť odstránenie chatu",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Povoliť nahrávanie súborov",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Povoliť ne-lokálne hlasy",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Povoliť dočasný chat",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Povoliť užívateľskú polohu",
 	"Allow Voice Interruption in Call": "Povoliť prerušenie hlasu počas hovoru",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "URL zdieľanej konverzácie skopírované do schránky!",
 	"Copied to clipboard": "Skopírované do schránky",
 	"Copy": "Kopírovať",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Skopírujte posledný blok kódu",
 	"Copy last response": "Skopírujte poslednú odpoveď",
 	"Copy Link": "Kopírovať odkaz",

+ 4 - 0
src/lib/i18n/locales/sr-RS/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Сви документи",
 	"All models deleted successfully": "Сви модели су успешно обрисани",
+	"Allow Call": "",
 	"Allow Chat Controls": "Дозволи контроле ћаскања",
 	"Allow Chat Delete": "Дозволи брисање ћаскања",
 	"Allow Chat Deletion": "Дозволи брисање ћаскања",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Дозволи отпремање датотека",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Дозволи нелокалне гласове",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Дозволи привремена ћаскања",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Дозволи корисничку локацију",
 	"Allow Voice Interruption in Call": "Дозволи прекид гласа у позиву",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Адреса дељеног ћаскања ископирана у оставу!",
 	"Copied to clipboard": "Копирано у оставу",
 	"Copy": "Копирај",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Копирај последњи блок кода",
 	"Copy last response": "Копирај последњи одговор",
 	"Copy Link": "Копирај везу",

+ 4 - 0
src/lib/i18n/locales/sv-SE/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "Alla dokument",
 	"All models deleted successfully": "Alla modeller har raderats framgångsrikt",
+	"Allow Call": "",
 	"Allow Chat Controls": "Tillåt chattkontroller",
 	"Allow Chat Delete": "Tillåt radering av chatt",
 	"Allow Chat Deletion": "Tillåt chattborttagning",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Tillåt filuppladdning",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Tillåt icke-lokala röster",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Tillåt tillfällig chatt",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Tillåt användarplats",
 	"Allow Voice Interruption in Call": "Tillåt röstavbrott under samtal",
 	"Allowed Endpoints": "Tillåtna Endpoints",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Kopierad delad chatt-URL till urklipp!",
 	"Copied to clipboard": "",
 	"Copy": "Kopiera",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Kopiera sista kodblock",
 	"Copy last response": "Kopiera sista svar",
 	"Copy Link": "Kopiera länk",

+ 4 - 0
src/lib/i18n/locales/th-TH/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "เอกสารทั้งหมด",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "อนุญาตการลบการสนทนา",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "อนุญาตเสียงที่ไม่ใช่ท้องถิ่น",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "อนุญาตตำแหน่งผู้ใช้",
 	"Allow Voice Interruption in Call": "อนุญาตการแทรกเสียงในสาย",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "คัดลอก URL แชทที่แชร์ไปยังคลิปบอร์ดแล้ว!",
 	"Copied to clipboard": "",
 	"Copy": "คัดลอก",
+	"Copy Formatted Text": "",
 	"Copy last code block": "คัดลอกบล็อกโค้ดสุดท้าย",
 	"Copy last response": "คัดลอกการตอบสนองล่าสุด",
 	"Copy Link": "คัดลอกลิงก์",

+ 4 - 0
src/lib/i18n/locales/tk-TW/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "",
+	"Allow Text to Speech": "",
 	"Allow User Location": "",
 	"Allow Voice Interruption in Call": "",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "",
 	"Copied to clipboard": "",
 	"Copy": "",
+	"Copy Formatted Text": "",
 	"Copy last code block": "",
 	"Copy last response": "",
 	"Copy Link": "",

+ 4 - 0
src/lib/i18n/locales/tr-TR/translation.json

@@ -57,6 +57,7 @@
 	"All": "Tüm",
 	"All Documents": "Tüm Belgeler",
 	"All models deleted successfully": "Tüm modeller başarıyla silindi",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "Sohbet Silmeye İzin Ver",
 	"Allow Chat Deletion": "Sohbet Silmeye İzin Ver",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Dosya Yüklemeye İzin Ver",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Yerel olmayan seslere izin verin",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Geçici Sohbetlere İzin Ver",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Kullanıcı Konumuna İzin Ver",
 	"Allow Voice Interruption in Call": "Aramada Ses Kesintisine İzin Ver",
 	"Allowed Endpoints": "İzin Verilen Uç Noktalar",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Paylaşılan sohbet URL'si panoya kopyalandı!",
 	"Copied to clipboard": "Panoya kopyalandı",
 	"Copy": "Kopyala",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Son kod bloğunu kopyala",
 	"Copy last response": "Son yanıtı kopyala",
 	"Copy Link": "Bağlantıyı Kopyala",

+ 4 - 0
src/lib/i18n/locales/uk-UA/translation.json

@@ -57,6 +57,7 @@
 	"All": "Усі",
 	"All Documents": "Усі документи",
 	"All models deleted successfully": "Усі моделі видалені успішно",
+	"Allow Call": "",
 	"Allow Chat Controls": "Дозволити керування чатом",
 	"Allow Chat Delete": "Дозволити видалення чату",
 	"Allow Chat Deletion": "Дозволити видалення чату",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Дозволити завантаження файлів",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Дозволити не локальні голоси",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Дозволити тимчасовий чат",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Доступ до місцезнаходження",
 	"Allow Voice Interruption in Call": "Дозволити переривання голосу під час виклику",
 	"Allowed Endpoints": "Дозволені кінцеві точки",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Скопійовано URL-адресу спільного чату в буфер обміну!",
 	"Copied to clipboard": "Скопійовано в буфер обміну",
 	"Copy": "Копіювати",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Копіювати останній блок коду",
 	"Copy last response": "Копіювати останню відповідь",
 	"Copy Link": "Копіювати посилання",

+ 4 - 0
src/lib/i18n/locales/ur-PK/translation.json

@@ -57,6 +57,7 @@
 	"All": "",
 	"All Documents": "تمام دستاویزات",
 	"All models deleted successfully": "",
+	"Allow Call": "",
 	"Allow Chat Controls": "",
 	"Allow Chat Delete": "",
 	"Allow Chat Deletion": "چیٹ کو حذف کرنے کی اجازت دیں",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "غیر مقامی آوازوں کی اجازت دیں",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "عارضی چیٹ کی اجازت دیں",
+	"Allow Text to Speech": "",
 	"Allow User Location": "صارف کی مقام کی اجازت دیں",
 	"Allow Voice Interruption in Call": "کال میں آواز کی مداخلت کی اجازت دیں",
 	"Allowed Endpoints": "",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "مشترکہ چیٹ یو آر ایل کلپ بورڈ میں نقل کر دیا گیا!",
 	"Copied to clipboard": "کلپ بورڈ پر نقل کر دیا گیا",
 	"Copy": "نقل کریں",
+	"Copy Formatted Text": "",
 	"Copy last code block": "آخری کوڈ بلاک نقل کریں",
 	"Copy last response": "آخری جواب کاپی کریں",
 	"Copy Link": "لنک کاپی کریں",

+ 4 - 0
src/lib/i18n/locales/vi-VN/translation.json

@@ -57,6 +57,7 @@
 	"All": "Tất cả",
 	"All Documents": "Tất cả tài liệu",
 	"All models deleted successfully": "Tất cả các mô hình đã được xóa thành công",
+	"Allow Call": "",
 	"Allow Chat Controls": "Cho phép Điều khiển Chat",
 	"Allow Chat Delete": "Cho phép Xóa Chat",
 	"Allow Chat Deletion": "Cho phép Xóa nội dung chat",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "Cho phép Tải tệp lên",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "Cho phép giọng nói không bản xứ",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "Cho phép Chat nháp",
+	"Allow Text to Speech": "",
 	"Allow User Location": "Cho phép sử dụng vị trí người dùng",
 	"Allow Voice Interruption in Call": "Cho phép gián đoạn giọng nói trong cuộc gọi",
 	"Allowed Endpoints": "Các Endpoint được phép",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "Đã sao chép link chia sẻ trò chuyện vào clipboard!",
 	"Copied to clipboard": "Đã sao chép vào clipboard",
 	"Copy": "Sao chép",
+	"Copy Formatted Text": "",
 	"Copy last code block": "Sao chép khối mã cuối cùng",
 	"Copy last response": "Sao chép phản hồi cuối cùng",
 	"Copy Link": "Sao chép link",

+ 21 - 17
src/lib/i18n/locales/zh-CN/translation.json

@@ -57,6 +57,7 @@
 	"All": "全部",
 	"All Documents": "所有文档",
 	"All models deleted successfully": "所有模型删除成功",
+	"Allow Call": "",
 	"Allow Chat Controls": "允许对话高级设置",
 	"Allow Chat Delete": "允许删除对话记录",
 	"Allow Chat Deletion": "允许删除对话记录",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "允许上传文件",
 	"Allow Multiple Models in Chat": "",
 	"Allow non-local voices": "允许调用非本地音色",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "允许临时对话",
+	"Allow Text to Speech": "",
 	"Allow User Location": "允许获取您的位置",
 	"Allow Voice Interruption in Call": "允许通话中的打断语音",
 	"Allowed Endpoints": "允许的端点",
@@ -81,7 +84,7 @@
 	"and {{COUNT}} more": "还有 {{COUNT}} 个",
 	"and create a new shared link.": "并创建一个新的分享链接。",
 	"Android": "",
-	"API Base URL": "API 基础地址",
+	"API Base URL": "API 请求地址",
 	"API Key": "API 密钥",
 	"API Key created.": "API 密钥已创建。",
 	"API Key Endpoint Restrictions": "API 密钥端点限制",
@@ -120,8 +123,8 @@
 	"Autocomplete Generation Input Max Length": "输入框内容自动补全输入最大长度",
 	"Automatic1111": "Automatic1111",
 	"AUTOMATIC1111 Api Auth String": "AUTOMATIC1111 Api 鉴权字符串",
-	"AUTOMATIC1111 Base URL": "AUTOMATIC1111 基础地址",
-	"AUTOMATIC1111 Base URL is required.": "需要 AUTOMATIC1111 基础地址。",
+	"AUTOMATIC1111 Base URL": "AUTOMATIC1111 请求地址",
+	"AUTOMATIC1111 Base URL is required.": "需要 AUTOMATIC1111 请求地址。",
 	"Available list": "可用列表",
 	"Available Tools": "可用工具",
 	"available!": "版本可用!",
@@ -207,8 +210,8 @@
 	"Color": "颜色",
 	"ComfyUI": "ComfyUI",
 	"ComfyUI API Key": "ComfyUI API 密钥",
-	"ComfyUI Base URL": "ComfyUI 基础地址",
-	"ComfyUI Base URL is required.": "ComfyUI 基础地址为必需填写。",
+	"ComfyUI Base URL": "ComfyUI 请求地址",
+	"ComfyUI Base URL is required.": "ComfyUI 请求地址为必需填写。",
 	"ComfyUI Workflow": "ComfyUI 工作流",
 	"ComfyUI Workflow Nodes": "ComfyUI 工作流节点",
 	"Command": "命令",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "已复制此对话分享链接至剪贴板!",
 	"Copied to clipboard": "已复制到剪贴板",
 	"Copy": "复制",
+	"Copy Formatted Text": "",
 	"Copy last code block": "复制最后一个代码块中的代码",
 	"Copy last response": "复制最后一次回复内容",
 	"Copy Link": "复制链接",
@@ -408,10 +412,10 @@
 	"Enter Docling Server URL": "输入 Docling 服务器 URL",
 	"Enter Document Intelligence Endpoint": "输入 Document Intelligence 端点",
 	"Enter Document Intelligence Key": "输入 Document Intelligence 密钥",
-	"Enter domains separated by commas (e.g., example.com,site.org)": "输入以逗号分隔的域名(例如:example.comsite.org)",
+	"Enter domains separated by commas (e.g., example.com,site.org)": "输入以逗号分隔的域名(例如:example.com,site.org)",
 	"Enter Exa API Key": "输入 Exa API 密钥",
-	"Enter Firecrawl API Base URL": "",
-	"Enter Firecrawl API Key": "",
+	"Enter Firecrawl API Base URL": "输入 Firecrawl API 请求地址",
+	"Enter Firecrawl API Key": "输入 Firecrawl API 密钥",
 	"Enter Github Raw URL": "输入 Github Raw 地址",
 	"Enter Google PSE API Key": "输入 Google PSE API 密钥",
 	"Enter Google PSE Engine Id": "输入 Google PSE 引擎 ID",
@@ -429,8 +433,8 @@
 	"Enter Mojeek Search API Key": "输入 Mojeek Search API 密钥",
 	"Enter Number of Steps (e.g. 50)": "输入步骤数 (Steps) (例如:50)",
 	"Enter Perplexity API Key": "输入 Perplexity API 密钥",
-	"Enter Playwright Timeout": "",
-	"Enter Playwright WebSocket URL": "",
+	"Enter Playwright Timeout": "输入 Playwright 超时时间",
+	"Enter Playwright WebSocket URL": "输入 Playwright WebSocket URL",
 	"Enter proxy URL (e.g. https://user:password@host:port)": "输入代理 URL (例如:https://用户名:密码@主机名:端口)",
 	"Enter reasoning effort": "设置推理努力",
 	"Enter Sampler (e.g. Euler a)": "输入 Sampler (例如:Euler a)",
@@ -454,7 +458,7 @@
 	"Enter system prompt": "输入系统提示词 (Prompt)",
 	"Enter system prompt here": "在这里输入系统提示词 (Prompt)",
 	"Enter Tavily API Key": "输入 Tavily API 密钥",
-	"Enter Tavily Extract Depth": "",
+	"Enter Tavily Extract Depth": "输入 Tavily 提取深度",
 	"Enter the public URL of your WebUI. This URL will be used to generate links in the notifications.": "输入 WebUI 的公共 URL。此 URL 将用于在通知中生成链接。",
 	"Enter Tika Server URL": "输入 Tika 服务器地址",
 	"Enter timeout in seconds": "输入以秒为单位的超时时间",
@@ -535,8 +539,8 @@
 	"Filter is now globally enabled": "过滤器已全局启用",
 	"Filters": "过滤器",
 	"Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "检测到指纹伪造:无法使用姓名缩写作为头像。默认使用默认个人形象。",
-	"Firecrawl API Base URL": "",
-	"Firecrawl API Key": "",
+	"Firecrawl API Base URL": "Firecrawl API 请求地址",
+	"Firecrawl API Key": "Firecrawl API 密钥",
 	"Fluidly stream large external response chunks": "流畅地传输外部大型响应块数据",
 	"Focus chat input": "聚焦对话输入",
 	"Folder deleted successfully": "分组删除成功",
@@ -847,8 +851,8 @@
 	"Pipelines Valves": "Pipeline 值",
 	"Plain text (.txt)": "TXT 文档 (.txt)",
 	"Playground": "AI 对话游乐场",
-	"Playwright Timeout (ms)": "",
-	"Playwright WebSocket URL": "",
+	"Playwright Timeout (ms)": "Playwright 超时时间 (ms)",
+	"Playwright WebSocket URL": "Playwright WebSocket URL",
 	"Please carefully review the following warnings:": "请仔细阅读以下警告信息:",
 	"Please do not close the settings page while loading the model.": "加载模型时请不要关闭设置页面。",
 	"Please enter a prompt": "请输入一个 Prompt",
@@ -1057,7 +1061,7 @@
 	"Tap to interrupt": "点击以中断",
 	"Tasks": "任务",
 	"Tavily API Key": "Tavily API 密钥",
-	"Tavily Extract Depth": "",
+	"Tavily Extract Depth": "Tavily 提取深度",
 	"Tell us more:": "请告诉我们更多细节",
 	"Temperature": "温度 (Temperature)",
 	"Template": "模板",
@@ -1214,7 +1218,7 @@
 	"Warning: Jupyter execution enables arbitrary code execution, posing severe security risks—proceed with extreme caution.": "警告:Jupyter 执行允许任意代码执行,存在严重的安全风险——请极其谨慎地操作。",
 	"Web": "网页",
 	"Web API": "网页 API",
-	"Web Loader Engine": "",
+	"Web Loader Engine": "网页加载引擎",
 	"Web Search": "联网搜索",
 	"Web Search Engine": "联网搜索引擎",
 	"Web Search in Chat": "聊天中的网页搜索",

+ 4 - 0
src/lib/i18n/locales/zh-TW/translation.json

@@ -57,6 +57,7 @@
 	"All": "全部",
 	"All Documents": "所有文件",
 	"All models deleted successfully": "成功刪除所有模型",
+	"Allow Call": "",
 	"Allow Chat Controls": "允許控制對話",
 	"Allow Chat Delete": "允許刪除對話",
 	"Allow Chat Deletion": "允許刪除對話紀錄",
@@ -64,7 +65,9 @@
 	"Allow File Upload": "允許上傳檔案",
 	"Allow Multiple Models in Chat": "允許在聊天中使用多個模型",
 	"Allow non-local voices": "允許非本機語音",
+	"Allow Speech to Text": "",
 	"Allow Temporary Chat": "允許暫時對話",
+	"Allow Text to Speech": "",
 	"Allow User Location": "允許使用者位置",
 	"Allow Voice Interruption in Call": "允許在通話中打斷語音",
 	"Allowed Endpoints": "允許的端點",
@@ -242,6 +245,7 @@
 	"Copied shared chat URL to clipboard!": "已複製共用對話 URL 到剪貼簿!",
 	"Copied to clipboard": "已複製到剪貼簿",
 	"Copy": "複製",
+	"Copy Formatted Text": "",
 	"Copy last code block": "複製最後一個程式碼區塊",
 	"Copy last response": "複製最後一個回應",
 	"Copy Link": "複製連結",

+ 120 - 32
src/lib/utils/index.ts

@@ -15,6 +15,11 @@ dayjs.extend(localizedFormat);
 import { WEBUI_BASE_URL } from '$lib/constants';
 import { TTS_RESPONSE_SPLIT } from '$lib/types';
 
+import { marked } from 'marked';
+import markedExtension from '$lib/utils/marked/extension';
+import markedKatexExtension from '$lib/utils/marked/katex-extension';
+import hljs from 'highlight.js';
+
 //////////////////////////
 // Helper functions
 //////////////////////////
@@ -309,46 +314,129 @@ export const formatDate = (inputDate) => {
 	}
 };
 
-export const copyToClipboard = async (text) => {
-	let result = false;
-	if (!navigator.clipboard) {
-		const textArea = document.createElement('textarea');
-		textArea.value = text;
-
-		// Avoid scrolling to bottom
-		textArea.style.top = '0';
-		textArea.style.left = '0';
-		textArea.style.position = 'fixed';
+export const copyToClipboard = async (text, formatted = false) => {
+	if (formatted) {
+		const options = {
+			throwOnError: false,
+			highlight: function (code, lang) {
+				const language = hljs.getLanguage(lang) ? lang : 'plaintext';
+				return hljs.highlight(code, { language }).value;
+			}
+		};
+		marked.use(markedKatexExtension(options));
+		marked.use(markedExtension(options));
+
+		const htmlContent = marked.parse(text);
+
+		// Add basic styling to make the content look better when pasted
+		const styledHtml = `
+			<div>
+				<style>
+					pre {
+						background-color: #f6f8fa;
+						border-radius: 6px;
+						padding: 16px;
+						overflow: auto;
+					}
+					code {
+						font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
+						font-size: 14px;
+					}
+					.hljs-keyword { color: #d73a49; }
+					.hljs-string { color: #032f62; }
+					.hljs-comment { color: #6a737d; }
+					.hljs-function { color: #6f42c1; }
+					.hljs-number { color: #005cc5; }
+					.hljs-operator { color: #d73a49; }
+					.hljs-class { color: #6f42c1; }
+					.hljs-title { color: #6f42c1; }
+					.hljs-params { color: #24292e; }
+					.hljs-built_in { color: #005cc5; }
+					blockquote {
+						border-left: 4px solid #dfe2e5;
+						padding-left: 16px;
+						color: #6a737d;
+						margin-left: 0;
+						margin-right: 0;
+					}
+					table {
+						border-collapse: collapse;
+						width: 100%;
+						margin-bottom: 16px;
+					}
+					table, th, td {
+						border: 1px solid #dfe2e5;
+					}
+					th, td {
+						padding: 8px 12px;
+					}
+					th {
+						background-color: #f6f8fa;
+					}
+				</style>
+				${htmlContent}
+			</div>
+		`;
 
-		document.body.appendChild(textArea);
-		textArea.focus();
-		textArea.select();
+		// Create a blob with HTML content
+		const blob = new Blob([styledHtml], { type: 'text/html' });
 
 		try {
-			const successful = document.execCommand('copy');
-			const msg = successful ? 'successful' : 'unsuccessful';
-			console.log('Fallback: Copying text command was ' + msg);
-			result = true;
+			// Create a ClipboardItem with HTML content
+			const data = new ClipboardItem({
+				'text/html': blob,
+				'text/plain': new Blob([text], { type: 'text/plain' })
+			});
+
+			// Write to clipboard
+			await navigator.clipboard.write([data]);
+			return true;
 		} catch (err) {
-			console.error('Fallback: Oops, unable to copy', err);
+			console.error('Error copying formatted content:', err);
+			// Fallback to plain text
+			return await copyToClipboard(text);
 		}
+	} else {
+		let result = false;
+		if (!navigator.clipboard) {
+			const textArea = document.createElement('textarea');
+			textArea.value = text;
+
+			// Avoid scrolling to bottom
+			textArea.style.top = '0';
+			textArea.style.left = '0';
+			textArea.style.position = 'fixed';
+
+			document.body.appendChild(textArea);
+			textArea.focus();
+			textArea.select();
+
+			try {
+				const successful = document.execCommand('copy');
+				const msg = successful ? 'successful' : 'unsuccessful';
+				console.log('Fallback: Copying text command was ' + msg);
+				result = true;
+			} catch (err) {
+				console.error('Fallback: Oops, unable to copy', err);
+			}
 
-		document.body.removeChild(textArea);
-		return result;
-	}
+			document.body.removeChild(textArea);
+			return result;
+		}
 
-	result = await navigator.clipboard
-		.writeText(text)
-		.then(() => {
-			console.log('Async: Copying to clipboard was successful!');
-			return true;
-		})
-		.catch((error) => {
-			console.error('Async: Could not copy text: ', error);
-			return false;
-		});
+		result = await navigator.clipboard
+			.writeText(text)
+			.then(() => {
+				console.log('Async: Copying to clipboard was successful!');
+				return true;
+			})
+			.catch((error) => {
+				console.error('Async: Could not copy text: ', error);
+				return false;
+			});
 
-	return result;
+		return result;
+	}
 };
 
 export const compareVersion = (latest, current) => {

Some files were not shown because too many files changed in this diff